聊聊Swift中的设计模式---行为型(命令模式)(25)

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情


前言

在面向对象的开发过程中,其实咱们或多或少的都接触过一些设计模式,可能知道或不知道其对应的名称,也不知道其具体使用场景,今天咱们就来说说几种常见的设计模式,帮助你们在开发过程中,更加得心应手。

正文

命令模式

命令模式(Command)解释:

它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。

这里的关键就是包装请求对象放入/移除队列可撤销

命令模式和正常请求的区别就在,正常模式下,行为请求者与行为实现者通常是一种紧耦合的关系,但在特殊情况下,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。所以这时,命令模式就比较适合。

举个生活中的例子:

比如我去餐厅点吃的,点餐员将我点的东西写在纸条上,然后贴在后厨的窗户上,厨师会根据贴纸的顺序去做菜,当我不想要了的时候,点餐员就可以去把贴纸撕下来,当厨师没看见我的那张贴纸时,就不会做我点的菜。

下面咱们再通过一个例子来说明

扫描二维码关注公众号,回复: 14291937 查看本文章

定义一个命令协议(Command),里面包括两个函数execute(执行)

import XCTest

protocol Command {

    func execute()
}
复制代码

写一个简单的命令,继承自命令协议,可以实现简单的操作

class SimpleCommand: Command {

    private var payload: String

    init(_ payload: String) {
        self.payload = payload
    }

    func execute() {
        print("SimpleCommand: See, I can do simple things like printing (" + payload + ")")
    }
}

复制代码

再看一个复杂点的命令

定义一个 Receiver 类,它包含一些重要的业务逻辑。 他们知道如何执行与执行请求相关的各种操作。 事实上,任何类都可以作为接收者。

class Receiver {

    func doSomething(_ a: String) {
        print("Receiver: Working on (" + a + ")\n")
    }

    func doSomethingElse(_ b: String) {
        print("Receiver: Also working on (" + b + ")\n")
    }
}

复制代码

然后定义一个复杂命令(ComplexCommand),里面有个Receiver类的属性,当实例化ComplexCommand命令后,执行execute方法,就可以操作Receiver类里的方法


/// 但是,某些命令可以将更复杂的操作委托给其他对象,称为“接收器”。
class ComplexCommand: Command {

    private var receiver: Receiver

    /// Context data, required for launching the receiver's methods.
    private var a: String
    private var b: String

    /// Complex commands can accept one or several receiver objects along with
    /// any context data via the constructor.
    init(_ receiver: Receiver, _ a: String, _ b: String) {
        self.receiver = receiver
        self.a = a
        self.b = b
    }

    /// Commands can delegate to any methods of a receiver.
    func execute() {
        print("ComplexCommand: Complex stuff should be done by a receiver object.\n")
        receiver.doSomething(a)
        receiver.doSomethingElse(b)
    }
}



复制代码

定义一个调用者(Invoker)类 Invoker 与一个或多个命令相关联。 它向命令发送请求。

class Invoker {

    private var onStart: Command?

    private var onFinish: Command?

    /// Initialize commands.
    func setOnStart(_ command: Command) {
        onStart = command
    }

    func setOnFinish(_ command: Command) {
        onFinish = command
    }

    /// Invoker 不依赖于具体的命令或接收器类。 调用者通过执行命令间接将请求传递给接收者。
    
    func doSomethingImportant() {

        print("Invoker: Does anybody want something done before I begin?")

        onStart?.execute()

        print("Invoker: ...doing something really important...")
        print("Invoker: Does anybody want something done after I finish?")

        onFinish?.execute()
    }
}

复制代码

最后看看 执行和结果

class CommandConceptual: XCTestCase {

    func test() {
        /// The client code can parameterize an invoker with any commands.

        let invoker = Invoker()
        invoker.setOnStart(SimpleCommand("Say Hi!"))

        let receiver = Receiver()
        invoker.setOnFinish(ComplexCommand(receiver, "Send email", "Save report"))
        invoker.doSomethingImportant()
    }
}
复制代码
Invoker: Does anybody want something done before I begin?
SimpleCommand: See, I can do simple things like printing (Say Hi!)
Invoker: ...doing something really important...
Invoker: Does anybody want something done after I finish?
ComplexCommand: Complex stuff should be done by a receiver object.

Receiver: Working on (Send email)

Receiver: Also working on (Save report)
复制代码

结语

命令模式适用场景

  • 如果你需要通过操作来参数化对象, 可使用命令模式。
  • 如果你想要将操作放入队列中、 操作的执行或者远程执行操作, 可使用命令模式。

命令模式优缺点

优点

  • 单一职责原则。 你可以解耦触发和执行操作的类。
  • 开闭原则。 你可以在不修改已有客户端代码的情况下在程序中创建新的命令。
  • 你可以实现撤销和恢复功能。
  • 你可以实现操作的延迟执行。

缺点

  • 代码可能会变得更加复杂, 因为你在发送者和接收者之间增加了一个全新的层次。

扩展阅读 下面还有其他模式

创建型-工厂模式

创建型-建造者模式

结构型-适配器模式

结构型-桥接模式

结构型-组合模式

结构型-装饰器模式

结构型-外观模式

猜你喜欢

转载自juejin.im/post/7110408736572702733
今日推荐