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

    通过继承Thread类来实行多线程 package com.cppdy; //通过继承Thread类来实行多线程 class MyThread extends Thread{ @Override pu ...

  2. LeetCode(43):字符串相乘

    Medium! 题目描述: 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 示例 1: 输入: num1 = &quo ...

  3. liunx centox ssh 配置

    https://www.cnblogs.com/xubing-613/p/6844564.html 一. 查看是否安装了ssh: rpm -qa | grep ssh 重启ssh  service s ...

  4. python 全栈开发,Day107(CRM初始,权限组件之权限控制,权限系统表设计)

    一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...

  5. php安全篇过滤用户输入的参数(转)

    规则 1:绝不要信任外部数据或输入 关于Web应用程序安全性,必须认识到的第一件事是不应该信任外部数据.外部数据(outside data) 包括不是由程序员在PHP代码中直接输入的任何数据.在采取措 ...

  6. git merge简介

    git merge的基本用法为把一个分支或或某个commit的修改合并到现在的分支上.我们可以运行git merge -h和git merge --help查看其命令,后者会直接转到一个网页(git的 ...

  7. Linux 文件系统与挂载详解

    https://blog.csdn.net/baidu_34051990/article/details/60963947

  8. 基于python的机器学习开发环境安装(最简单的初步开发环境)

    一.安装Python 1.下载安装python3.6 https://www.python.org/getit/ 2.配置环境变量(2个) 略...... 二.安装Python算法库 安装顺序:Num ...

  9. 递归回溯groupSum

  10. (转)Java按指定行数读取文件

    package test import java.io.File; import java.io.FileReader; import java.io.IOException; import java ...