【问题标题】:Data passing between Objects without introducing tight coupling?对象之间的数据传递而不引入紧密耦合?
【发布时间】:2018-06-16 14:46:00
【问题描述】:

我正在使用委托、数据源模式在 iOS 中实现精益视图控制器,我确实将 DataSource 和 Delegate 分离为单独的对象。

这段代码可以在操场上执行

// Calender Delegate
protocol CalenderDelegate: class{
    func calender(_ calender: Calender, willDisplay year:Int)
    func calender(_ calender: Calender, didSelect date: Date)
    func calenderShouldChange(_ calender: Calender) -> Bool
}

// Calender DataSource

protocol CalenderDataSource{
    func calender(_ calender: Calender, eventsFor date: Date) -> [String]
    func calender(_ calender: Calender, add event: String, to date: Date)
}

// Calander Object

class Calender{
    weak var delegate: CalenderDelegate?
    var dataSource: CalenderDataSource?
    var selectedDate: Date = Date()
    var currentYear: Int = 2018

    func changeDate(to date: Date){
        self.selectedDate = date
        delegate?.calender(self, didSelect: date)
        if let items = dataSource?.calender(self, eventsFor: date){
            print("Events for \(date) are")
            items.forEach{print($0)}
        }
        else{
            print("This is a rest day not event hurrrhhhhaaa!")
        }
    }

    func changeYear(to year: Int) {
        if delegate?.calenderShouldChange(self) ?? true{
            delegate?.calender(self, willDisplay: year)
            self.currentYear = year
            print(year)
        }
    }


    func add(event: String){
        dataSource?.calender(self, add: event, to: selectedDate)
    }
}

// Datasource

class RemindersCalenderDataSource: CalenderDataSource{

    func calender(_ calender: Calender, eventsFor date: Date) -> [String] {
        return ["Event 1","Event 2","Event 3","Event 4","Event 4"]
    }
    func calender(_ calender: Calender, add event: String, to date: Date) {
        print("Events for date are \(event) \(date).")
    }
}
protocol ReminderPresenting {
    func yearChanged(to year: Int)
}

// Delegate
class RemindersCalenderDelegate: CalenderDelegate{

    var parentController: ReminderPresenting?

    func calender(_ calender: Calender, willDisplay year: Int) {
        self.parentController?.yearChanged(to: year)
        // self.title = "Year: \(year)"

    }
    func calender(_ calender: Calender, didSelect date: Date) {
        print("You selected date \(date)")
    }
    func calenderShouldChange(_ calender: Calender) -> Bool {
        return true
    }
}

//Gernal Object like ViewController
class Reminders: ReminderPresenting{
    var title = "Year: 2200"
    var calender = Calender()

    init() {
        calender.delegate = RemindersCalenderDelegate()
        calender.dataSource = RemindersCalenderDataSource()
    }
    func yearChanged(to year: Int) {
        self.title = "Year: \(year)"
        print(self.title)
    }
}

我的问题是

如何在 RemindersCalenderDelegate 的 willDisplay 方法中设置 Reminders 类的 title 属性,而不会使两个对象产生高耦合。

不接受此解决方案

// In RemindersCalenderDelegate 
var parentController: Reminders?

func calendar(_ calendar: Calendar, willDisplay year: Int) {
    parentController?.title = "Year: \(year)"
}

示例来自:Paul Hudson。 “Swift 设计模式。”书。

【问题讨论】:

    标签: ios swift design-patterns delegates


    【解决方案1】:

    因此,如果您想在没有紧密耦合的情况下引入单向通信,您可以使用闭包以一种通用方式将信息传回,并让消费者控制将数据绑定到其本地控件。

    通过你所拥有的,我认为这是正确的关系。如果它有助于保持代码整洁,您还可以为回调类型键入别名。

    class RemindersCalenderDelegate: CalenderDelegate{
    
        let yearSelectionCallback: (Int) -> ()
    
        init(yearSelectionCallback: (Int) -> ()) {
            self.yearSelectionCallback = yearSelectioncallback
        }
    
        func calender(_ calender: Calender, willDisplay year: Int) {
            yearSelectionCallback(year)
        }
        func calender(_ calender: Calender, didSelect date: Date) {
            print("You selected date \(date)")
        }
        func calenderShouldChange(_ calender: Calender) -> Bool {
            return true
        }
    }
    
    class Reminders: ReminderPresenting{
        var title = "Year: 2200"
        var calender = Calender()
    
        init() {
           calender.delegate = RemindersCalenderDelegate(yearChangedCallback: {
               [weak self]
               year in
               self?.yearChanged(to: year)
           })
           calender.dataSource = RemindersCalenderDataSource()
        }
    
        func yearChanged(to year: Int) {
           self.title = "Year: \(year)"
           print(self.title)
        }
    }
    

    当然,请记住,这使 RemindersCalendarDelegate 无法了解 ReminderPresenting,但无助于让 ReminderPresenting 实施者了解 RemindersCalendarDelegate 的实施。

    为了避免这种情况,也许可以考虑采用工厂模式,唯一的工作就是了解这些耦合!这将允许 ReminderPresenting 和 RemindersCalendar 在不需要知道另一个存在的情况下度过一生。

    【讨论】:

    • 感谢您指出这种方法?只有一件事,如果有超过 1 次传递数据,在 init 中传递所有闭包会很混乱,有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    • 2011-05-24
    • 1970-01-01
    相关资源
    最近更新 更多