一 : 应用场景
当需要将方法调用包装成一个对象,以延时方法调用,或者让其他组件在对其内部实现细节不了解的情况下进行调用的时候可以使用命令模式
场景一:应用程序支持撤销和恢复
场景二:记录请求日志,当系统故障这些命令可以重新被执行
场景三:想用对象参数化一个动作以执行操作,并且用不同命令对象来替换回调函数
二: 角色划分
命令模式规范
1、角色一:接收者->Reciever
2、角色二:命令接口->CommandProtocol(协议)
3、角色三:具体命令->ConcrateCommand
4、角色四:请求者->Invoker
三: 具体命令分类
1:动态命令:
如果存在较多命令对象,会造成代码冗余,因此可以创建动态命令解决;
2: 泛型命令:
将接收者的类型设置为泛型,根据具体的接收者类型,动态的创建详情的接收者对象;
3: 复合命令:
同时执行多个命令;
4: 并发处理:
多线程情况下,会导致多个命令并发,报异常; 队列,同步代码块
5: 闭包命令:
block代码块代替协议
四: 具体代码
import Foundation /********************************** 协议 *********************************/ protocol CommandProtocol { func execute() } /********************************** 接收者 *********************************/ import Foundation class Receiver { init() {} func debugFunc() { print("debug方法执行...") } func releaseFunc() { print("release方法执行...") } } /********************************** 动态命令 *********************************/ import Foundation class DynamicCommand: CommandProtocol { private var receiver: Receiver private var commandBlock: (Receiver) -> () init(paramReceiver: Receiver, paramBlock: @escaping (Receiver) -> ()) { self.commandBlock = paramBlock self.receiver = paramReceiver } func execute() { self.commandBlock(self.receiver) } class func sharedCommand(paramReciever: Receiver, paramBlock: @escaping (Receiver) -> ()) -> CommandProtocol { return DynamicCommand(paramReceiver: paramReciever, paramBlock: paramBlock) } } /********************************** 请求者 *********************************/ import Foundation class InvokeManager { private var receiver: Receiver private var commands = [CommandProtocol]() init(paramReceiver: Receiver) { self.receiver = paramReceiver } func debugPrint() { /** 方法是一种特殊的闭包, 将方法作为闭包传递,不是类方法调用*/ addMethodCommands(method: Receiver.debugFunc) self.receiver.debugFunc() } func releasePrint() { addMethodCommands(method: Receiver.releaseFunc) self.receiver.releaseFunc() } func addMethodCommands(method: @escaping (Receiver) -> ()->() ) { self.commands.append(DynamicCommand(paramReceiver: self.receiver, paramBlock: { (returnReceiver) in method(returnReceiver)() })) } //撤销上一步 func undo() { print("撤销一步") if self.commands.count > 0 { self.commands.removeLast().execute() } } //撤销所有 func undoAll() { print("撤销所有") for item in self.commands { item.execute() } self.commands.removeAll() } }
复合命令
import Foundation /********************************** 复合命令 *********************************/ class WrapperCommands: CommandProtocol { private var commands: [CommandProtocol] init(commands: [CommandProtocol]) { self.commands = commands } func execute() { for commands in self.commands { commands.execute() } } } /********************************** 复合命令请求者 *********************************/ import Foundation class WrapperInvokeManager { private var receiver: Receiver private var commands = [CommandProtocol]() init(paramReceiver: Receiver) { self.receiver = paramReceiver } func debugPrint() { addMethodCommands(method: Receiver.debugFunc) self.receiver.debugFunc() } func releasePrint() { addMethodCommands(method: Receiver.releaseFunc) self.receiver.releaseFunc() } func addMethodCommands(method: @escaping (Receiver) -> ()->() ){ self.commands.append(DynamicCommand(paramReceiver: self.receiver, paramBlock: { (returnReceiver) in method(returnReceiver)() })) } func undo() { print("撤销一步") if self.commands.count > 0 { self.commands.removeLast().execute() } } func undoAll() { print("撤销所有") let wrapCommands = WrapperCommands(commands: self.commands) wrapCommands.execute() self.commands.removeAll() } }
泛型命令
/********************************** 泛型命令 *********************************/ import Foundation class GenericsCommands<T>: CommandProtocol { private var receiver: T private var commandsBlock: (T) -> () init(paramReceiver: T, paramBlock: @escaping (T) -> ()) { self.receiver = paramReceiver self.commandsBlock = paramBlock } func execute() { self.commandsBlock(self.receiver) } } /********************************** 泛型命令请求者 *********************************/ import Foundation class GenericsInvokeManager { private var receiver: Receiver private var commands = [CommandProtocol]() init(paramReceiver: Receiver) { self.receiver = paramReceiver } func debugPrint() { addMethodCommands(method: Receiver.debugFunc) self.receiver.debugFunc() } func releasePrint() { addMethodCommands(method: Receiver.releaseFunc) self.receiver.releaseFunc() } func addMethodCommands(method: @escaping (Receiver) -> ()->()) { self.commands.append(GenericsCommands<Receiver>(paramReceiver: self.receiver, paramBlock: { (returnReceiver) in method(returnReceiver)() })) } func undo() { print("撤销一步") if self.commands.count > 0 { self.commands.removeLast().execute() } } func undoAll() { print("撤销所有") let wrapCommands = WrapperCommands(commands: self.commands) wrapCommands.execute() self.commands.removeAll() } }
闭包命令
import Foundation class BlockInvokeManager { typealias CommandBlock = (Receiver) -> () private var receiver: Receiver private var commands = [CommandBlock]() init(paramReceiver: Receiver) { self.receiver = paramReceiver } func debugPrint() { addMethodCommands(method: Receiver.debugFunc) self.receiver.debugFunc() } func releasePrint() { addMethodCommands(method: Receiver.releaseFunc) self.receiver.releaseFunc() } func addMethodCommands(method: @escaping (Receiver) -> ()->()) { self.commands.append { (returnReceiver) in method(returnReceiver)() } } func undo() { print("撤销一步") if self.commands.count > 0 { // self.commands.removeLast().execute() let command = self.commands.removeLast() command(self.receiver) } } func undoAll() { print("撤销所有") for command in self.commands { command(self.receiver) } self.commands.removeAll() } }
demo地址(包含OC和swift版本): https://github.com/hongsejuxiong/designMode