编程模式之15---行为型----命令模式

定义

将一个请求封装成一个对象,让你可以用不同的请求对客户端进行参数化,对请求排队,纪录请求日志和支持可撤消操作.

有三个具体成员,请求的发送者,请求的接收者,还有就是请求本身(或者是命令).对客户端进行参数化,也就是客户端可以把请求对象当成一个参数,直接注入到请求发送者内部,不用管请求接收者;对请求排队,如果一个请求发送者发送了一个请求,有多个接收者会处理这个请求的话,那么就需要对命令排队,命令对象和请求接收者是一一对应的;纪录请求日志,当发出一个请求时,由命令对象来保存一些信息,证明本对象被使用了,也可以说是本命令被处理了;支持可撤消操作,比如一个加法命令,命令对象纪录下加数,通过减去这个加数就实现了一次撤消,通过再加上这个加数就实现了一次恢复.

结构组成

从定义中,可以看出,一次完整的命令(请求)处理需要有三种类型成员参与.

抽象命令类(Command):声明了执行请求的方法Execute,方法中调用请求接收者的处理方法.

具体命令类(ConcreteCommand):实现方法Execute,每个具体命令类对应一个请求处理者.

调用者(Invoke):发送命令者,维护一个命令对象的引用.调用命令类的Execute方法.

接收者(Receiver):定义了用于处理请求的业务方法.最终的处理还是在业务方法中.

示例

  

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using System.Configuration;
 5 using System.Reflection;
 6
 7 namespace 命令模式
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             Configuration cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
14             string comm = cfa.AppSettings.Settings["commandfan"].Value;//这是得到风扇命令类
15             Assembly assembly = Assembly.GetEntryAssembly();
16             Command command =(Command) assembly.CreateInstance(comm);
17             ButtonStart bs = new ButtonStart(command);//注入到调用者中
18             bs.Start();//调用者执行调用,直接调用的是命令类对象的方法,实质最终的响应还是接收者完成
19             Console.Read();
20         }
21     }
22     class ButtonStart
23     {
24         private Command com = null;
25         public ButtonStart(Command com)
26         {
27             this.com = com;
28         }
29         public void Start()
30         {
31             com.Execute();//执行命令类的方法
32         }
33     }
34     abstract class Command
35     {
36         public abstract void Execute();
37     }
38     class FanCommand : Command//风扇命令类
39     {
40         private Fan fan = null;
41         public FanCommand()
42         {
43             fan = new Fan();
44         }
45         public override void Execute()
46         {
47             fan.StartUP();
48         }
49     }
50     class BulbCommand : Command
51     {
52         private Bulb bulb= null;
53         public BulbCommand()
54         {
55             bulb = new Bulb();//调用命令接收者的业务方法
56         }
57         public override void Execute()
58         {
59             bulb.Light();//调用命令接收者的业务方法
60         }
61     }
62     class Fan//风扇类,命令接收者
63     {
64         public void StartUP()
65         {
66             Console.WriteLine("风扇启动");
67         }
68     }
69     class Bulb//灯泡类,命令接收者
70     {
71         public void Light()
72         {
73             Console.WriteLine("发光");
74         }
75     }
76 }

  感觉实际上还是按一条链那样调用的样子。看不出太多的优势。

命令队列,纪录日志,撤消操作

  命令队列适用的情况:当一个请求发出后,会有多个请求接收者响应,也就是有多个命令对象来“中间处理”;在命令发送者类中,维护一个命令列表,当请求发出时,依次调用命令队列中命令对象的方法。示例如下:

  

 1     class ButtonStart
 2     {
 3         private Command com = null;
 4         public List<Command> lstComm = new List<Command>();//维护命令队列
 5         public void StartAll()//启动所有命令
 6         {
 7             foreach (Command com in lstComm)
 8             {
 9                 com.Execute();
10             }
11         }
12         public ButtonStart()
13         {
14         }
15         public ButtonStart(Command com)
16         {
17             this.com = com;
18         }
19         public void Start()
20         {
21             com.Execute();//执行命令类的方法
22         }
23     }
24
25
26
27 //客户端调用情况
28             //命令队列
29             ButtonStart bsque = new ButtonStart();
30             bsque.lstComm.Add(new FanCommand());
31             bsque.lstComm.Add(new BulbCommand());
32             bsque.StartAll();
33
34 /*
35 在调用时,发送者类中的一次调用,就让所有命令对象来响应了,最终反映到所有接收者的响应中。
36 这次调用,也体现到了多态的作用。
37 */

  还可以把对多个命令的组织放到一个独立的对象中,对象对应的类结构大概如下:

 1     class QueueCommand
 2     {
 3         private List<Command> lstComm = new List<Command>();
 4         public void Add(Command com)//添加成员
 5         {
 6             lstComm.Add(com);
 7         }
 8         public void Execute()//执行此方法,循环调用多个命令对象的方法
 9         {
10             foreach (Command com in lstComm)
11             {
12                 com.Execute();
13             }
14         }
15     }

  纪录日志:

  当一个命令执行前,把这个操作纪录下来。方法是在某个命令对象执行Excute方法时,在调用对应的接收者的业务方法前,把一些有纪录意义的文本保存到“日志文件”中。

 1     class BulbCommand : Command
 2     {
 3         public string blog = "发光日志";
 4         private Bulb bulb= null;
 5         public BulbCommand()
 6         {
 7             bulb = new Bulb();//调用命令接收者的业务方法
 8         }
 9         public override void Execute()
10         {
11             Console.WriteLine("模拟灯泡被开启日志"+blog);
12             bulb.Light();//调用命令接收者的业务方法
13         }
14     }

  结合序列化等,把对象序列化到硬盘上。

  可撤消操作:

  当一个命令对象执行Excute方法后,可以再调用一个与之相反的操作的方法就实现了撤消。比如加一个数后,保存此加数,让被加数送去加数,就实现一回撤消;如果实现多回撤消的话,把多次使用的加数保存到一个队列中,通过索引来得到某个加数,再用被减数减去它。

 1     class Command
 2     {
 3         public abstract int Execute(int x);
 4         public abstract int UnDo(int x);
 5     }
 6     class AddCommand : Command
 7     {
 8         private int value = 100;//传入的值和value相加操作
 9         public override int Execute(int x)
10         {
11             return x + value;
12         }
13         public override int UnDo(int x)
14         {
15             return x - value;
16         }
17     }

什么时候可以用

  系统需要把请求发送者和接收者解耦;系统需要撤消操作、或者把请求处理排队。

编程模式之15---行为型----命令模式

时间: 2024-08-01 11:04:49

编程模式之15---行为型----命令模式的相关文章

15.设计模式_命令模式

一.前言 之前一直在忙于工作上的事情,关于设计模式系列一直没更新,最近项目中发现,对于设计模式的了解是必不可少的,当然对于设计模式的应用那更是重要,可以说是否懂得应用设计模式在项目中是衡量一个程序员的技术水平,因为对于一个功能的实现,高级工程师和初级工程师一样都会实现,但是区别在于它们实现功能的可扩展和可维护性,也就是代码的是否"优美".可读.但是,要更好地应用,首先就必须了解各种设计模式和其应用场景,所以我还是希望继续完成设计模式这个系列,希望通过这种总结的方式来加深自己设计模式的理

设计模式-行为型-命令模式

命令模式(Command): 将请求封装成对象,以便使用不同的请求.日志.队列等来参数化其他对象.命令模式也支持撤销操作. 命令模式的角色: 1)传递命令对象(Invoker):是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者. 2)抽象命令接口(Command):声明执行命令的接口,拥有执行命令的抽象方法execute(). 3)具体的命令对象(ConcreteCommand):是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完

JAVA设计模式(15):行为型-命令模式(Command)

介绍 命令模式:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作.也称之为:动作Action模式.事务transaction模式. 结构 Command抽象命令类 定义命令的接口,声明执行的方法. ConcreteCommand具体命令类 命令接口实现对象,是"虚"的实现:通常会持有接收者,并调用接收者的功能来完成命令要执行的操作. Invoker调用者/请求者 请求的发送者,它通过命令对象来执行请求.一个调用者并不需

[设计模式-行为型]命令模式(Command)

一句话 命令的请求和命令的执行用不同的对象表示.(好处是可以独立开发,也可以进行撤销) 概括 解析 COMMAND-俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我.这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:"我同时给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面."命令模式:命令模式把一个请求或者操作封装到一个对象中.命令模式把发出命令的责任和执行命令的责任

设计模式-行为型-命令模式(COMMAND)

命令模式是一个结构比较简单的设计模式,gof在书中对它的定义是:"将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作." 这里有两个要点,第一请求被封装成了一个对象,第二请求可以被持久化(排队或是记录.取消). 我们从第一个要点说起.首先需要注意一点的所有COMMAND的模型都可以抽象出一个Execute概念或是类似概念.如下图(左)一样,这里的请求就是对文档做出paste操作,封装的结果就是通过PasteCommand的一

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

将请求与实现解耦并封装成独立对象,从而使不同的请求对客户端的实现参数化.命令模式是将创建模块的逻辑封装在一个对象里,这个对象提供一个参数化的请求接口,通过调用这个接口并传递一些参数实现调用命令对象内部中的一些方法.请求部分很简单,只需要按照给定参数格式书写指令即可,所以实现部分的封装才是重点,因为它要为请求部分提供所需方法. // 模块实现模块 var viewCommand = (function() { var tpl = { // 展示图片结构模块 product: [ '<div>',

设计模式(十四):Command命令模式 -- 行为型模式

1.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活. 例子1:电视机遥控器 : 遥控器是请求的发送者,电视机是请求的接收者,遥控器上有一些按钮如开,关,换频道等按钮就是具体命令,不同的按钮对应电视机的不同操作. 2.问题 在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧

设计模式 ( 十三 ) 命令模式Command(对象行为型)

设计模式 ( 十三 ) 命令模式Command(对象行为型) 1.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活. 例子1:电视机遥控器 : 遥控器是请求的发送者,电视机是请求的接收者,遥控器上有一些按钮如开,关,换频道等按钮就是具体命令,不同的按钮对应电视机的不同操作. 2.问题

C#设计模式(15)——命令模式(Command Pattern)

原文:C#设计模式(15)--命令模式(Command Pattern) 一.前言 之前一直在忙于工作上的事情,关于设计模式系列一直没更新,最近项目中发现,对于设计模式的了解是必不可少的,当然对于设计模式的应用那更是重要,可以说是否懂得应用设计模式在项目中是衡量一个程序员的技术水平,因为对于一个功能的实现,高级工程师和初级工程师一样都会实现,但是区别在于它们实现功能的可扩展和可维护性,也就是代码的是否“优美”.可读.但是,要更好地应用,首先就必须了解各种设计模式和其应用场景,所以我还是希望继续完