命令模式算是设计模式中比较简单的,最常见的例子是工作任务安排下来进行编程,如果工作任务不需要完成,我们可以取消我们之前完成的代码,也可以理解为回滚撤销操作。这里面涉及到命令模式中的两个对象,一个是动作实现者,一个是行为请求者,我们可以将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. Range:HTML5中的新型Input类型

    <div style="width:100%; height:100%; position:fixed; top:0; left:0; z-index:100000; backgrou ...

  2. composer卸载重装

    $ composer remove phpunit/phpunit --dev $ composer require phpunit/phpunit --dev

  3. Iterator 接口

    首先要从foreach说起,我们都知道对象,数组和对象可以被foreach语法遍历,数字和字符串却不行.其实除了数组和对象之外PHP内部还提供了一个 Iterator 接口,实现了Iterator接口 ...

  4. Mac 下 Redis 5.0 的卸载与安装

    卸载 停止 redis 服务器 redis-cli shutdown 检测 #检测后台进程是否存在 ps -ef |grep redis #检测6379端口是否在监听 netstat -lntp | ...

  5. Android Handler的内存泄露问题+解决方案

    谈谈handler的内存泄露问题 再来看看我们的新建Handler的代码: private Handler mHandler = new Handler() { @Override public vo ...

  6. (第4篇)hadoop之魂--mapreduce计算框架,让收集的数据产生价值

    摘要: 通过前面的学习,大家已经了解了HDFS文件系统.有了数据,下一步就要分析计算这些数据,产生价值.接下来我们介绍Mapreduce计算框架,学习数据是怎样被利用的. 博主福利 给大家赠送一套ha ...

  7. POJ 3262 Protecting the Flowers 【贪心】

    题意:有n个牛在FJ的花园乱吃.所以FJ要赶他们回牛棚.每个牛在被赶走之前每秒吃Di个花朵.赶它回去FJ来回要花的总时间是Ti×2.在被赶走的过程中,被赶走的牛就不能乱吃 思路: 先赶走破坏力大的牛假 ...

  8. [ZJOI2012]数列

    超级水的题还wa了一次 首先很容易发现其实就只有两个值并存 然后 要注意把数组初始化啊...可能后面有多余的元素(对拍的时候由于从小到大就没跑出错) #include <bits/stdc++. ...

  9. 【AtCoder】CODE FESTIVAL 2017 qual A

    A - Snuke's favorite YAKINIKU -- #include <bits/stdc++.h> #define fi first #define se second # ...

  10. 安装oracle11g时遇到INS-13001环境不满足最低要求

    在安装oracle11g,点击setup.exe之后,弹出了如下提示框: 解决方法: 首先,打开你解压后的database文件夹,找到stage,然后cvu,找到cvu_prereq.xml文件,用记 ...