原文:C#设计模式之十四命令模式(Command Pattern)【行为型】
一、引言
今天我们开始讲“行为型”设计模式的第二个模式,该模式是【命令模式】,又称为步履(Action)模式或交易(Transaction)模式,英文名称是:Command Pattern。还是老套路,先从名字上来看看。“命令模式”我第一次看到这个名称,我的理解是,可能是一种行为或者一个操纵就是一个命令。“命令”这个词语在军队里面用的最多,好比:下达作战命令,接下来就是上战场玩命了。基于这些,我觉得“命令”就是任务,执行了命令就完成了一个任务。或者说,命令是任务,我们再从这个名字上并不知道命令的发出者和接受者分袂是谁,为什么呢?因为我们并不关心他们是谁,发出命令的人发出命令,可以继续做其他的工作,接受命令的人执行任务就可以,不需要你发出命令,还要监督我们完成,只要我们完成任务是合格的就行。这种行为也就是“解耦”。在我们的现实生活中有很多例子可以拿来说明这个模式,我们还拿吃饺子这个工作来说。我的奶奶说了,,今天想吃饺子,发出了命令,然后我奶奶就去看电视去了。我们伉俪俩收到命令就开始和面,做饺子馅,包饺子。饺子包好了,我们就休息一会,等下午5点就开始烧水煮饺子了,晚饭的时间到了,我奶奶定时吃上了饺子。还有很多例子,就不一一列举了。
二、命令模式的详细介绍
2.1、动机(Motivate)
在软件构建过程中,“行为请求者”与“行为实现者”凡是泛起一种“紧耦合”。但在某些场合——好比需要对行为进行“记录、勾销/重做(undo/redo)、事务”等措置惩罚惩罚,这种无法抵制变革的紧耦合是不同适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为东西,可以实现二者之间的松耦合。
2.2、意图(Intent)
将一个请求封装为一个东西,从而使你可用差此外请求对客户(客户措施,也是行为的请求者)进行参数化;对请求排队或记录请求日志,以及撑持可勾销的操纵。 ——《设计模式》GoF
2.3、布局图(Structure)
2.4、模式的构成
屈从令模式的布局图可以看出,它涉及到五个角色,它们分袂是:
(1)、客户角色(Client):创建具体的命令东西,并且设置命令东西的接收者。注意这个不是我们通例意义上的客户端,而是在组装命令东西和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
(2)、命令角色(Command):声明了一个给所有具体命令类实现的抽象接口。
(3)、具体命令角色(ConcreteCommand):命令接口实现东西,是“虚”的实现;凡是会持有接收者,并挪用接收者的成果来完成命令要执行的操纵。
(4)、请求者角色(Invoker):要求命令东西执行请求,凡是会持有命令东西,可以持有很多的命令东西。这个是客户端真正触发命令并要求命令执行相应操纵的处所,也就是说相当于使用命令东西的入口。
(5)、接受者角色(Receiver):接收者,真正执行命令的东西。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应成果。
2.5、命令模式的代码实现
下面以生活中吃饺子为例来说说如何实现命令模式吧。在现实生活中,作为北方人都爱吃饺子,我奶奶出格爱吃饺子,我也遗传了这个喜好。今天早上,我奶奶就颁布了命令,说她白叟家想吃猪肉大葱馅的饺子。我奶奶腿脚欠好,就让我爸爸捎个话给我们伉俪俩,晚上要吃猪肉大葱馅的饺子。我瞬间就大白了,这个伟大的任务就落到我们伉俪俩肩上了。说做就做,保证晚饭能吃上热气腾腾的饺子,具体实现代码如下:
1 namespace 命令模式的实现 2 { 3 /// <summary> 4 /// 俗话说:“好吃不如饺子,舒服不如倒着”。今天奶奶发话要吃他大孙子和孙媳妇包的饺子。今天还拿吃饺子这件事来说说命令模式的实现吧。 5 /// </summary> 6 class Client 7 { 8 static void Main(string[] args) 9 { 10 //奶奶想吃猪肉大葱馅的饺子 11 PatrickLiuAndWife liuAndLai = new PatrickLiuAndWife();//命令接受者 12 Command command = new MakeDumplingsCommand(liuAndLai);//命令 13 PaPaInvoker papa = new PaPaInvoker(command); //命令请求者 14 15 //奶奶颁布命令 16 papa.ExecuteCommand(); 17 18 19 Console.Read(); 20 } 21 } 22 23 //这个类型就是请求者角色--也就是我爸爸的角色,报告奶奶要吃饺子 24 public sealed class PaPaInvoker 25 { 26 //我爸爸从奶奶那里接受到的命令 27 private Command _command; 28 29 //爸爸开始接受具体的命令 30 public PaPaInvoker(Command command) 31 { 32 this._command = command; 33 } 34 35 //爸爸给我们下达命令 36 public void ExecuteCommand() 37 { 38 _command.MakeDumplings(); 39 } 40 } 41 42 //该类型就是抽象命令角色--Commmand,界说了命令的抽象接口,任务是包饺子 43 public abstract class Command 44 { 45 //真正任务的接受者 46 protected PatrickLiuAndWife _worker; 47 48 protected Command(PatrickLiuAndWife worker) 49 { 50 _worker = worker; 51 } 52 53 //该要领就是抽象命令东西Command的Execute要领 54 public abstract void MakeDumplings(); 55 } 56 57 //该类型是具体命令角色--ConcreteCommand,这个命令完成制作“猪肉大葱馅”的饺子 58 public sealed class MakeDumplingsCommand : Command 59 { 60 public MakeDumplingsCommand(PatrickLiuAndWife worker) : base(worker) { } 61 62 //执行命令--包饺子 63 public override void MakeDumplings() 64 { 65 //执行命令---包饺子 66 _worker.Execute("今天包的是农家猪肉和农家大葱馅的饺子"); 67 } 68 } 69 70 //该类型是具体命令接受角色Receiver,具体包饺子的行为是我们伉俪俩来完成的 71 public sealed class PatrickLiuAndWife 72 { 73 //这个要领相当于Receiver类型的Action要领 74 public void Execute(string job) 75 { 76 Console.WriteLine(job); 77 } 78 } 79 }