本文作者:小黑黑

[设计模式]行为型模式之命令模式

小黑黑 1年前 ( 2019-03-03 ) 619 抢沙发
[设计模式]行为型模式之命令模式摘要: 一、引言        今天学习的是【行为型】设计模式中的命令模式,首先来看看什么是命令呢,举一个生...

一、引言

        今天学习的是【行为型】设计模式中的命令模式,首先来看看什么是命令呢,举一个生活中的例子:现在我们又很多的智能家居,它们都由同一个控制器控制,比如,控制开关灯,窗帘,电视等。每一个按钮(相当于一个命令)都对应一个电器的功能,但是控制器1按钮,对应的功能不一定是电视开关功能,也可能是开关电灯的功能,或者其他,也就是说,我们的控制器按钮,可以绑定任意的具体电器功能,所以我们定义一个接口,以便控制器能够自由更换绑定功能。

二、动机

        在软件构建过程中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合--比如需要对行为进行“记录、撤销、重做、事物”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”和“行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

三、意图

        将一个请求封装为一个对象,从未使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。    --《设计模式》 GoF

四、结构图

123.PNG

4.1  模式的组成

        1、命令角色(Command):声明了一个给所有具体命令类实现的抽象接口。

        2、具体命令角色(ConcreteCommand):定义了一个接受者和行为的弱耦合,负责调用接受者的相应方法。

        3、接受者角色(Receiver):真正执行命令的对象。任何类都可能成为一个接受者,只要它能够实现命令要求实现的相应功能。

        4、请求者角色(Invoker):负责调用命令对象执行命令。

        5、客户端(Client):发出一个具体的命令并确定其接受者。

五、命令模式的具体实现

        下面我们将以读取和写入文档的例子,来看看命令模式的具体实现:

    /// <summary>
    /// 命令接收者
    /// </summary>
    public class Receiver
    {

        public void Read()
        {
            Console.WriteLine("读取文档内容");
        }

        public void Write()
        {
            Console.WriteLine("写入文档内容");
        }
    }
    
    /// <summary>
    /// 命令抽象类
    /// </summary>
    public abstract class BaseCommand
    {
        /// <summary>
        /// 命令接收者,这里也可以对命令接收者进行抽象
        /// </summary>
        protected Receiver _receiver;

        /// <summary>
        /// 设置命令接收者
        /// </summary>
        /// <param name="receiver"></param>
        public void Set(Receiver receiver)
        {
            this._receiver = receiver;
        }

        /// <summary>
        /// 命令执行方法
        /// </summary>
        public abstract void Action();
    }
    
    /// <summary>
    /// 读取文档命令,具体命令角色
    /// </summary>
    public class ReadCommand : BaseCommand
    {
        public override void Action()
        {
            this._receiver.Read();
        }
    }
    
    /// <summary>
    /// 读取文档命令,具体命令角色
    /// </summary>
    public class WriteCommand : BaseCommand
    {
        public override void Action()
        {
            this._receiver.Write();
        }
    }
    
    /// <summary>
    /// 负责调用命令对象执行请求
    /// </summary>
    public class Invoke
    {
        private BaseCommand _command;

        public Invoke(BaseCommand command)
        {
            this._command = command;
        }

        /// <summary>
        /// 执行请求
        /// </summary>
        public void ExecuteCommand()
        {
            _command.Action();
        }
    }
  
    class Program
    {
        static void Main(string[] args)
        {
            //读取配置文件
            var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");

            while (true)
            {
                Console.WriteLine("请输入命令");

                //接受用户输入的命令
                string commandStr = Console.ReadLine();

                string typeName = builder.Build()[commandStr];

                if (string.IsNullOrEmpty(typeName))
                {
                    Console.WriteLine("无效的命令");
                }
                else
                {

                    Assembly assembly = Assembly.GetExecutingAssembly();

                    //创建命令接收者
                    Receiver receiver = new Receiver();
                    //根据用户输入的命令利用反射生成具体的命令角色
                    BaseCommand command = (BaseCommand)assembly.CreateInstance(typeName);
                    command.Set(receiver);

                    Invoke invoke = new Invoke(command);
                    invoke.ExecuteCommand();
                }
            }

        }
    }
    
  //配置文件,根据用户传入的命令,用于生成响应的具体命令角色

  {
    "r": "CommandPattern.Command.ReadCommand",
    "w": "CommandPattern.Command.WriteCommand"
  }

5.1  命令的分析

        命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分隔开。

        1、每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。

        2、命令模式允许请求的一方和接受的一方独立开,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎样被接受的,以及操作是否被执行,何时被执行,以及是怎么被执行的。

        3、命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。

        4、命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。

六、命令模式的优缺点

优点:

        1、降低了系统的耦合度。

        2、新的命令可以很容易地加入到系统中。

        3、可以比较容易地设计一个命令队列和宏命令。

        4、可以方便地实现队请求的Undo和Redo。

缺点:

        1、使用命令模式可能会导致某些系统有过多的具体命令类,因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

分享到: 网站分享代码

发表评论

快捷回复:

评论列表 (暂无评论,619人围观)参与讨论

还没有评论,来说两句吧...