• Category: behavioral
  • Type: object
  • Motivation: defines a dependency between objects so that whenever an object change its state, all its dependents are notified

diagram

do {
    var podcast = Podcast()
    let foo = Listener(name: "foo")
    let bar = Listener(name: "bar")
    podcast.add(subscriber: foo)
    podcast.add(subscriber: bar)

    podcast.release("Episode 1: Hello World")
}
protocol Publisher
{
    var subscribers: [Subscriber] {get set}

    mutating func add(subscriber: Subscriber)
    mutating func remove(at index: Int)
    func notify()
}

extension Publisher
{
    func notify()
    {
        for listener in subscribers {
            listener.update(self)
        }
    }

    mutating func add(subscriber: Subscriber)
    {
        subscribers.append(subscriber)
    }

    mutating func remove(at index: Int)
    {
        subscribers.remove(at: index)
    }
}

class Podcast: Publisher
{
    var subscribers: [Subscriber] = []
    var episode = ""

    func release(_ episode: String)
    {
        self.episode = episode
        notify()
    }
}
protocol Subscriber
{
    func update(_ publisher: Publisher)
}

struct Listener: Subscriber
{
    var name: String

    func update(_ publisher: Publisher)
    {
        guard let podast = publisher as? Podcast else {
            return
        }
        print("\(name) receives notification of \(podast.episode)")
    }
}