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

    1 折腾 php nodejs 到一起 nodejs当然很火,就像着火了一样,但是必须承认要搭建一个前端的demo开发环境还是PHP靠谱, windows下可以非常的集成套件,比如http://www ...

  2. python 全栈开发,Day73(django多表添加,基于对象的跨表查询)

    昨日内容回顾 多表方案: 如何确定表关系呢? 表关系是在2张表之间建立的,没有超过2个表的情况. 那么相互之间有2条关系线,先来判断一对多的关系. 如果其中一张表的记录能够对应另外一张表的多条记录,那 ...

  3. visual studio 2015百度云下载

    visual studio 2015百度云下载 https://pan.baidu.com/s/1b198Zo3mX5_zA2VX3xRRfw 提取码: 关注公众号[GitHubCN]回复2015获取

  4. php 发送超大数据处理

    set_time_limit(0);//设置永不超时 ignore_user_abort(); //设置客户端断开,继续处理 //总数 $allusercount= $this->gamedb_ ...

  5. day14--前端HTML、CSS

        HTML是一个裸体的人,CSS穿上华丽的衣服,JS动起来.     HTML 1. -一套规则,浏览器识别的规则 2. 开发者: 学习HTML规则 开发后台程序 - 写HTML文件(充当模板的 ...

  6. Linux学习之用户管理命令与用户组管理命令(十五)

    Linux学习之用户管理命令与用户组管理命令 目录 用户管理命令 用户添加命令useradd 修改用户密码passwd 修改用户信息usermod 修改用户密码状态chage 删除用户userdel ...

  7. Dart语言特性必备了解!

    学习Dart语言,必须将以下的概念熟记于心: 在dart语言中,一切皆为对象.所有的对象都是一个类的实例.甚至整数.函数.null也看做是对象.所有的对象都继承于Object类 尽管Dart是强类型语 ...

  8. 深度学习(TensorFlow)环境搭建:(二)Ubuntu16.04+1080Ti显卡驱动

    前几天把刚拿到了2台GPU机器组装好了,也写了篇硬件配置清单的文章——<深度学习(TensorFlow)环境搭建:(一)硬件选购和主机组装>.这两台也在安装Ubuntu 16.04和108 ...

  9. 图解 Java 内存模型

    图解 Java 内存模型 (图片来自于:http://www.cnblogs.com/zhangs1986/p/7903722.html)

  10. AGC027 C - ABland Yard 拓扑排序

    目录 题目链接 题解 代码 题目链接 AGC027 C - ABland Yard 题解 发现有解的充要条件是有一个形为AABBAABBAABB的环 此时每一个点至少与两个不同颜色的点相连 对于初始不 ...