持续创作,加速生长!这是我参加「日新方案 6 月更文应战」的第28天,点击查看活动详情


前言

在面向目标的开发过程中,其实我们或多或少的都接触过一些设计形式,可能知道或不知道其对应的称号,也不知道其具体运用场景,今天我们就来说说几种常见的设计形式,协助你们在开发过程中,愈加称心如意。

正文

调查者形式

调查者形式是一种订阅形式,可在被调查的目标事情产生时告诉多个“调查”该目标的其他目标。

这个就像iOS中的observe,当被调查的目标变了,调查者就会收到告诉,做出响应改动。

在现实生活中,就像刚出来的PS+订阅服务,我订阅了索尼的PS+,如果PS+游戏库中的游戏更新了,我就会收到能够下载的告诉。不用重新在去查找下载了。(ps,索尼罪孽深重)索尼就担任保护我们这些订阅者列表,当有人不想订阅了,索尼就将这个人从订阅列表中移除。那这个人就不会收到订阅信息的更新提示了。

接下来,我们再用一个例子说明一下。

首先,界说一个主题(Subject),里面界说一个包含调查者(Observer)的数组,然后分别完成将调查者结合(attach(observer: Observer) )、分离(deattach(observer: Observer))和告诉(notify())的办法

state改动时 就会调用notify()办法

notify()办法就是将observes数组中,所有的调查者目标都执行update()办法

class Subject {
    private var observes: [Observer] = []
    private var _state: Int = 0
    var state: Int {
        set {
            _state = newValue
            notify()
        }
        get {
            return _state
        }
    }
    func attach(observer: Observer) {
        observes.append(observer)
    }
    func deattach(observer: Observer) {
        guard let index = observes.firstIndex(where: {$0.id == observer.id}) else {return}
        observes.remove(at: index)
    }
    func notify() {
        observes.forEach { (obs) in
            obs.update()
        }
    }
}

界说一个调查者的协议


protocol Observer {
    var id : String {get set}
    var subject: Subject { get set }
    func update()
}

界说三个调查者的类(BinaryObserverOctalObserverHexaObserver)都恪守调查者协议(Observer)并完成了update()的办法

class BinaryObserver: Observer {
    var subject: Subject
    var id: String
    init(id: String, subject: Subject) {
        self.id = id
        self.subject = subject
        self.subject.attach(observer: self)
    }
    func update() {
        let val = String(subject.state, radix: 2, uppercase: true)
        print("二进制: (val)")
    }
}
class OctalObserver: Observer {
    var subject: Subject
    var id: String
    init(id: String, subject: Subject) {
        self.id = id
        self.subject = subject
        self.subject.attach(observer: self)
    }
    func update() {
        let val = String(subject.state, radix: 8, uppercase: true)
        print("八进制: (val)")
    }
}
class HexaObserver: Observer {
    var subject: Subject
    var id: String
    init(id: String, subject: Subject) {
        self.id = id
        self.subject = subject
        self.subject.attach(observer: self)
    }
    func update() {
        let val = String(subject.state, radix: 16, uppercase: true)
        print("十六进制: (val)")
    }
}

接下来,我们来看看完成。

let subject = Subject()
HexaObserver(id: "hexa", subject: subject)
OctalObserver(id: "octal", subject: subject)
BinaryObserver(id: "binary", subject: subject)
print("输入5:")
subject.state = 5
print("\n输入10")
subject.state = 10

输出结果:

输入5:
十六进制: 5
八进制: 5
二进制: 101
输入10
十六进制: A
八进制: 12
二进制: 1010

能够发现,每次改动subject.state 的值时,调查者都会收到改动的消息,并执行函数。

结语

调查者形式适合运用场景

  • 当一个目标状态的改动需求改动其他目标,或实践目标是事先未知的或动态改变的时,可运用调查者形式。
  • 当运用中的一些目标必须调查其他目标时,可运用该形式。但仅能在有限时间内或特定情况下运用。

调查者形式优缺点

长处

  • 开闭准则。你无需修正发布者代码就能引进新的订阅者类(如果是发布者接口则可轻松引进发布者类)。

  • 你能够在运行时树立目标之间的联络。

缺点

  • 订阅者的告诉顺序是随机的。

扩展阅览 下面还有其他形式

创建型-工厂形式

创建型-建造者形式

结构型-适配器形式

结构型-桥接形式

结构型-组合形式

结构型-装修器形式

结构型-外观形式