Programming Languange/디자인 패턴

디자인 패턴 (Design Patterns) - 옵서버 패턴

타자치는 문돌이 2024. 4. 10. 16:46

옵서버 패턴은 자신을 관찰하고 있는 객체에 자신의 상태를 알리는 디자인 패턴이다.

코드의 로직이 다른 값의 변화에 의존하는 경우, 코드는 값을 확인하는 과정이 필요하다. 그러나 변화를 확인하기 위해 계속해서 상태를 확인하는 것은 비효율적이다. 직접 상태를 관찰하는 대신 수동적으로 상태 값을 전달받아 처리하는 패턴을 옵서버 패턴이라 한다.

구현

옵서버 패턴은

  • Subject
  • Observer
    로 구성된다.
    Subject는 통보를, Observer는 처리를 담당한다.

Subject

Subject는 객체의 등록, 삭제, 통보를 담당한다.
상태 값을 전달받고 싶어 하는 모든 객체는 Subject에 등록되어 있어야 한다.

// 주제(Subject) 인터페이스
class Subject
{
public:
    virtual void attach(Observer *observer) = 0;
    virtual void detach(Observer *observer) = 0;
    virtual void notify(const std::string &message) = 0;
};

// 주제(Concrete Subject)
class ConcreteSubject : public Subject
{
public:
    // 추가
    void attach(Observer *observer) override { observers_.push_back(observer); }
    // 삭제
    void detach(Observer *observer) override
    {
        observers_.erase(std::remove(observers_.begin(), observers_.end(), observer), observers_.end());
    }
    // 알림
    void notify(const std::string &message) override
    {
    // 모든 관찰자에게 메시지 전달
        for (auto observer : observers_) { observer->update(message); }
    }

private:
    std::vector *> observers_;
};

Observer

Observer는 Subject가 보낸 통보를 수신받아 처리하는 객체이다.

// 관찰자(Observer) 인터페이스
class Observer
{
public:
    virtual void update(const std::string &message) = 0;
};

// 관찰자(Concrete Observer)
class ConcreteObserver : public Observer
{
public:
    explicit ConcreteObserver(const std::string &name) : name_(name) {}
    void update(const std::string &message) override
    {
        std::cout << name_ << " received message: " << message << std::endl;
    }

private:
    std::string name_;
};

예시

int main()
{
    ConcreteSubject subject;

    // 관찰자들 생성
    ConcreteObserver observer1("Observer 1");
    ConcreteObserver observer2("Observer 2");

    // 주제에 관찰자들을 추가
    subject.attach(&observer1);
    subject.attach(&observer2);

    // 주제가 변경되었음을 알림
    subject.notify("Hello World!");

    // observer1을 제거
    subject.detach(&observer1);

    // 다시 변경 알림
    subject.notify("Goodbye!");

    return 0;
}

장점

  • 개방/폐쇄 원칙을 만족한다. Subject의 코드를 변경하지 않고 새 Object 클래스를 도입할 수 있다.
  • 런타임에 객체 간의 관계를 형성할 수 있다.

단점

  • Object는 무작위로 알림을 받는다.

 

디자인 패턴 (Design Patterns) - Index