设计模式--命令模式

概念
将一个请求封装为一个对象,从而使得你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。


结构图

设计模式--命令模式


角色说明

  • Client
    这个就是我们的客户大大了
    发布命令者

  • Invoker
    调用者
    要求该命令执行这个请求(也就是接收命令并执行命令)

  • Command
    声明执行操作的接口
    需要执行的命令在此声明

  • ConcreteCommand
    将一个接收者对象绑定一个工作,调用接收者相应的操作,实现execute

  • Receiver
    接收者,实际做工的角色,我们的命令的执行是由这个角色去做的。


实现

  • Command
abstract  class Command
    {
        protected Receiver receiver;

        public Command(Receiver receiver)
        {
            this.receiver = receiver;
        }

        abstract public void Execute();

    }
  • ConcreteCommnad
 class ConcreteCommnad : Command
    {
        public ConcreteCommnad(Receiver receiver ):base(receiver)
        { }
        public override void Execute()
        {
            receiver.Action();
        }
    }
  • Invoker
class Invoker
    {
        private Command command;

        public void Setcommand(Command command)
        {
            this.command = command;
        }

        public void ExecuteCommand()
        {
            command.Execute();
        }
  • Receiver
class Receiver
    {
        public void Action()
        {
            Console.WriteLine("执行请求!");
        }

    }
  • 客户端
static void Main(string[] args)
        {
            Receiver r = new Receiver();
            Command c = new ConcreteCommnad(r);
            Invoker i = new Invoker();
            i.Setcommand(c);
            i.ExecuteCommand ();

            Console.Read();


        }

优点

  • 解除类之间的耦合

  • 可扩展性好

  • 命令模式与其他模式相结合使用更加nice

  • 比较容易设计一个命令队列

  • 比较容易将命令计入日志

  • 允许接收请求的一方决定是否否决请求

  • 可以容易的实现对请求的撤销和重做

  • 增加新的具体的命令类很容易

如何解除类之间的耦合
例子:
前景描述:
路边单人经营的烧烤店和有服务员的烧烤店

  • 单人经营的烧烤店:

烤:

public  class Barbecuer
    {
        //烤肉串
        public void BakeMutton()
        {
            Console.WriteLine("烤肉串");

        }

        public void BackChickwing()
        {
            Console.WriteLine("烤鸡翅");
        }

    }

客户要求:

static void Main(string[] args)
        {
            Barbecuer boy = new Barbecuer();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BakeMutton();
            boy.BackChickwing();

            Console.Read();

        }

问题描述:
我们可以发现,客户提出要求和摊主烤肉是 直接通信的关系,那么摊主的职责就比较大啦,他要记住客户分别都要了多少串,还要负责算账,如果其中一个客户要增加或减少串对于摊主来说任务就比较大,容易混淆,且目前的状况是客户与摊主直接沟通,现在两个类是紧耦合的状态。

  • 进入服务员

结构图:
设计模式--命令模式

抽象命令类:

  • 客户端
  static void Main(string[] args)
        {
            //前提装备
            Barbecuer boy = new Barbecuer();//烤肉者就位

            //烤肉串和烤鸡翅的命令由烤肉工作者具体来做,所以(boy)其实是指明了接收者
            //指明接收者的动作
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
            Command bakeChickenwingCommand = new BackChickenwingCommand(boy);

            Waiter girl = new Waiter();

            //营业
            girl.SetOrder(bakeMuttonCommand1);
            girl.Notify();
            girl.SetOrder(bakeMuttonCommand2);
            girl.Notify();
            girl.SetOrder(bakeChickenwingCommand);

            girl.Notify();
          

            Console.Read();



        }
  • 命令类
public abstract class Command
    {
        //抽象命令
        protected Barbecuer receiver;
        public Command (Barbecuer receiver)
        {
            this.receiver = receiver;
        }

        //执行命令

        abstract public void ExcuteCommand();
    }
  • 具体命令
    class BakeMuttonCommand : Command //烤肉串
    {
        public BakeMuttonCommand(Barbecuer receiver):base(receiver)
        {

        }

        public override void ExcuteCommand()
        {
           receiver.BakeMutton ();
        }
    }

    class BackChickenwingCommand : Command
    {

        public BackChickenwingCommand(Barbecuer receiver) : base(receiver)
        { }

        public override void ExcuteCommand()
        {
           receiver.BackChickwing ();
        }

    }
  • 服务员类
 public class Waiter
        {


        private Command command;

            //设置订单
            public void SetOrder(Command command)
        {
            this.command = command;
        }


        
            public void Notify()
            {
              command.ExcuteCommand ();
            }
        }

可以发现有了 服务员后客人的命令不再直接传给烤肉人员, 而是由服务人员去传递。这样就避免的紧耦合