iOS开发-命令模式
命令模式算是设计模式中比较简单的,最常见的例子是工作任务安排下来进行编程,如果工作任务不需要完成,我们可以取消我们之前完成的代码,也可以理解为回滚撤销操作。这里面涉及到命令模式中的两个对象,一个是动作实现者,一个是行为请求者,我们可以将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开发-命令模式的更多相关文章
- iOS开发-代理模式
代理模式有的时候也被称之为委托模式,但是实际上两者是有分别的,代理模式为另一个对象提供一个替身或占位符访问这个对象,代理对象和控制访问对象属于同一类,委托对象和对象不一定属于同一类.两者都可以控制类的 ...
- iOS设计模式 - 命令模式
前言: 命令对象封装了如何对目标执行指令的信息,因此客户端或调用者不必了解目标的任何细节,却仍可以对他执行任何已有的操作.通过把请求封装成对象,客 户端可 以把它参数化并置入队列或日志中,也能够支持可 ...
- iOS开发-工厂模式
工厂模式算是开发中比较常见的设计模式,简单工厂模式,工厂模式和抽象工厂模式,都属于工厂模式.简单工厂模式(simple factory)是类的创建模式,静态工厂方法(static factory me ...
- iOS开发-状态模式
状态模式允许对象内部状态改变时改变它的行为,对象看起来好像修改了它的类.状态模式看起来和策略模式比较相像,策略模式是将可以互换的行为封装起来,然后通过使用委托的方式,决定使用哪一个行为,状态也是封装行 ...
- iOS开发-迭代器模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示.开发过程中,我们可能需要针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但是我们不希望 ...
- iOS开发——工厂模式
工厂模式很好用,为表诚意,我直接搞个实用的例子放这,解析一个订单的数据,并且这个订单里面可能不止一件商品的做法. 还是直接上代码,不懂的地方,再提出来. 1.在MyOrderDeals.h文件中 #i ...
- iOS开发-模板方法模式
模板方法模式定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤.模板方法模式是由子类决定实现算法中的步骤,工厂方法由子类决定实现哪一 ...
- iOS开发-策略模式
策略(Strategy)模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.策略模式是对算法的包装,是把使用算法的责任和算法本身分割开 ...
- 1_Command 游戏开发命令模式
A dead simple implementation looks like: ``` // simple void InputHandler::handleInput() { if (isPres ...
随机推荐
- HTTP 1.1学习笔记
前言 由于HTTP 1自身的局限性,它不能很好的为用户提供性能良好的WEB服务.于1999年6月正式发布了HTTP1.1标准REC2616,它厘清了之前版本中很多有歧义的地方,而且还新增了很多重要的优 ...
- jsonp原理和实例详解
1.一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨域请求,一律不准:2.不过我们又发现,Web页面上调用js文件时则不受 ...
- LeetCode(58): 最后一个单词的长度
Easy! 题目描述: 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度. 如果不存在最后一个单词,请返回 0 . 说明:一个单词是指由字母组成,但不包含任何空格的字符串. ...
- Laravel框架中的event事件操作
有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作中多 ...
- python接口自动化测试二十:函数写接口测试
# coding:utf-8import requestsimport refrom bs4 import BeautifulSoup # s = requests.session() # 全局的s ...
- python 全栈开发,Day108(客户管理之权限控制,客户管理之动态"一级"菜单,其他应用使用rbac组件,django static文件的引入方式)
一.客户管理之权限控制 昨天的作业,有很多不完善的地方 下载代码,基本实现权限验证 https://github.com/987334176/luffy_permission/archive/v1.2 ...
- java使用md5加密
代码: public String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingExcep ...
- Pycharm里面使用PIL库之后,为什么调用Image的方法不能弹出代码提示,怎样能让代码提示弹出?
之前也碰到了这个问题,安装了pillow后没有代码提示,最后查了半天,发现问题原来非常简单,解决方法也很无厘头. 之所以没有代码提示,仅仅是因为Pycharm没法判断Image.open()返回的对象 ...
- AOJ 2224 Save your cats (Kruskal)
题意:给出一个图,去除每条边的花费为边的长度,求用最少的花费去除部分边使得图中无圈. 思路:先将所有的边长加起来,然后减去最大生成树,即得出最小需要破坏的篱笆长度. #include <cstd ...
- POJ 2385 Apple Catching【DP】
题意:2棵苹果树在T分钟内每分钟随机由某一棵苹果树掉下一个苹果,奶牛站在树#1下等着吃苹果,它最多愿意移动W次,问它最多能吃到几个苹果.思路:不妨按时间来思考,一给定时刻i,转移次数已知为j, 则它只 ...