zoukankan      html  css  js  c++  java
  • 命令模式

      -

    一、引言

    在软件系统中,往往“行为请求者”和“行为实现者”通常呈现一种紧耦合。比如对行为进行“记录、撤销”等处理,命令模式就是提供一种封装将两者进行解耦。
    命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。[GOF 《设计模式》]

    • 结构图
      Command模式结构图
      从命令模式的结构图可以看出,它涉及到五个角色,它们分别是:

    客户角色:发出一个具体的命令并确定其接受者。
    命令角色:声明了一个给所有具体命令类实现的抽象接口
    具体命令角色:定义了一个接受者和行为的弱耦合,负责调用接受者的相应方法。
    请求者角色:负责调用命令对象执行命令。
    接受者角色:负责具体行为的执行。

    • 情景模拟
      用餐时的账单是Command模式的一个例子。服务员接受顾客的点单,把它记在账单上封装。这个点单被排队等待烹饪。注意这里的”账单”是不依赖于菜单的,它可以被不同的顾客使用,因此它可以添入不同的点单项目。
      命令模式执行
      客户:命令发出者,知道具体命令、接受者和传送命令的调用者
      传送命令的调用者:负责调用调用命令对象,生成具体命令。
      接受者:执行具体命令
    • -

    二、程序设计

    • 1、原本设计

    Command模式它封装的是命令,把命令发出者的责任和命令执行者的责任分开。我们知道,一个类是一组操作和相应的一些变量的集合,现在有这样一个类Log,如下:
    日志类
    我们常用的调用是:

    class Program
    
    {
        static void Main(string[] args)
    
        {
            Log doc = new Log();
    
            doc.OpenFile();
    
            doc.WriteMessage();
        }
    }

    这里是直接操作了Log对象的命令,加入对Log功能扩展的话,就需要修改该代码。
    第一步:命令模式将指令升华为类,抽象为一个对象,即对命令对象进行抽象。然后将调用方传入即可。
    第二步:将命令的产生生成订单(抽象工厂样子),这样讲客户将执行者解耦。

    • 2、程序改进
      为了实现调用者和执行者之间的解耦,我们将指令上升到对象层面,所以生成两个指令类,继承自一个抽象类,然后用一个简单工厂生成指令,调用这个工厂类,即可。
      命令模式
      代码为:
    //运用抽象类,避免子类传入Log参数
    public abstract class Command
    {
       //保护类型,只能子类访问
        protected Log _log;
        public Command(Log log)
        {
            _log = log;
        }
        //抽象函数,由子类实现
        public abstract void Excute();
    
    }
    
    public class FileCommand : Command
    {
        public FileCommand(Log log)
            : base(log)
        { }
    
        //执行指令
        public override void Excute()
        {
            _log.OpenFIle();
        }
    
    }
    
    
    public class MessageCommand : Command
    {
        public MessageCommand(Log log):base(log)
        {
    
        }
    
        public override void Excute()
        {
            //关键是传入参数
            _log.WriteMessage();
        }
    
    }
    
    
    public class Log
    {
        public Log()
        {
        }
        public virtual void OpenFIle()
        {
            throw new System.NotImplementedException();
        }
    
        public virtual void WriteMessage()
        {
            throw new System.NotImplementedException();
        }
    
    }
    
    public class CommandFactory
    {
        Command _file;
        Command _meg;
        public virtual void Openfile()
        {
            _file.Excute();
        }
    
        public virtual void Writemeg()
        {
            throw new System.NotImplementedException();
        }
    
        public CommandFactory(Command file, Command meg)
        {
        }
    
    }
    
    public class Client
    {
        //从构成图上,明确依赖于Log和CommandFactory
        public static void main()
        {
            Log log = new Log();
            Command _file = new FileCommand(log);
            Command _meg = new MessageCommand(log);
            CommandFactory _excute = new CommandFactory(_file, _meg);
            _excute.Openfile();
            _excute.Writemeg();
        }
    
    
    }
    -
    View Code

    三、综述

    1.Command模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的实现手段是“将行为抽象为对象”。
    2.实现Command接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息。
    3.通过使用Compmosite模式,可以将多个命令封装为一个“复合命令”MacroCommand。
    4.Command模式与C#中的Delegate有些类似。但两者定义行为接口的规范有所区别:Command以面向对象中的“接口-实现”来定义行为接口规范,更严格,更符合抽象原则;Delegate以函数签名来定义行为接口规范,更灵活,但抽象能力比较弱。
    5.使用命令模式会导致某些系统有过多的具体命令类。某些系统可能需要几十个,几百个甚至几千个具体命令类,这会使命令模式在这样的系统里变得不实际。
    适用性
    在下面的情况下应当考虑使用命令模式:
    1.使用命令模式作为”CallBack”在面向对象系统中的替代。”CallBack”讲的便是先将一个函数登记上,然后在以后调用此函数。
    2.需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也可以在网络的另外一个地址。命令对象可以在串形化之后传送到另外一台机器上去。
    3.系统需要支持命令的撤消(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供redo()方法,以供客户端在需要时,再重新实施命令效果。
    4.如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用Execute()方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。
    总结
    Command模式是非常简单而又优雅的一种设计模式,它的根本目的在于将“行为请求者”与“行为实现者”解耦。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    jQuery EasyUI API 中文文档 可调整尺寸
    jQuery EasyUI API 中文文档 链接按钮(LinkButton)
    jQuery EasyUI API 中文文档 手风琴(Accordion)
    jQuery EasyUI API 中文文档 表单(Form)
    jQuery EasyUI API 中文文档 组合(Combo)
    jQuery EasyUI API 中文文档 布局(Layout)
    jQuery EasyUI API 中文文档 拆分按钮(SplitButton)
    jQuery EasyUI API 中文文档 菜单按钮(MenuButton)
    jQuery EasyUI API 中文文档 搜索框
    jQuery EasyUI API 中文文档 验证框(ValidateBox)
  • 原文地址:https://www.cnblogs.com/polly333/p/4705675.html
Copyright © 2011-2022 走看看