Swift 디자인패턴 Multicast Delegate Pattern (멀티캐스트 딜리게이트 패턴)
멀티캐스트 델리게이트 패턴은 델리게이트 패턴을 확장하여, 하나의 객체가 여러 개의 델리게이트에게 알림을 전송.
히스토리
- 2022-06-07: 디자인 패턴 스터디 정리
- 2024-11-26: 포스팅 글 재정리 및 예제 변경
Multicast Delegate Pattern
멀티캐스트 객체가 델리게이트 객체와의 관계가 일대일이 아닌 일대다로 확장되며, 여러 개의 델리게이트 객체가 이벤트를 수신하고 반응할 수 있음
- 이 패턴의 핵심은 멀티캐스트 델리게이트 헬퍼 클래스로, 이 클래스는 여러 델리게이트를 관리하고, 델리게이트 객체들이 이벤트를 받을 수 있도록 함.
- 헬퍼 클래스를 통해 한 객체가 여러 델리게이트에게 동일한 이벤트를 전달할 수 있도록 함
- RxSwift나 Combine 등을 통해 손쉽게 처리 가능
멀티캐스트 딜리게이트 패턴은 일반적으로 3가지 개념으로 구성됨
- 델리게이팅 객체 (Delegating Object): 이벤트가 발생했을 때 다른 객체들에게 알림을 보내는 객체
- 여러 개의 델리게이트를 가질 수 있습니다.
- 델리게이트 (Delegate): 델리게이트 프로토콜을 구현하고 이벤트에 반응하는 객체
- 멀티캐스트 델리게이트 헬퍼 (Multicast Delegate Helper): 여러 델리게이트 객체를 관리하는 헬퍼 클래스
- Delegating Object가 여러 Delegate에게 이벤트를 전달할 수 있도록 구조를 가짐
- 델리게이트 프로토콜 (Delegate Protocol): 델리게이트가 구현해야 할 메서드를 정의하는 인터페이스
동작하는 방식 (코드 흐름)
- Delegating Object 객체는 하나 이상의 Delegate를 가질 수 있으며, Delegate 들에게 이벤트가 발생했을 때 알림을 전달
- Multicast Delegate Helper는 Delegating Object가 여러 Delegate를 등록하고, 각각의 Delegate가 이벤트를 수신하도록 관리
- 여러 개의 Delgeate가 동일한 이벤트를 수신 할 수 있어, 여러 리스너들에게 동일한 알림을 효율적으로 전달
사용 예시
- 여러개의 컴포넌트가 하나의 이벤트에 대해 수신해야 하는 경우에 사용하면 좋음
코드 예제
멀티 캐스트 패턴을 가장 일반적으로 사용한 예제
import UIKit
import SwiftUI
/// Protocol that defines delegate behavior
protocol EventDelegate: AnyObject {
func didReceiveEvent(_ message: String)
}
/// A class for managing multiple delegates
class MulticastDelegate<T> {
private var delegates = NSHashTable<AnyObject>.weakObjects() // Weak references to avoid retain cycles
/// Add a delegate
func addDelegate(_ delegate: T) {
delegates.add(delegate as AnyObject)
}
/// Remove a delegate
func removeDelegate(_ delegate: T) {
delegates.remove(delegate as AnyObject)
}
/// Notify all delegates
func invokeDelegates(_ closure: (T) -> Void) {
for delegate in delegates.allObjects {
if let delegate = delegate as? T {
closure(delegate)
}
}
}
}
/// An example broadcaster that uses the multicast delegate
class EventBroadcaster {
private let multicastDelegate = MulticastDelegate<EventDelegate>()
func addDelegate(_ delegate: EventDelegate) {
multicastDelegate.addDelegate(delegate)
}
func removeDelegate(_ delegate: EventDelegate) {
multicastDelegate.removeDelegate(delegate)
}
func broadcastEvent(message: String) {
print("Broadcasting event: \(message)")
multicastDelegate.invokeDelegates { delegate in
delegate.didReceiveEvent(message)
}
}
}
/// Example delegate classes
class FirstListener: EventDelegate {
func didReceiveEvent(_ message: String) {
print("FirstListener received: \(message)")
}
}
class SecondListener: EventDelegate {
func didReceiveEvent(_ message: String) {
print("SecondListener received: \(message)")
}
}
struct ContentView: View {
var body: some View {
Button("Execute") {
/// Example usage
let broadcaster = EventBroadcaster()
let firstListener = FirstListener()
let secondListener = SecondListener()
broadcaster.addDelegate(firstListener)
broadcaster.addDelegate(secondListener)
// Broadcast an event
broadcaster.broadcastEvent(message: "Hello, Multicast Delegates!")
// Remove a delegate and broadcast again
broadcaster.removeDelegate(firstListener)
broadcaster.broadcastEvent(message: "Only SecondListener should receive this.")
}
}
}
#Preview {
ContentView()
}
(참고)
'apple > DesignPattern, Architecture' 카테고리의 다른 글
Swift 디자인패턴 FlyWeight Pattern (플라이웨이트 패턴) (1) | 2022.06.09 |
---|---|
Swift 디자인패턴 Facade Pattern (퍼사드 패턴) (1) | 2022.06.07 |
Swift 디자인패턴 State Pattern (상태 패턴) (0) | 2022.05.30 |
Swift 디자인패턴 Prototype Pattern (프로토타입 패턴) (0) | 2022.05.28 |
Swift 디자인패턴 Iterator Pattern (반복자 패턴) (0) | 2022.05.13 |