前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式---命令模式

设计模式---命令模式

作者头像
Wu_Candy
发布2022-07-04 20:18:25
1940
发布2022-07-04 20:18:25
举报
文章被收录于专栏:无量测试之道
这是无量测试之道的第170篇原创

什么是命令模式?:行为参数化的模式

作用?:降低代码重合度

1.命令模式介绍

命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志。以及支持可撤销的操作。   讲一个模式时,从定义上是不能体会其中的技巧,所以接着我会通过举例子来说明命令模式。

1.1.举例:

 假设某个公司需要设计一个多用功能的遥控器。基本的需求如下:

  • 该遥控器有可以控制风扇,白炽灯,热水器等等的多对开关,
  • 可能还有其他的电器,暂时不做其功能,但是希望可以保留接口,用的时间可以方便的扩展。
  • 还需要有个按钮,可以撤销上一步的操作。

1.2. 问题

  由于各种电器的开关方法都不一样,而且还存在一个待扩展的电器,如果没有学习命名模式之前,我们在设置扩展的开关时,会出现的问题是什么呢?假设现在有电视,冰箱还可能会用到遥控器,那么我们会在最后一个开关上写if else,当然如果哪一天又多了一个大门也加入了我们的遥控的行列,这样我们继续加if else ,很显然随着电器的高速发展,会有多个需要遥控可以控制的,从而耦合度会越来越高。

1.3. 解决问题

  采用命令模式。我们可以先定义好我们的风扇,白炽灯,热水器。然后定义其分别的开关命令,每个命令都有自己对应的电器引用,而且会在命令的Excute中包装电器的开或者关,最后需要把命令安装到遥控器上面,在遥控器上每个按钮都对应有自己的响应方法。说白了,就是将一系列的请求命令封装起来,不直接调用真正执行者的方法,这样比较好扩展。

2. 命令模式的术语以及其之间关系介绍

Command(抽象命令类):抽象出命令对象,可以根据不同的命令类型。写出不同的实现类 ConcreteCommand(具体命令类):实现了抽象命令对象的具体实现 Invoker(调用者/请求者):请求的发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令之间存在关联。在程序运行时,将调用命令对象的execute() ,间接调用接收者的相关操作。 Receiver(接收者):接收者执行与请求相关的操作,真正执行命令的对象。具体实现对请求的业务处理。未抽象前,实际执行操作内容的对象。 Client(客户端):在客户类中需要创建调用者对象,具体命令类对象,在创建具体命令对象时指定对应的接收者。发送者和接收者之间没有直接关系,都通过命令对象来调用。

2.1. 本文以白炽灯为例进行分析

  对象1:家里有一个可遥控的白炽灯;

对象2:遥控器【可以控制白炽灯:ON/OFF】;

对象3:主人;

对象

对应命令模式中的术语

白炽灯

Client

遥控器

Receiver

主人

Invoker

遥控器以手机屏幕上的 ON OFF来代替; 白炽灯以屏幕的背景颜色白色 黑色来代替 主人以使用该手机的人来代替

2.2. 代码实现

  下面主要看2个核心类:Commond类、CommondManager类,具体的在代码中有详细的注释

代码语言:javascript
复制
class Commond: NSObject {
    public typealias CommondCompletionClosure = (_ cmd: Commond) -> Void
    var completion: CommondCompletionClosure?

    func exexute() {
        //override to subclass
        self.done()
    }

    func cancle() {
        self.completion = nil
    }

    func done() {
        //异步回到主队列,为了考虑多线程的情况,才采用了这种方式
        DispatchQueue.main.async {
            if self.completion != nil {
                self.completion!(self)
            }
            self.completion = nil
            CommondManager.share.arrayCoMmmands.remove(at: CommondManager.share.arrayCoMmmands.firstIndex(of: self) ?? 0)
        }
    }
}
代码语言:javascript
复制
class CommondManager: NSObject {
    var arrayCoMmmands = [Commond?]()
    static let share = CommondManager()
    public typealias CommondCompletionClosure = (_ cmd: Commond) -> Void
    func executeCommand(cmd: Commond?, completion: @escaping CommondCompletionClosure) {
        if cmd != nil {
            //如果正在执行则不做处理,否则添加并执行命令
            if !isExcutingCommond(cmd: cmd) {
                CommondManager.share.arrayCoMmmands.append(cmd)
                 cmd?.completion = completion
                //执行命令
                cmd?.exexute()
            }
        }
    }
    func cancleCommand(cmd: Commond?) {
        if cmd != nil {
            CommondManager.share.arrayCoMmmands.remove(at: CommondManager.share.arrayCoMmmands.firstIndex(of: cmd) ?? 0)
            cmd?.cancle()
        }
    }
    private func isExcutingCommond(cmd: Commond?) -> Bool {
        if cmd != nil {
            for Acmd in CommondManager.share.arrayCoMmmands {
                if cmd == Acmd { return true}
            }
        }
        return false
    }
}

2.3. 关于撤销操作

  可以直接CommondManager.share.arrayCoMmmands.removeLast() 或者在Commond类里面加一个rollBack()方法,   举例:以LightONCommond为例,实现rollBack()方法。

代码语言:javascript
复制
class LightONCommond: Commond {
    var lightReceiver: LightReceiver?

    override init() {}
    convenience init(lightReceiver: LightReceiver) {
        self.init()
        self.lightReceiver = lightReceiver
    }
    
    override func exexute() {
        lightReceiver?.LightOn() //"灯开"
        CommondManager.share.rollBackCommond = self
    }

    override func rollBack() { //撤销
        lightReceiver?.LightOff()
    }
}

3. 总结:

  命令模式主要通过中介Command实现了发出命令者和命令的执行者,也即Invoke类和Receiver的松耦合。本文先给出了命令模式的定义,通过遥控器的例子详细的讲解了命令模式的使用以及实现。最后,也介绍了命令模式撤销操作的实现。

end

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 无量测试之道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是命令模式?:行为参数化的模式
    • 1.命令模式介绍
      • 1.2. 问题
        • 1.3. 解决问题
          • 2. 命令模式的术语以及其之间关系介绍
            • 2.1. 本文以白炽灯为例进行分析
            • 2.2. 代码实现
            • 2.3. 关于撤销操作
          • 3. 总结:
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档