设计模式学习笔记--Command命令模式
- 格式:docx
- 大小:81.73 KB
- 文档页数:12
安卓常⽤的6种设计模式总结最近看到两篇博客,觉得很不错,记录⼀下由于项⽬变更的频繁性,作为⼀名程序员,我们需要掌握设计模式的必要性,就不⾔⽽喻~~,下⾯就是⼀些我⾃⼰学习的设计模式总结。
接下来,主要是针对⼏个⽐较常⽤模式进⾏讲解,主要是以下⼏种:观察者模式适配器模式代理模式⼯⼚模式单例模式命令模式1.观察者模式(Observer Pattern)释义:观察者模式定义了⼀种⼀对多的依赖关系,让多个观察者对象同时监听某⼀个主题对象,这个主题对象在状态上发⽣变化时,会通知所有观察者对象,使他们能够⾃动更新⾃⼰。
故事理解:观察者想知道公司所有MM的情况,只要加⼊公司的MM情报邮件组就⾏了,tom负责搜集情报,当发现新情报时,不⽤⼀个⼀个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦。
常见实例:1.BaseAdapter.registerDataSetObserver和BaseAdapter.unregisterDataSetObserver两⽅法来向BaseAdater注册、注销⼀个DataSetObserver ; 2.使⽤ContentObserver去监听数据库变化。
适⽤场景:1.当对⼀个对象的改变需要同时改变其他对象,⽽不知道具体有多少对象有待改变;2.当⼀个对象必须通知其它对象,⽽它⼜不能假定其它对象是谁.观察者模式主要有观察者和被观察者2个对象,在该模式中,Observable表⽰被观察者,这个对象是⼀个抽象类,只能被继承。
Observer表⽰观察者,他是⼀个接⼝,所以观察者可以有多个,实现了该接⼝的类都是属于观察者。
这是⽹上⼀个⽣动细致的demo:被观察者:public class MyPerson extends Observable {private int age;private String name;private String sax;public int getAge() {return age;}public void setAge(int age) {this.age = age;setChanged();notifyObservers();}public String getName() {return name;}public void setName(String name) { = name;setChanged();notifyObservers();}public String getSax() {return sax;}public void setSax(String sax) {this.sax = sax;}@Overridepublic String toString() {return "MyPerson [age=" + age + ", name=" + name + ", sax=" + sax + "]";}}MyPerson是被观察者,类中调⽤了setChange()以及notifyObservers()两个⽅法,前者是告知数据改变,后者是发送信号通知观察者。
命令模式将请求封装成对象使得可以用不同的请求对客户进行参数化命令模式(Command Pattern)是一种行为设计模式,它将一个请求封装成一个对象,使得可以用不同的请求对客户进行参数化。
这种模式中,请求的调用者和请求的接收者解耦,使得调用者不需要知道请求的接收者的具体信息。
在实际的软件开发中,命令模式是一个非常常用的设计模式。
它可以用于实现菜单项的点击事件、处理用户交互的命令、撤销和重做操作等功能。
下面我们通过一个简单的例子来说明命令模式的使用场景和优势。
假设我们正在开发一个家庭智能控制系统,用户可以通过手机APP 控制家里的电器设备。
现在我们要实现一个功能,当用户点击“开灯”按钮时,系统能够自动打开客厅的灯。
这个功能可以通过命令模式来实现。
首先,我们定义一个抽象命令类(Command),其中包含一个抽象方法execute()用于执行命令。
接下来,我们定义具体的命令类(LightOnCommand),继承自抽象命令类,实现execute()方法,在execute()方法中调用相应的接收者(Light)的方法,完成具体的操作(打开灯)。
同时,我们还需要定义一个接收者类(Light),其中包含打开灯的方法。
接下来,我们可以定义一个请求者(Invoker)类,该类包含一个命令对象(Command)作为成员变量,并提供一个方法用于设置命令对象。
在请求者类的方法中,调用命令对象的execute()方法实现请求的执行。
最后,我们可以编写一个客户端类(Client),通过该类来测试命令模式的使用。
在客户端类中,我们实例化命令对象和接收者对象,将命令对象设置进请求者对象,然后调用请求者对象的方法。
这样,当用户点击“开灯”按钮时,请求者对象会调用命令对象的execute()方法,从而执行相应的命令,打开客厅的灯。
通过使用命令模式,我们可以很方便地实现对请求的封装和参数化。
比如,如果用户点击“关灯”按钮,我们只需要定义一个新的具体命令类(LightOffCommand),实现execute()方法即可。
命令模式与观察者模式:解耦与扩展代码的设计模式命令模式和观察者模式是两种常见的设计模式,它们可以帮助我们解耦和扩展代码。
下面我将详细介绍这两种模式,并分析它们的优点和适用场景。
1.命令模式(Command Pattern)命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使得我们可以用不同的请求来参数化其他对象。
命令模式的核心思想是将方法调用、请求或者操作封装到一个单一的对象中,然后通过传递和调用这个对象来实现请求的不同。
命令模式的主要角色包括:-命令接口(Command Interface):用于封装请求的接口,通常包含一个执行(execute)方法。
-具体命令类(Concrete Command Class):实现命令接口,负责执行具体的操作。
-命令接收者(Command Receiver):负责执行命令的对象。
-命令发起者(Command Invoker):负责调用命令对象执行请求。
命令模式的优点有:-解耦:命令模式可以将命令的接收者和发送者解耦,发送者只需要知道如何调用命令对象,而无需知道命令对象如何处理请求。
-扩展:通过添加新的命令对象,可以很方便地扩展和改变系统的行为。
-撤销和重做:命令模式可以支持撤销和重做操作,通过保存命令对象的历史记录,可以回到之前的状态。
命令模式适用的场景有:-需要将命令的请求者和执行者解耦时,可以使用命令模式。
-需要支持撤销和重做操作时,可以使用命令模式。
-需要记录操作日志时,可以使用命令模式。
2.观察者模式(Observer Pattern)观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生变化时,它的所有依赖者都会收到通知并作出相应的更新。
观察者模式的核心思想是将观察者和被观察者解耦,使得它们可以独立地变化。
观察者模式的主要角色包括:-被观察者(Subject):维护一组观察者对象,并提供添加、删除和通知观察者的接口。
vi编辑器:命令模式、输⼊模式、末⾏模式1、命令模式(command mode)—执⾏命令 在该模式中,可以输⼊命令来执⾏许多种功能。
控制屏幕光标的移动,字符、字或⾏的删除,移动复制某区段及进⼊Insert mode下,或者到last line mode。
2、输⼊模式(Insert mode)—输⼊⽂本 vi被运⾏时,通常处在命令模式下,键⼊以下命令可以使vi退出命令模式,进⼊输⼊模式:I(i)、A(a)、O(o)。
3、末⾏模式(last line mode)—执⾏待定命令 将⽂件保存或退出vi,也可以设置编辑环境,如寻找字符串、列出⾏号……等。
不过⼀般我们在使⽤时把vi简化成两个模式,就是将末⾏模式(last line mode)也算⼊命令⾏模式command mode)。
1. vi的启动 输⼊vi命令后,便进⼊全屏幕编辑环境,此时的状态为命令模式。
(1) vi 进⼊vi的⼀个临时缓冲区,光标定位在该缓冲区第1⾏第1列的位置上。
(2) vi file1 如果file1⽂件不存在,将建⽴此⽂件;如该⽂件存在,则将其拷贝到⼀个临时缓冲区。
光标定位在该缓冲区第1⾏第1列的位置上。
(3) vi + file1 如果file1⽂件不存在,将建⽴此⽂件;如该⽂件存在,则将其拷贝到⼀个临时缓冲区。
光标定位在⽂件最后1⾏第1列的位置上。
(4) vi +N file1(N:为数字) 如果file1⽂件不存在,将建⽴此⽂件;如该⽂件存在,则将其拷贝到⼀个临时缓冲区。
光标定位在⽂件第N⾏第1列的位置上。
(5) vi +/string file1 如果file1⽂件不存在将建⽴此⽂件;如该⽂件存在则将其拷贝到⼀个临时缓冲区。
光标定位在⽂件中第⼀次出现字符串string的⾏⾸位置。
2. 退出vi(末⾏模式(last line mode)) 建议在退出vi前,先按ESC键,以确保当前vi的状态为命令⽅式,然后再键⼊“:”(冒号),输⼊下列命令,退出vi。
command的用法command(命令)是一种编程语句,它可以用于调用其他程序文件来执行特定任务。
它是一种很有用的编程工具,可以用来搜索文件,操作文件系统,控制网络,创建用户界面等。
Command语句基本上为以下格式:Command [ option ] [ argument ] ...其中,“Command”是指操作,“option”是指该操作可用的一组选项,而“argument”则是指相关参数,比如输入文件的路径或文件名等。
使用Command有以下几个常用方法:一、方法一:在命令行模式下输入指令我们可以在命令行模式下输入以下格式的指令,来间接执行某些操作:command [ option ] [ argument ] ...举个例子:要求系统显示一文件的列表,我们首先可以用dir命令,并加上参数(例如c:\temp),就可以实现该功能:dir c:\temp二、方法二:通过脚本运行命令我们也可以使用脚本来执行命令,以更便捷、更简单的方式完成复杂任务。
例如:要在系统中安装一个应用程序,可以通过使用脚本来执行安装命令的方式来实现:setup.exe [ option ] [ argument ] ...三、方法三:使用第三方工具执行命令我们还可以使用一些第三方工具来执行命令,以达到可视化操作的目的。
比如,使用PowerShell可以方便地执行系统操作和网络管理等常见任务,且可以很方便地生成界面。
例如:要添加一个用户到某服务器,可以使用PowerShell脚本来自动实现这一目的:$user = get-credentialnet user $ername $user.password /Add通过以上方法,我们可以很方便地利用command完成系统任务,从而大大加快操作的效率。
command的使用不仅提升了我们的工作效率,而且还可以更有效地解决复杂的任务。
Command(命令模式)Command(命令模式)属于行为型模式。
意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
举例子如果看不懂上面的意图介绍,没有关系,设计模式需要在日常工作里用起来,结合例子可以加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。
点菜是命令模式为什么顾客会找服务员点菜,而不是直接冲到后厨盯着厨师做菜?因为做菜比较慢,肯定会出现排队的现象,而且有些菜可能是一起做效率更高,所以将点菜和做菜分离比较容易控制整体效率。
其实这个社会现象就对应编程领域的命令模式:点菜就是一个个请求,点菜员记录的菜单就是将请求生成的对象,点菜员不需要关心怎么做菜、谁来做,他只要把菜单传到后厨即可,由后厨统一调度。
大型软件系统的操作菜单大型软件操作系统都有一个特点,即软件非常复杂,菜单按钮非常多。
但由于菜单按钮本身并没有业务逻辑,所以通过菜单按钮点击后触发的业务行为不适合由菜单按钮完成,此时可利用命令模式生成一个或一系列指令,由软件系统的实现部分来真正执行。
浏览器请求排队浏览器的请求不仅会排队,还会取消、重试,因此是个典型的命令模式场景。
如果不能将window.fetch序列化为一个个指令放入到队列中,是无法实现请求排队、取消、重试的。
意图解释意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
一个请求指的是来自客户端的一个操作,比如菜单按钮点击。
重点在点击后并不直接实现,而是将请求封装为一个对象,可以理解为从直接实现:function onClick() {// ... balabala 实现逻辑}改为生成一个对象,序列化这个请求:function onClick() {concreteCommand.push({// ... 描述这个请求})// 执行所有命令队列concreteCommand.executeAll()}看上去繁琐了一些,但得到了后面所说的好处:“从而使你可用不同的请求对客户进行参数化”,也就是可以对任何请求进行参数化存储,我们可以在任意时刻调用。
命令模式是对命令的封装。
通过封装把发出命令的责任和执行命令的责任分割开,委派给不同的对象。
命令(Command)模式属于对象的行为模式【GOF95】,它又称为行动(Action)模式或交易(Transaction)模式。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
命令模式涉及到五个角色,它们分别是:1、客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
2、命令(Command)角色:声明了一个给所有具体命令类的抽象接口。
这是一个抽象角色。
3、具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Exec ute()方法,负责调用接收考的相应操作。
Execute()方法通常叫做执方法。
4、请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
5、接收者(Receiver)角色:负责具体实施和执行一个请求。
任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
代码实现:根据命令(Command)角色所要负责的工作,我们可分为两种方式来实现:1、一种是Seperate方式,此方式下命令(Command)角色仅确定一个接收者和执行该请求的动作,因此,它需要在子类中完成具体的命令操作,并通过请求者(Invoker)角色这一中间层来与接收者互动。
2、另一种是Combine方式,此时命令(Command)角色要自己实现所有命令功能,根本不需要请求者(Invoker)角色,它自己充当了中间层来与接收者互动。
下面我们来用代码说明如何理解Command命令模式,程序如下图:一、传统的做法:不采用Command模式的情况1、定义一个类Carusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace CommandCar{//一个类是一组操作和相应的一些变量的集合,现在有这样一个类Car,它有如下的一些操作public class Car{public string curStateStr;public Car(){curStateStr = "";}public void Start(){Console.WriteLine("车子起动");}public void MoveForwards(){Console.WriteLine("车子前进");}public void MoveBackwards(){Console.WriteLine("车子倒退");}public void Stop(){Console.WriteLine("车子停止");}}}2、使用这个类及其相关操作,写在Programme.cs中#region通常的操作(紧耦合方式)//通常的操作使得行为的请求者和行为的实现者之间呈现一种紧耦合,如果我们要对相关操作进行Redo,Undo等操作则这种紧耦合方式就显得很复杂//可以看到,客户程序是依赖于具体Car的命令(方法)的,引入Command 模式,需要对Car中的4个命令进行抽象//在抽象前,在我们看来Start(),MoveForwards(),MoveBackwards(), Stop()这几个方法都应该是Car所具有的,//如果单独抽象出来成一个命令对象,那就是把函数层面的功能提到了类的层面Car mycar = new Car();Console.WriteLine("--------常规方式执行效果如下----------"); mycar.Start();mycar.MoveForwards();mycar.MoveBackwards();mycar.Stop();// Console.ReadLine();#endregion这种情况下,把命令的接收者Car与行为(Start,Stop等操作)紧密耦合二、Seperate方式仍使用上面定义的类Car(它就是接收者Receiver角色),不同的是我们要加入以下角色1、命令Command角色CarSeperateCommandusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace CommandCar{//定义抽象类CarSeperateCommand,对于Function方式而言,它仅确定一个接收者Car和执行该请求的动作Excute。
24种设计模式Factory Pattern(⼯⼚模式):1. 创建对象的接⼝,封装对象的创建;2. 使具体化类的⼯作延迟到⼦类中。
(维护⼀类对象)AbstractFactory Pattern(抽象⼯⼚模型):该模式将⼀组对象的创建封装到⼀个⽤于创建对象的类中。
(解决的问题:要创建⼀组或者相互依赖的对象)。
Singleton Pattern(单例模式):该模式在⾯向纯粹的⾯向对象的范式中⽤于创建唯⼀的实例,值得注意的是Singleton不能被实例化,因此将其构造函数声明为protected或private类型。
Singleton Pattern经常与Factory Pattern结合使⽤,因为Factory对象只能有⼀个。
Builder Pattern(创建者模式):将⼀个复杂的对象的构建与它的表⽰分离,使得同样的构建构成可以创建不同的表⽰。
如建筑师画图纸,⽽⼯⼈建造房屋。
Prototype Pattern(原型模式):提供⼀个通过已存在对象进⾏新对象创建的接⼝(clone)。
(浅拷贝和深拷贝)Bridge Pattern(桥梁模式):将抽象部分与实现部分分开实现,使他们都可以独⽴地变化,并使⽤组合的⽅式将多维度的抽象⽅法联系在⼀起。
⽐如咖啡分⼩杯、中杯、⼤杯以及加奶和不加奶,则抽象部分为:⼩杯、中杯、⼤杯,⾏为为:加奶和不加奶。
Adapter Pattern(适配器模式):适配就是由“源”到“⽬标”的适配,⽽当中链接两者的关系就是适配器。
它负责把“源”过度到“⽬标”。
将⼀个类的接⼝转换成客户希望的另外⼀个接⼝。
Adapter模式使得原本由于接⼝不兼容⽽不能⼀起⼯作的那些类可以⼀起⼯作。
适配器模式分为两种:①⾯向类的设计模式;②⾯向对象的设计模式。
①⾯向类的适配器:该模式使⽤继承和接⼝实现的⽅式复⽤需要适配器的类。
②⾯向对象的适配器:该模式使⽤组合的⽅式实现需要复⽤的类。
Decorator模式(装饰模式):动态地给⼀个对象添加⼀些额外的职责。
分享⼀下我记忆23种设计模式的⽅法来CNBLOGS好久了,也没写过点什么,最近在学习23种设计模式,既然是要学习这些模式,⾸先得记住吧,呵呵,下⾯我总结我⼀下我的记忆⽅法,希望给⼤家分享。
⾸先列出23种设计模式1 Singleton 单件2 Abstract Factory 抽象⼯⼚模式3 Builder ⽣成器模式4 Factory Method ⼯⼚⽅法模式5 Prototype 原型模式6 Adapter 适配器模式7 Bridge 桥接模式8 Composite 组合模式9 Decorator 装饰模式10 Facade 外观模式11 Flyweight 享元模式12 Proxy 代理模式13 Template Methed模板⽅法14 Command 命令模式15 Interpreter 解释器模式16 Mediator 中介者模式17 Iterator 迭代器模式18 Observer 观察者模式19 Chain Of Responsibility 职责链模式20 Memento 备忘录模式21 State 状态模式22 Strategy 策略模式23 Visitor 访问者模式下⾯我们开始这样记忆根据设计模式前的数字来联想记忆,把1,11,21这样的模式串联起来记忆。
具体如下:1------ 肯定是⼀个了,所以是单个,联想单件模式;11----- 1是最⼩单位,11是由两个1(可以想象成多个1)组成,要解决多个1共享资源的模式是享元模式21----- 由2变成了1.可以想象成⼩弟弟见到MM后由S形变成了棍形,状态发⽣了变化 ---状态模式2------ 把2想象成鸭⼦,是我们的想象,是我们的抽象,想到抽象⼯⼚模式12----- 把我们1家的产品叫给2家或更多家来代理,想到代理模式22----- 从家到公司有2条(或多条)路来⾛(把每个2都想象成弯弯的路),⾛每条都是⼀个策略,策略模式3------ 想象成MM的胸部,⽣成奶汁的地⽅,⽣成器模式13-----⽤印模印过⼩猪吧,这个想象到什么了吗?对!把这个样⼦⾥填充⼀些泥巴,就可以得到MM的mimi模型喽,13象个模板吧?呵呵模板⽅法23-----这个更简单了,两只⼿来摸(访问)MM的mimi,访问者模式4------- 4象⼀⾯⼩红旗,象⼀⾯插在⼯⼚屋顶的⼩红旗,⼯⼚⽅法模式14------ 4象⼀⾯⼩红旗,1⾯红旗就是⼀道命令,命令模式5------- 5象个挺着⼤肚⼦的孕妇,穿再多的⾐服也掩盖不了她这种原型,原型模式15------ 旁边已经有1个⼩孩了,你怎么⼜怀上了?给⼤家解释⼀下吧,解释器模式6-------带天线的电⼦器件,适配器?适配器模式16------我要在淘宝上买⼀个适配器,淘宝就是中介者,中介者模式7-------想象成天桥,桥接模式17------⼀座桥连⼀座桥,桥上还有桥,迭代器模式8------- 8是由oo组合⽽成的组合模式18------- 带着1个望远镜(8象⼀个望远镜)⼲吗?观察呗!观察者模式9------- 象⼀个⽓球,⽓球是⽤来装饰的,装饰模式19------- ⼀串⽓球,每个⽓球都有⾃⼰的位置和职责,职责链模式10------- 瞧,⼀个鸡蛋,鸡蛋的外观就是这样的,外观模式20-------⼀个台灯,⼀个圆桌,我在写备忘录,备忘录模式好了,写到这吧,先每个⼈都有⾃⼰的记忆⽅法,我就是联想,就是瞎想,世界没有联想将会怎样?(另,今天11:10~11:30左右,由于同时链接过多造成⽹站不能访问,当我发布的时候,⽹站不能访问了,苦呀,哭呀,还好,我⼜写了⼀遍)。
命令模式是对命令的封装。
通过封装把发出命令的责任和执行命令的责任分割开,委派给不同的对象。
命令(Command)模式属于对象的行为模式【GOF95】,它又称为行动(Action)模式或交易(Transaction)模式。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
命令模式涉及到五个角色,它们分别是:1、客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
2、命令(Command)角色:声明了一个给所有具体命令类的抽象接口。
这是一个抽象角色。
3、具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Exec ute()方法,负责调用接收考的相应操作。
Execute()方法通常叫做执方法。
4、请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
5、接收者(Receiver)角色:负责具体实施和执行一个请求。
任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
代码实现:根据命令(Command)角色所要负责的工作,我们可分为两种方式来实现:1、一种是Seperate方式,此方式下命令(Command)角色仅确定一个接收者和执行该请求的动作,因此,它需要在子类中完成具体的命令操作,并通过请求者(Invoker)角色这一中间层来与接收者互动。
2、另一种是Combine方式,此时命令(Command)角色要自己实现所有命令功能,根本不需要请求者(Invoker)角色,它自己充当了中间层来与接收者互动。
下面我们来用代码说明如何理解Command命令模式,程序如下图:一、传统的做法:不采用Command模式的情况1、定义一个类Carusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace CommandCar{//一个类是一组操作和相应的一些变量的集合,现在有这样一个类Car,它有如下的一些操作public class Car{public string curStateStr;public Car(){curStateStr = "";}public void Start(){Console.WriteLine("车子起动");}public void MoveForwards(){Console.WriteLine("车子前进");}public void MoveBackwards(){Console.WriteLine("车子倒退");}public void Stop(){Console.WriteLine("车子停止");}}}2、使用这个类及其相关操作,写在Programme.cs中#region通常的操作(紧耦合方式)//通常的操作使得行为的请求者和行为的实现者之间呈现一种紧耦合,如果我们要对相关操作进行Redo,Undo等操作则这种紧耦合方式就显得很复杂//可以看到,客户程序是依赖于具体Car的命令(方法)的,引入Command 模式,需要对Car中的4个命令进行抽象//在抽象前,在我们看来Start(),MoveForwards(),MoveBackwards(), Stop()这几个方法都应该是Car所具有的,//如果单独抽象出来成一个命令对象,那就是把函数层面的功能提到了类的层面Car mycar = new Car();Console.WriteLine("--------常规方式执行效果如下----------"); mycar.Start();mycar.MoveForwards();mycar.MoveBackwards();mycar.Stop();// Console.ReadLine();#endregion这种情况下,把命令的接收者Car与行为(Start,Stop等操作)紧密耦合二、Seperate方式仍使用上面定义的类Car(它就是接收者Receiver角色),不同的是我们要加入以下角色1、命令Command角色CarSeperateCommandusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace CommandCar{//定义抽象类CarSeperateCommand,对于Function方式而言,它仅确定一个接收者Car和执行该请求的动作Excute。
//所以,在抽象类CarSeperateCommand中,只声明一个Excute的方法。
这个方法在其子类(StartCommand类,MoveForwardsCommand类,MoveBackwardsCommand类,Sto pCommand类)中进行实现。
//(当然这个CarSeperateCommand还可以定义成接口)//Car所具有的其他的具体命令类(StartCommand类,MoveForwardsCommand类,Mo veBackwardsCommand类,StopCommand类)都继承于该抽象类//StartCommand类,MoveForwardsCommand类,MoveBackwardsCommand类,Sto pCommand类将用于封装对应的操作命令public abstract class CarSeperateCommand{Car _car;public CarSeperateCommand(Car mycar){this._car = mycar;}public abstract void Excute();}}2、具体命令(ConcreteCommand)角色:CarSeperateCommandClasses中内含的(StartCommand类,MoveForwardsCommand类,MoveBackwardsCommandusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Collections;namespace CommandCar{//定义StartCommand类,MoveForwardsCommand类,MoveBackwardsCommand 类,StopCommand类//这四个类都继承自抽象类CarFunctionCommand,它们实现了对Car对象自身所具备的Start(),MoveForwards(),MoveBackwards(),Stop()四个命令分别进行了封装//它们都把Car对象实例做为传入的参数StartCommand命令类MoveForwardsCommand命令类MoveBackwardsCommand命令类StopCommand命令类Undo命令}3、请求者(Invoker)角色:CarSeperateInvoker,它充当客户与操作的中间层using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace CommandCar{//这是一个中间角色CarSeperateInvoker,//通过这个中间角色,把对象Car对CarSeperateCommand的依赖转换为Car对Car SeperateInvoker的依赖。
class CarSeperateInvoker{CarSeperateCommand _start;CarSeperateCommand _moveforwards;CarSeperateCommand _movebackwards;CarSeperateCommand _stop;CarSeperateCommand _undo;public CarSeperateInvoker( CarSeperateCommand start,CarSeperateCommand moveforwards, CarSeperateCommand movebackwards, CarSeperateCommand stop,CarSeperateCommand undo){this._start = start;this._moveforwards = moveforwards;this._movebackwards = movebackwards;this._stop = stop;this._undo = undo;}public void Start(){_start.Excute();}public void MoveForwards(){_moveforwards.Excute();}public void MoveBackwards(){_movebackwards.Excute();}public void Stop(){_stop.Excute();}public void Undo(){_undo.Excute();}}}4、客户(Client)角色:写在Programme.cs中#region Seperate方式//在客户程序中,不再依赖于Car的Start(),MoveForwards(),MoveBa ckwards(),Stop()命令,//通过StartCommand类,MoveForwardCommand类,MoveBackwardCom mand类,StopCommand类对这些命令进行了封装,使用它们的一个关键就是抽象的CarFunc tionCommand类,它定义了一个操作的接口。
//而StartCommand类,MoveForwardCommand类,MoveBackwardComma nd类,StopCommand类四个对应于相关命令的类继承自CarFunctionCommand这个接口并实现接口中定义的Excute功能//同时我们也可以看到,本来这四个命令仅仅是四个方法而已,但是通过Com mand模式却把它们提到了类的层面,//它通过违背面向对象的原则为代价,解决了分离命令的请求者和命令的执行者的问题。