聊聊Swift中的设计模式---行为型(观察者模式)

持续创作,加速成长!这是我参与「掘金日新计划 · 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 的值时,观察者都会收到改变的消息,并执行函数。

结语

观察者模式适合应用场景

  • 当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时, 可使用观察者模式。
  • 当应用中的一些对象必须观察其他对象时, 可使用该模式。 但仅能在有限时间内或特定情况下使用。

观察者模式优缺点

优点

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

  • 你可以在运行时建立对象之间的联系。

缺点

  • 订阅者的通知顺序是随机的。

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

创建型-工厂模式

创建型-建造者模式

结构型-适配器模式

结构型-桥接模式

结构型-组合模式

结构型-装饰器模式

结构型-外观模式

猜你喜欢

转载自juejin.im/post/7111495640441421860