如何在观察者模式中创建一个 class 实例?

How to create a class instance in Observer pattern?

我在下面的代码中实现了一个观察者模式。但是,我不确定如何创建 SeasonSubject class 的实例以调用 addObserver() 函数? 我不想在我的视图控制器中创建它。请参考以下代码。

//
//  SeasonViewController.swift
//  PhotoCalender
//
//  Created by Suraj M Gaikwad on 09/07/21.
//

import UIKit

enum Season: String {
    case summer
    case winter
    case monsoon
    case none
}

protocol SeasonObserver {
    func onSeasonChange(_season: Season)
}

class PhotoframeObserver: SeasonObserver {
    var delegate: SeasonViewControllerDelegate?
    
    init(_delegate: SeasonViewControllerDelegate) {
        delegate = _delegate
    }
    
    func onSeasonChange(_season: Season) {
        switch _season {
        case .monsoon, .summer, .winter:
            delegate?.changeTheLayoutPer(_season: _season)
        case .none:
            debugPrint("none")
        }
    }
}

class PhotoDetailsObserver: SeasonObserver {
    
    var delegate: SeasonViewControllerDelegate?
        
    init(_delegate: SeasonViewControllerDelegate) {
        delegate = _delegate
    }
    
    func onSeasonChange(_season: Season) {
        switch _season {
        case .monsoon, .summer, .winter:
            delegate?.changeTheTitle(_season: _season)
        case .none:
            debugPrint("none")
        }
    }
}

protocol SeasonSubjectProtocol {
    func informTheSeasonChange(_season: Season)
}

class SeasonSubject: SeasonSubjectProtocol {
    
    private var _season = Season.none
        
    var changedSeason: Season {
        get {
            _season
        }
        set {
            _season = newValue
        }
    }
    
    private var seasonObserver = [SeasonObserver]()
    
    func addObserver(_observer: SeasonObserver) {
        seasonObserver.append(_observer)
    }
    
    func removeObserver(_observer: SeasonObserver) {
//        seasonObserver.remove(at: 0)
    }
    
    private func notifyObserver() {
        seasonObserver.forEach { [=11=].onSeasonChange(_season: _season)
        }
    }
    
    func informTheSeasonChange(_season: Season) {
        changedSeason = _season
    }
    
    deinit {
        seasonObserver.removeAll()
    }
}


protocol SeasonViewControllerDelegate {
    func changeTheLayoutPer(_season: Season)
    func changeTheTitle(_season: Season)
}

class SeasonViewController: UIViewController {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var backgroundView: UIView!
    @IBOutlet weak var seasonTitle: UILabel!
    
    var delegate: SeasonSubjectProtocol?

    var count = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        self.imageView.image = UIImage()
        self.backgroundView.backgroundColor = .white
        self.seasonTitle.text = "none"
    }
    
    @IBAction func changeTheSeason(_ sender: UIButton) {
        if count > 2 {
            count = 0
            return
        }
        
        if count == 0 {
            delegate?.informTheSeasonChange(_season: Season.summer)
        }
        if count == 1 {
            delegate?.informTheSeasonChange(_season: Season.winter)
        }
        if count == 2 {
            delegate?.informTheSeasonChange(_season: Season.monsoon)
        }
        
        count += 1
    }
}

extension SeasonViewController: SeasonViewControllerDelegate {
    
    func changeTheLayoutPer(_season: Season) {
        switch _season {
        case .monsoon:
            self.imageView.image = UIImage()
            self.backgroundView.backgroundColor = .gray
        case .summer:
            self.imageView.image = UIImage()
            self.backgroundView.backgroundColor = .orange
        case .winter:
            self.imageView.image = UIImage()
            self.backgroundView.backgroundColor = .blue
        case .none:
            debugPrint("none")
            self.imageView.image = UIImage()
            self.backgroundView.backgroundColor = .white
        }
    }
    
    func changeTheTitle(_season: Season) {
        switch _season {
        case .monsoon, .summer, .winter, .none:
            self.seasonTitle.text = _season.rawValue
        }
    }
}

我想创建一个 SeasonSubject() 实例 class。我想调用 addObserver 和 removeObserver() 方法。

您可以创建 SeasonSubject 作为单例实例,它已经维护了一个观察者数组,因此多个观察者可以在整个应用程序中使用同一个实例。

class SeasonSubject: SeasonSubjectProtocol {
    static let shared = SeasonSubject()
}

你现在需要做的就是 - 从你想要的地方调用这个单例实例的 addObserver / removeObserver

class ViewController: UIViewController {

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        SeasonSubject.shared.addObserver(self)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        SeasonSubject.shared.removeObserver(self)
    }
}

注意:您必须确保这些 add/remove 调用是平衡的,否则您将落入观察者永远不会被释放的陷阱。

如果你想远离这个问题 - 你应该考虑一个基于 NotificationCenter 的实现,你的观察者永远不会有永远保留在内存中的风险。