命令模式是解决了命令的请求者和命令的实现者之间的耦合关系,命令的扩展性,命令的统一性(队列、撤销/恢复、记录日志等等),命令模式有五个重要的对象Command,ConcreteCommand,Receiver,Invoker与Client.
① 抽象命令(Command):定义命令的接口,声明执行的方法.
② 具体命令(ConcreteCommand):具体命令,实现要执行的方法,它通常是“虚”的实现;通常会有接收者,并调用接收者的功能来完成命令要执行的操作.
③ 接收者(Receiver):真正执行命令的对象。任何类都可能成为一个接收者,只要能实现命令要求实现的相应功能.
④ 调用者(Invoker):要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口.
⑤ 客户端(Client):命令由客户端来创建,并设置命令的接收者.
生活中的洗衣机洗衣服的场景比较符合命令模式,实现如下:
洗衣机:
class WashMachine {
func wash() {
print("洗衣服")
}
func dry() {
print("脱水")
}
func unWash() {
print("终止洗衣服")
}
}
命令:
class Command {
func execute() { }
func undo() { }
}
class WashCommand: Command {
var washMachine:WashMachine?
convenience init(machine:WashMachine) {
self.init()
washMachine = machine
}
override func execute() {
washMachine?.wash()
washMachine?.dry()
}
override func undo() {
washMachine?.unWash()
}
}
执行者:
class Person {
var commands:[Command] = []
func addCommand(command:Command) {
commands.append(command)
}
func executeCommand(index:Int) {
let command:Command? = commands[index]
command?.execute()
}
func undoCommand(index:Int) {
let command:Command? = commands[index]
command?.undo()
}
}
测试代码:
@IBAction func executeAction(_ sender: UIButton) {
self.person?.executeCommand(index: 0)
}
@IBAction func cancelAction(_ sender: UIButton) {
self.person?.undoCommand(index: 0)
print("简书---FlyElephant")
}
func setUp() {
let machine:WashMachine = WashMachine()
let washCommand:WashCommand = WashCommand(machine: machine)
self.person = Person()
self.person?.addCommand(command: washCommand)
}
命令模式对功能方法的抽象提升到对象层面来实现,降低了系统的耦合度,比较常见的场景是队列,日志,很容易将各种命令组合实现业务需求.
命令模式的缺点非常明显,一个命令绑定一个命令执行者,如果业务较复杂,会导致过多的具体命令类.