
Observer 3. Publisher-Subscriber
코드들은 설명을 위한 예제 코드입니다. 오류가 있을 수 있습니다.
이번에는 Publisher-Subscriber 패턴에 대해 알아보겠습니다. 옵저버 패턴을 이미 알고 있다면, Publisher-Subscriber 패턴은 옵저버 패턴에서 한 단계 더 나아가 발행자(Publisher)와 구독자(Subscriber) 사이의 직접적인 의존성을 줄이는 방법을 제공한다고 볼 수 있습니다.
이 패턴은 옵저버 패턴의 확장판으로, 중재자(Mediator) 역할을 하는 브로커(Broker)를 도입하여 발행자와 구독자가 서로 직접적인 참조를 하지 않고도 메시지를 주고받을 수 있습니다. 그 결과, 객체 간의 결합도가 느슨해지고, 시스템 확장성이 더욱 높아집니다.
구조
- Publisher: 이벤트나 메시지를 발행하는 역할을 합니다.
- Subscriber: 발행된 이벤트나 메시지를 구독하고 처리하는 역할을 합니다.
- Broker: 발행자와 구독자 간의 중재자로, 발행자로부터 메시지를 받아 구독자들에게 전달합니다.
특징
- 발행자와 구독자는 서로를 참조하지 않음: 발행자는 구독자가 누구인지 알 필요가 없고, 구독자도 발행자가 누구인지 알 필요가 없습니다. 이 둘 사이의 모든 소통은 브로커를 통해 이루어집니다.
- 결합도가 낮음: 발행자와 구독자가 직접 연결되어 있지 않기 때문에, 둘 간의 의존성이 줄어듭니다. 이는 시스템의 유지보수와 확장성을 높이는 데 도움이 됩니다.
- 확장성과 유연성: 새로운 구독자를 추가하거나 발행자를 교체하는 것이 간단해집니다. 시스템을 유연하게 확장할 수 있습니다.
예제 코드 (C#)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public interface ISubscriber
{
void MessageReceived(string message);
}
public interface IPublisher
{
void Publish(string message);
}
public class Broker
{
private List<ISubscriber> subscribers = new List<ISubscriber>();
// 구독자 추가
public void Subscribe(ISubscriber subscriber)
{
subscribers.Add(subscriber);
}
// 구독자 제거
public void Unsubscribe(ISubscriber subscriber)
{
subscribers.Remove(subscriber);
}
// 메시지를 구독자에게 전달
public void Distribute(string message)
{
foreach (var subscriber in subscribers)
{
subscriber.MessageReceived(message);
}
}
}
public class ConcretePublisher : IPublisher
{
private Broker broker;
public ConcretePublisher(Broker broker)
{
this.broker = broker;
}
public void Publish(string message)
{
broker.Distribute(message); // 브로커를 통해 메시지 전달
}
}
public class ConcreteSubscriber : ISubscriber
{
private string name;
public ConcreteSubscriber(string name)
{
this.name = name;
}
public void MessageReceived(string message)
{
Console.WriteLine($"{name} received message: {message}");
}
}
// 사용 예시
class Program
{
static void Main(string[] args)
{
Broker broker = new Broker();
// 구독자 생성
ConcreteSubscriber sub1 = new ConcreteSubscriber("Subscriber 1");
ConcreteSubscriber sub2 = new ConcreteSubscriber("Subscriber 2");
// 브로커에 구독자 등록
broker.Subscribe(sub1);
broker.Subscribe(sub2);
// 발행자 생성
ConcretePublisher publisher = new ConcretePublisher(broker);
// 발행자가 메시지 발행
publisher.Publish("Hello Subscribers!");
// 구독 취소 후 다시 발행
broker.Unsubscribe(sub1);
publisher.Publish("Another message for remaining subscribers.");
}
}
출력 예시:
1
2
3
4
Subscriber 1 received message: Hello Subscribers!
Subscriber 2 received message: Hello Subscribers!
Subscriber 2 received message: Another message for remaining subscribers.
비교
옵저버 패턴 (Observer Pattern)
- 직접적인 관계: 주체와 옵저버는 직접 연결되어 있습니다. 옵저버는 주체에 등록되어 상태 변경을 기다립니다.
- 강한 결합: 발행자와 옵저버는 직접적인 관계이므로 결합도가 높습니다.
Publisher-Subscriber 패턴
- 간접적인 관계: 발행자와 구독자는 서로 직접 참조하지 않으며, 중재자(브로커)를 통해 간접적으로 연결됩니다.
- 느슨한 결합: 발행자와 구독자가 서로를 참조하지 않으므로 결합도가 낮고, 확장성과 유연성이 높습니다.