![옵서버](/images/patterns/cards/observer-mini.png?id=fd2081ab1cff29c60b499bcf6a62786a)
C++로 작성된 옵서버
옵서버 패턴은 일부 객체들이 다른 객체들에 자신의 상태 변경에 대해 알릴 수 있는 행동 디자인 패턴입니다.
옵서버 패턴은 구독자 인터페이스를 구현하는 모든 객체에 대한 이러한 이벤트들을 구독 및 구독 취소하는 방법을 제공합니다.
복잡도:
인기도:
사용 사례들: 옵서버 패턴은 C++ 코드, 특히 그래픽 사용자 인터페이스 컴포넌트들에서 매우 일반적입니다. 다른 객체들과의 클래스들과 결합하지 않고 해당 객체들에서 발생하는 이벤트들에 반응하는 방법을 제공합니다.
식별: 옵서버 패턴은 들어오는 메서드들을 목록에 저장하는 구독 메서드로 초기 식별할 수 있으며, 만약 위 구독 메서드가 목록의 객체들을 순회하고 그들의 '업데이트' 메서드를 호출하면 해당 패턴은 옵서버 패턴으로 확정지을 수 있습니다.
개념적인 예시
이 예시는 옵서버 패턴의 구조를 보여주고 다음 질문에 중점을 둡니다:
- 패턴은 어떤 클래스들로 구성되어 있나요?
- 이 클래스들은 어떤 역할을 하나요?
- 패턴의 요소들은 어떻게 서로 연관되어 있나요?
main.cc: 개념적인 예시
/**
* Observer Design Pattern
*
* Intent: Lets you define a subscription mechanism to notify multiple objects
* about any events that happen to the object they're observing.
*
* Note that there's a lot of different terms with similar meaning associated
* with this pattern. Just remember that the Subject is also called the
* Publisher and the Observer is often called the Subscriber and vice versa.
* Also the verbs "observe", "listen" or "track" usually mean the same thing.
*/
#include <iostream>
#include <list>
#include <string>
class IObserver {
public:
virtual ~IObserver(){};
virtual void Update(const std::string &message_from_subject) = 0;
};
class ISubject {
public:
virtual ~ISubject(){};
virtual void Attach(IObserver *observer) = 0;
virtual void Detach(IObserver *observer) = 0;
virtual void Notify() = 0;
};
/**
* The Subject owns some important state and notifies observers when the state
* changes.
*/
class Subject : public ISubject {
public:
virtual ~Subject() {
std::cout << "Goodbye, I was the Subject.\n";
}
/**
* The subscription management methods.
*/
void Attach(IObserver *observer) override {
list_observer_.push_back(observer);
}
void Detach(IObserver *observer) override {
list_observer_.remove(observer);
}
void Notify() override {
std::list<IObserver *>::iterator iterator = list_observer_.begin();
HowManyObserver();
while (iterator != list_observer_.end()) {
(*iterator)->Update(message_);
++iterator;
}
}
void CreateMessage(std::string message = "Empty") {
this->message_ = message;
Notify();
}
void HowManyObserver() {
std::cout << "There are " << list_observer_.size() << " observers in the list.\n";
}
/**
* Usually, the subscription logic is only a fraction of what a Subject can
* really do. Subjects commonly hold some important business logic, that
* triggers a notification method whenever something important is about to
* happen (or after it).
*/
void SomeBusinessLogic() {
this->message_ = "change message message";
Notify();
std::cout << "I'm about to do some thing important\n";
}
private:
std::list<IObserver *> list_observer_;
std::string message_;
};
class Observer : public IObserver {
public:
Observer(Subject &subject) : subject_(subject) {
this->subject_.Attach(this);
std::cout << "Hi, I'm the Observer \"" << ++Observer::static_number_ << "\".\n";
this->number_ = Observer::static_number_;
}
virtual ~Observer() {
std::cout << "Goodbye, I was the Observer \"" << this->number_ << "\".\n";
}
void Update(const std::string &message_from_subject) override {
message_from_subject_ = message_from_subject;
PrintInfo();
}
void RemoveMeFromTheList() {
subject_.Detach(this);
std::cout << "Observer \"" << number_ << "\" removed from the list.\n";
}
void PrintInfo() {
std::cout << "Observer \"" << this->number_ << "\": a new message is available --> " << this->message_from_subject_ << "\n";
}
private:
std::string message_from_subject_;
Subject &subject_;
static int static_number_;
int number_;
};
int Observer::static_number_ = 0;
void ClientCode() {
Subject *subject = new Subject;
Observer *observer1 = new Observer(*subject);
Observer *observer2 = new Observer(*subject);
Observer *observer3 = new Observer(*subject);
Observer *observer4;
Observer *observer5;
subject->CreateMessage("Hello World! :D");
observer3->RemoveMeFromTheList();
subject->CreateMessage("The weather is hot today! :p");
observer4 = new Observer(*subject);
observer2->RemoveMeFromTheList();
observer5 = new Observer(*subject);
subject->CreateMessage("My new car is great! ;)");
observer5->RemoveMeFromTheList();
observer4->RemoveMeFromTheList();
observer1->RemoveMeFromTheList();
delete observer5;
delete observer4;
delete observer3;
delete observer2;
delete observer1;
delete subject;
}
int main() {
ClientCode();
return 0;
}
Output.txt: 실행 결과
Hi, I'm the Observer "1".
Hi, I'm the Observer "2".
Hi, I'm the Observer "3".
There are 3 observers in the list.
Observer "1": a new message is available --> Hello World! :D
Observer "2": a new message is available --> Hello World! :D
Observer "3": a new message is available --> Hello World! :D
Observer "3" removed from the list.
There are 2 observers in the list.
Observer "1": a new message is available --> The weather is hot today! :p
Observer "2": a new message is available --> The weather is hot today! :p
Hi, I'm the Observer "4".
Observer "2" removed from the list.
Hi, I'm the Observer "5".
There are 3 observers in the list.
Observer "1": a new message is available --> My new car is great! ;)
Observer "4": a new message is available --> My new car is great! ;)
Observer "5": a new message is available --> My new car is great! ;)
Observer "5" removed from the list.
Observer "4" removed from the list.
Observer "1" removed from the list.
Goodbye, I was the Observer "5".
Goodbye, I was the Observer "4".
Goodbye, I was the Observer "3".
Goodbye, I was the Observer "2".
Goodbye, I was the Observer "1".
Goodbye, I was the Subject.