委托模式是主要的设计模式之一。
假设我们正在开发一个理发店应用程序。该应用程序有一个日历,用于选择记录的日期;点击日期将打开一个可供选择的理发师列表。
让我们实现一个简单的系统组件链接,使用指向彼此的指针将日历和屏幕结合起来,实现列表显示:
// псевдокод
class BarbershopScreen {
let calendar: Calendar
func showBarbersList(date: Date) {
showSelectionSheet(barbers(forDate: date))
}
}
class Calendar {
let screen: BarbershopScreen
func handleTap(on date: Date) {
screen.showBarbersList(date: date)
}
}
几天后,要求发生变化;在显示列表之前,您需要显示包含多种服务选择(胡须修剪等)的优惠,但并非总是如此,除了周六之外的所有日子。
我们向日历添加一个检查是否是星期六的检查,根据它,我们调用理发师列表或服务列表的方法,为了清楚起见,我将演示:
// псевдокод
class BarbershopScreen {
let calendar: Calendar
func showBarbersList(date: Date) {
showSelectionSheet(barbers(forDate: date))
}
func showOffersList() {
showSelectionSheet(offers)
}
}
class Calendar {
let screen: BarbershopScreen
func handleTap(on date: Date) {
if date.day != .saturday {
screen.showOffersList()
}
else {
screen.showBarbersList(date: date)
}
}
}
一周后,我们被要求在反馈屏幕上添加日历,就在那时,第一个架构问题发生了!
该怎么办?日历与理发预约屏幕紧密相连。
哇!啊!哦哦
如果您继续使用这个疯狂的应用程序架构,您应该复制整个日历类并将此副本与反馈屏幕相关联。
好吧,看起来不错,然后我们又添加了几个屏幕和几份日历,然后 X 时刻就来了。我们被要求更改日历的设计,这意味着现在我们需要找到日历的所有副本并对所有副本添加相同的更改。这种“做法”极大地影响了开发速度,也增加了出错的机会。结果,这样的项目最终会陷入崩溃状态,甚至原始架构的作者也不再理解他的类的副本是如何工作的,并且沿途添加的其他黑客也会立即崩溃。
需要做什么,或者更好的是,现在开始做什么还不算太晚?使用委托模式!
委托是一种通过公共接口传递类事件的方法。下面是日历委托的示例:
protocol CalendarDelegate {
func calendar(_ calendar: Calendar, didSelect date: Date)
}
现在让我们将使用委托的代码添加到示例代码中:
// псевдокод
class BarbershopScreen: CalendarDelegate {
let calendar: Calendar
init() {
calendar.delegate = self
}
func calendar(_ calendar: Calendar, didSelect date: Date) {
if date.day != .saturday {
showOffersList()
}
else {
showBarbersList(date: date)
}
}
func showBarbersList(date: Date) {
showSelectionSheet(barbers(forDate: date))
}
func showOffersList() {
showSelectionSheet(offers)
}
}
class Calendar {
weak var delegate: CalendarDelegate
func handleTap(on date: Date) {
delegate?.calendar(self, didSelect: date)
}
}
这样一来,我们就将日历与屏幕完全解开了,当从日历中选择日期时,它会传输日期选择事件– *将事件处理委托给订阅者;订阅者就是屏幕。
我们从这种方法中得到什么好处?现在我们可以独立地更改日历和屏幕逻辑,而无需重复类,从而简化了进一步的支持;这样就实现了系统组件实现的“全责原则”,遵守了DRY原则。
使用委托时,您可以添加、更改显示窗口的逻辑、屏幕上任何内容的顺序,这完全不会影响日历和其他类,客观上它们不应该参与与它们不直接相关的进程。< br/>或者,不太打扰自己的程序员可以使用通过公共总线发送消息,而不需要编写单独的协议/委托接口,在这种情况下最好使用委托。我在上一篇文章中写过这种方法的缺点– “观察者模式。”
来源
https://refactoring.guru/ru/replace-inheritance -with-delegation