设计模式 - 命令模式

一. 简述

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

属于行为型模式


二. 组成

  • Command:定义命令的接口,声明执行的方法。
  • ConcreteCommand:命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • Receiver(Barbecuer类):接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
  • Invoker(Waiter类):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
  • Client:创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

三. UML类图


四. 基本代码

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
      
    namespace CommandExample  
    {  
        /*烤肉串者类*/  
        public class Barbecuer  
        {  
            //烤羊肉  
            public void BakeMutton()  
            {  
                Console.WriteLine("烤羊肉串...");  
            }  
            //烤鸡翅  
            public void BackChickenWing()  
            {  
                Console.WriteLine("烤鸡翅...");  
            }  
        }  
      
        /*抽象命令*/  
        public abstract class Command  
        {  
            protected Barbecuer receiver;  
      
            public Command(Barbecuer receiver)//抽象命令类,只需要确定“烤肉串者”是谁  
            {  
                this.receiver = receiver;  
            }  
      
            //执行命令  
            public abstract 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()  
            {  
                this.receiver.BackChickenWing(); 
            }  
        }  
      
        /*服务员*/  
        public class Waiter  
        {  
            private IList<Command> orders = new List<Command>();  
      
            //设置订单  
            public void SetOrder(Command command)  
            {  
                if (command.ToString() == "CommandExample.BackChickenWingCommand")  
                {  
                    Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤...");  
                }  
                else  
                {  
                    orders.Add(command);  
                    Console.WriteLine("增加订单:"+ command.ToString()+"时间:"+DateTime.Now.ToString());  
                }  
            }  
      
            //取消订单  
            public void CancelOrder(Command command)  
            {  
                orders.Remove(command);  
                Console.WriteLine("取消订单:" + command.ToString() + "时间:" + DateTime.Now.ToString());  
            }  
      
            //通知全部执行  
            public void Notify()  
            {  
                foreach (Command c in orders)  
                {  
                    c.ExcuteCommand();  
                }  
            }  
        }  
    }  


// 客户端调用
namespace CommandExample  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            //开店前的准备  
            Barbecuer boy = new Barbecuer();  
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);  
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);  
            Command bakeChickenCommand1 = new BackChickenWingCommand(boy);  
  
            Waiter girl = new Waiter();  
  
            //开门营业 顾客点菜  
            girl.SetOrder(bakeMuttonCommand1);  
            girl.SetOrder(bakeMuttonCommand2);  
            girl.SetOrder(bakeChickenCommand1);  
  
            //订单下好后,一次性通知厨房  
            girl.Notify();  
  
            Console.Read();  
        }  
    }  
}  

五. 优缺点

优点:

  1. 命令模式能较容易的设计一个命令队列;
  2. 在需要的情况下,可以较容易的将命令记入日志;
  3. 允许接收请求的一方决定是否要否决该请求;
  4. 可以容易的实现对请求的撤销和重构;
  5. 由于加入新的具体命令类不影响其它的类,因此增加新的具体命令很容易;
  6. 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。


六. 应用场景

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  2. 系统需要在不同的时间指定请求、将请求排队和执行请求。
  3. 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
  4. 系统需要将一组操作组合在一起,即支持宏命令。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值