分享

【C#设计模式-命令模式】

 鸿枫nh 2017-02-21

一.定义: 命令模式是将一类对象的功能操作进行抽象,一般来说,这些对象有相同的方法,所以这类对象有着类似的操作,我们通过抽象,就可以定义出一个命令对象,通过这样的方式,用户程序在使用的时候,只与该命令对象打交道,而不用与一类对象打交道,降低了耦合性,提高了程序设计的灵活性。

二.实现:引入生活中的例子,在执行一次考始终,考试办公室发起考试给监控员,监控员发卷学生开始考试,考试办公室通知传达手卷到监控员老师,要求学生停止考试手卷,使用命令模式进行编码如下:

[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 命令最后的执行者  
  3. /// </summary>  
  4. public class OrderReceiver  
  5. {  
  6.     public void GetExam()  
  7.     {  
  8.         Console.WriteLine("进行期中考试!");  
  9.     }  
  10.   
  11.     public void GetPaper()  
  12.     {  
  13.         Console.WriteLine("交卷!");  
  14.     }  
  15. }  
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 传递命令者的抽象类  
  3. /// </summary>  
  4. public abstract class Command  
  5. {  
  6.     /// <summary>  
  7.     /// 命令执行者  
  8.     /// </summary>  
  9.     protected OrderReceiver recediver;  
  10.   
  11.     public Command(OrderReceiver recediver)  
  12.     {  
  13.         this.recediver = recediver;  
  14.     }  
  15.   
  16.     /// <summary>  
  17.     /// 执行命令的方法  
  18.     /// </summary>  
  19.     public abstract void Action();  
  20. }  
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 执行考试命令传递者  
  3. /// </summary>  
  4. public class examcmd:Command  
  5. {  
  6.     public examcmd(OrderReceiver recetive) : base(recetive) { }  
  7.   
  8.     public override void Action()  
  9.     {  
  10.         this.recediver.GetExam();  
  11.     }  
  12. }  
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 执行交卷命令传递者  
  3. /// </summary>  
  4. public class papercmd:Command  
  5. {  
  6.     public papercmd(OrderReceiver request) : base(request) { }  
  7.   
  8.     /// <summary>  
  9.     /// 执行命令  
  10.     /// </summary>  
  11.     public override void Action()  
  12.     {  
  13.         //开始考试  
  14.         this.recediver.GetPaper();  
  15.     }  
  16. }  
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// 命令的发出者  
  3. /// </summary>  
  4. public class Invoke  
  5. {  
  6.     protected Command cmd;  
  7.     public Invoke(Command cmd)  
  8.     {  
  9.         this.cmd = cmd;  
  10.     }  
  11.   
  12.     public void Init()  
  13.     {  
  14.         this.cmd.Action();  
  15.     }  
  16. }  
[csharp] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. /// <summary>  
  2. /// C#设计模式-命令模式  
  3. /// </summary>  
  4. class Program  
  5. {  
  6.     static void Main(string[] args)  
  7.     {  
  8.         OrderReceiver o=new OrderReceiver(); //命令的响应者      >响应传达者传达的命令  
  9.         Command ecmd = new examcmd(o);       //命令的传达和监视者>传达发出这的命令给响应者  
  10.         Invoke ka = new Invoke(ecmd);        //命令的发出者        
  11.         ka.Init();                           //>传达给传递者扩散命令  
  12.   
  13.         Console.WriteLine("考试结束后");  
  14.         Command pcmd = new papercmd(o); //命令的传达和监视者  
  15.         Invoke kb = new Invoke(pcmd);   //命令的发出者  
  16.         kb.Init();    
  17.     }  
  18. }  
包括角色:
客户角色:发出一个具体的命令并确定其接受者。
命令角色:声明了一个给所有具体命令类实现的抽象接口
具体命令角色:定义了一个接受者和行为的弱耦合,负责调用接受者的相应方法。
请求者角色:负责调用命令对象执行命令。
接受者角色:负责具体行为的执行。

适用场景:
系统需要支持命令的撤销(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo方法吧命令所产生的效果撤销掉。命令对象还可以提供redo方法,以供客户端在需要时,再重新实现命令效果。
系统需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命周期。意思为:原来请求的发出者可能已经不存在了,而命令对象本身可能仍是活动的。这时命令的接受者可以在本地,也可以在网络的另一个地址。命令对象可以串行地传送到接受者上去。
如果一个系统要将系统中所有的数据消息更新到日志里,以便在系统崩溃时,可以根据日志里读回所有数据的更新命令,重新调用方法来一条一条地执行这些命令,从而恢复系统在崩溃前所做的数据更新。
系统需要使用命令模式作为“CallBack(回调)”在面向对象系统中的替代。Callback即是先将一个方法注册上,然后再以后调用该方法。

优缺点:
命令模式使得新的命令很容易被加入到系统里。
可以设计一个命令队列来实现对请求的Undo(取消)和Redo(重做)操作。
可以较容易地将命令写入日志。
可以把命令对象聚合在一起,合成为合成命令。合成命令式合成模式的应用。
命令模式使得命令发出的一个和接收的一方实现低耦合。
使用命令模式可能会导致系统有过多的具体命令类。这会使得命令模式在这样的系统里变得不实际。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多