设计模式-10.观察者模式

209 阅读2分钟

一句话总结

定义了一种一对多的依赖关系,让多个观察对象同时观察同一个主题对象。当这个主题对象状态发生改变时,会通知所有观察对象,是它们能够自动更新自己,

需求

最近股市比较火,公司的员工都想抽空就看一下股市行情,但又怕被老板发现,就跟前台的小美搞好关系。当老板回来的时候,让小美打内部电话通知大家一下。

Code V1.0

双向耦合的代码

func main() {
    let secretary = Secretary()
    
    let colleague1 = StockObserve(name: "同事1", sub: secretary)
    let colleague2 = StockObserve(name: "同事2", sub: secretary)
    
    secretary.attach(observe: colleague1)
    secretary.attach(observe: colleague2)
    
    secretary.action = "老板回来了"
    secretary.notify()
}

class Secretary {
    var observes: [StockObserve] = []
    var action = ""
    
    func attach(observe: StockObserve) {
        observes.append(observe)
    }
    
    func notify() {
        observes.forEach { (item) in
            item.update()
        }
    }
}

class StockObserve {
    let name: String
    let sub: Secretary
    
    init(name: String, sub: Secretary) {
        self.name = name
        self.sub = sub
    }
    
    func update() {
        print("\(sub.action), \(name) 关闭股票行情,继续工作")
    }
}

Code V2.0

观察者模式实现

static func main() {
    let boss = Boss(subjectState: "老板回来了")

    let lookStockColleague = StockObserve(name: "小明", sub: boss)
    let lookNBAColleague = NBAObserve(name: "小方", sub: boss)

    boss.attach(observe: lookStockColleague)
    boss.attach(observe: lookNBAColleague)

    boss.notify()
}

protocol Subject {
    var observes: [Observe] { get set }
    var subjectState: String { get set }
    
    func attach(observe: Observe)
    func detach(observe: Observe)
    func notify()
}

protocol Observe {
    var name: String { get set }
    var sub: Subject { get set }
    
    func update()
}

class Boss: Subject {
    var observes: [Observe]

    var subjectState: String

    init(subjectState: String) {
        observes = []
        self.subjectState = subjectState
    }

    func attach(observe: Observe) {
        observes.append(observe)
    }

    func detach(observe: Observe) {
        observes.removeAll { (item) -> Bool in
            item.name == observe.name
        }
    }

    func notify() {
        observes.forEach { (item) in
            item.update()
        }
    }
}

//秘书类同Boss类
class Secretary: Subject {
    var observes: [Observe]

    var subjectState: String

    init(subjectState: String) {
        observes = []
        self.subjectState = subjectState
    }

    func attach(observe: Observe) {
        observes.append(observe)
    }

    func detach(observe: Observe) {
        observes.removeAll { (item) -> Bool in
            item.name == observe.name
        }
    }

    func notify() {
        observes.forEach { (item) in
            item.update()
        }
    }
}

class StockObserve: Observe {
    var name: String

    var sub: Subject

    init(name: String, sub: Subject) {
        self.name = name
        self.sub = sub
    }

    func update() {
        print("\(sub.subjectState), \(name)关闭股票行情,继续工作")
    }
}

class NBAObserve: Observe {
    var name: String

    var sub: Subject

    init(name: String, sub: Subject) {
        self.name = name
        self.sub = sub
    }

    func update() {
        print("\(sub.subjectState), \(name)关闭NBA直播,继续工作")
    }
}

适用场景

当一个对象更改时,需要同时更改另外一个或者多个对象时,使用观察者模式比较合适。