命令模式算是设计模式中比较简单的,最常见的例子是工作任务安排下来进行编程,如果工作任务不需要完成,我们可以取消我们之前完成的代码,也可以理解为回滚撤销操作。这里面涉及到命令模式中的两个对象,一个是动作实现者,一个是行为请求者,我们可以将Boss理解为行为请求者,程序员理解为实现者,命令模式中我们通过调用者实现两者之间的解耦,生活中我们通过技术管理部门将老板和程序员隔离。我们有时候会遇到老板认为新版设计实现不如上一版,业务发生变化和开发效率的问题会随时进行任务的调整,虽然你有的时候很不情愿,但是还是会发生取消完成的任务,跟原来保持不变。

基础知识

先来看一下命令模式的UML类图:

Client:客户端,命令发送者;

Receiver:接收者,行为实现者;

Command:命令基类,定义基础的命令方法;

ConcreteCommand:命令子类,每个命令子类会关联一个Receiver,实现具体的任务;

Invoker:调用者,负责执行打包过的命令对象;

功能实现

我们可以先来定义Command类:

@protocol CommandProtocal <NSObject>

@optional
-(void)excute;
@optional
-(void)undo; @end @interface Command : NSObject<CommandProtocal> @end

CarOnCommand类:

@interface CarOnCommand(){
Car *car;
} @end @implementation CarOnCommand -(instancetype)initWithCar:(Car *)myCar{
self=[super init];
if (self) {
car=myCar;
}
return self;
} -(void)excute{
[car on];
} -(void)undo{
[car off];
} @end

CarOffCommand实现:

@interface CarOffCommand(){
Car *car;
} @end @implementation CarOffCommand -(instancetype)initWithCar:(Car *)myCar{
self=[super init];
if (self) {
car=myCar;
}
return self;
} -(void)excute{
[car off];
} -(void)undo{
[car on];
} @end

DoorOpenCommand类:

@interface  DoorOpenCommand(){
Door *myDoor;
}
@end @implementation DoorOpenCommand -(instancetype)initWithDoor:(Door *)door{
self=[super init];
if (self) {
myDoor=door;
}
return self;
} -(void)excute{
[myDoor open];
} -(void)undo{
[myDoor shut];
} @end
DoorShutCommand
@interface DoorShutCommand(){
Door *myDoor;
}
@end @implementation DoorShutCommand -(instancetype)initWithDoor:(Door *)door{
self=[super init];
if (self) {
myDoor=door;
}
return self;
} -(void)excute{
[myDoor shut];
} -(void)undo{
[myDoor open];
} @end

这里需要提示一样,因为每个命令都会有撤销的功能,因为打开和关闭是两个单独的命令,不同对象的对象也是分开使用不同的命令,每个对象内部关于excute实现的过程会有不同~

Invoker调用者的定义:

@interface EleControl : NSObject

-(instancetype)initWithCommandCount:(NSInteger)count;

-(void)setupCommand:(NSInteger)index onCommand:(Command *)onCommand  offCommand:(Command *)offCommand;

-(void)controlPressedOn:(NSInteger)index;

-(void)controlPressedOff:(NSInteger)index;

-(void)controlPressedUndo;

@end

Invoker的实现:

@interface EleControl(){
Command *undoCommand;
} @property (strong,nonatomic) NSMutableArray *onCommands; @property (strong,nonatomic) NSMutableArray *offCommands; @end @implementation EleControl -(instancetype)initWithCommandCount:(NSInteger)count{
self=[super init];
if (self) {
for (NSInteger i=0; i<count; i++) {
[self.onCommands addObject:[NSNull null]];
[self.offCommands addObject:[NSNull null]];
}
}
return self;
} -(void)setupCommand:(NSInteger)index onCommand:(Command *)onCommand offCommand:(Command *)offCommand{
self.onCommands[index]=onCommand;
self.offCommands[index]=offCommand;
} -(void)controlPressedOn:(NSInteger)index{
Command *cmd=[self.onCommands objectAtIndex:index];
[cmd excute];
undoCommand=cmd;
} -(void)controlPressedOff:(NSInteger)index{
Command *cmd=[self.offCommands objectAtIndex:index];
[cmd excute];
undoCommand=cmd;
} -(void)controlPressedUndo{
[undoCommand undo];
} #pragma mark getter and setter
-(NSMutableArray *)onCommands{
if (!_onCommands) {
_onCommands=[[NSMutableArray alloc]init];
}
return _onCommands;
} -(NSMutableArray *)offCommands{
if (!_offCommands) {
_offCommands=[[NSMutableArray alloc]init];
}
return _offCommands;
} @end

 客户端调用:

    Car *car=[[Car alloc]init];
Command *carOnCommand=[[CarOnCommand alloc]initWithCar:car];
Command *carOffCommand=[[CarOffCommand alloc]initWithCar:car]; Door *door=[[Door alloc]init];
Command *doorOpenCommand=[[DoorOpenCommand alloc]initWithDoor:door];
Command *doorShutCommand=[[DoorShutCommand alloc]initWithDoor:door]; EleControl *control=[[EleControl alloc]initWithCommandCount:2];
[control setupCommand:0 onCommand:carOnCommand offCommand:carOffCommand];
[control setupCommand:1 onCommand:doorOpenCommand offCommand:doorShutCommand];
[control controlPressedOn:0];
[control controlPressedOff:1];
[control controlPressedUndo];
NSLog(@"博客园-FlyElephant");
NSLog(@"http://www.cnblogs.com/xiaofeixiang/");

测试:

关于命令模式实现的比较简单,NSUndoManger算是命令模式的典型应用,在一些线程池,工作队列中,我们只需要将具体的执行的任务包装成命令,当任务可以用的时候执行里面的execute方法,在日志和版本控制系统中回滚,我们会回到之前的稳定的版本,取代当前不能工作的版本也可以理解为命令模式在工程实践中的应用。

iOS开发-命令模式的更多相关文章

  1. iOS开发-代理模式

    代理模式有的时候也被称之为委托模式,但是实际上两者是有分别的,代理模式为另一个对象提供一个替身或占位符访问这个对象,代理对象和控制访问对象属于同一类,委托对象和对象不一定属于同一类.两者都可以控制类的 ...

  2. iOS设计模式 - 命令模式

    前言: 命令对象封装了如何对目标执行指令的信息,因此客户端或调用者不必了解目标的任何细节,却仍可以对他执行任何已有的操作.通过把请求封装成对象,客 户端可 以把它参数化并置入队列或日志中,也能够支持可 ...

  3. iOS开发-工厂模式

    工厂模式算是开发中比较常见的设计模式,简单工厂模式,工厂模式和抽象工厂模式,都属于工厂模式.简单工厂模式(simple factory)是类的创建模式,静态工厂方法(static factory me ...

  4. iOS开发-状态模式

    状态模式允许对象内部状态改变时改变它的行为,对象看起来好像修改了它的类.状态模式看起来和策略模式比较相像,策略模式是将可以互换的行为封装起来,然后通过使用委托的方式,决定使用哪一个行为,状态也是封装行 ...

  5. iOS开发-迭代器模式

    迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示.开发过程中,我们可能需要针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但是我们不希望 ...

  6. iOS开发——工厂模式

    工厂模式很好用,为表诚意,我直接搞个实用的例子放这,解析一个订单的数据,并且这个订单里面可能不止一件商品的做法. 还是直接上代码,不懂的地方,再提出来. 1.在MyOrderDeals.h文件中 #i ...

  7. iOS开发-模板方法模式

    模板方法模式定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤.模板方法模式是由子类决定实现算法中的步骤,工厂方法由子类决定实现哪一 ...

  8. iOS开发-策略模式

    策略(Strategy)模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.策略模式是对算法的包装,是把使用算法的责任和算法本身分割开 ...

  9. 1_Command 游戏开发命令模式

    A dead simple implementation looks like: ``` // simple void InputHandler::handleInput() { if (isPres ...

随机推荐

  1. Hibrenate关系映射(一对一外键关联)

    一.一对一(单向):使用外部索引将其中的一个类作为parent,相对应的一个就是子类,并且参照父 类的主键ID来生成数据库表.(比如:可以将husband中设置一个wife_id对应wife中的主键i ...

  2. git的入门摸索和入门研究

    git官网:https://git-scm.com/ git教程---菜鸟教程:http://www.runoob.com/git/git-tutorial.html git教程---廖雪峰:http ...

  3. 090实战 Hadoop离线项目介绍(不包括程序)

    一:项目场景 1.需求分析 根据用户行为数据进行程序的处理,得到结果保存到关系型数据库中 需要收集用户(系统使用者)在不同客户端上产生的用户行为数据,最终保存到hdfs上 需要明确收集字段的相关信息, ...

  4. centos关机、重启、图形界面与命令行界面切换命令

    1.关机: init0;  poweroff;  halt;  shutdown 2.重启: init1;  reboot; 3.图形界面切换到命令行界面: init3; 或者,修改配置文件: #vi ...

  5. 最短路(Bellman)-Hdu1874畅通工程序

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1874 题目: 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城 ...

  6. Python爬虫之正则表达式的使用(三)

    正则表达式的使用 re.match(pattern,string,flags=0) re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none 参数 ...

  7. Flutter中打造多行列列表GridView组件的使用

    GridView组件.一个可滚动的二维空间数组. 在使用无限加载滚动列表的时候,最先使用的还是ListView组件.但若是要一行显示2列或者更多列的滚动列表,GridView组件更为方便.如下 在向服 ...

  8. Effective Java 第三版——57. 最小化局部变量的作用域

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  9. sass那些事儿

    Sass,Syntactically Awesome StyleSheets,语法样式表.Sass有两种实现,ruby-sass与lib-sass,前者用ruby实现,后者用C/C++实现. 一.Sa ...

  10. dns 监控系统 设计 dns安全威胁的可视化。

    基于DNS大数据分析实现宽带共享监控系统.实现对宽带用户进行有效管理. 本系统基于DNS大数据分析实现宽带共享监控系统,包括以下方面. 1)数据采集:数据采集过程是通过探针采集的方式,从各地市的DNS ...