내배캠/C++

디자인 패턴(Observer Pattern)

동그래님 2024. 12. 30. 19:53
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// Observer 패턴에서 상태 변화를 알림 받는 객체들의 공통 인터페이스
// Observer를 상속 받은 객체들은 이 인터페이스를 구현하여 'Update' 메서드를 통해 데이터를 전달 받는다
class Observer
{
public:
	virtual ~Observer() = default;
	virtual void Update(int Data) = 0;
};

// Subject 클래스(액셀 시트 역할)
// 데이터의 상태 변화를 관리하고, 모든 등록된 Observer에게 변경 사항을 알림
class ExcelSheet
{
private:
	vector<Observer*> Observers;
	int Data;

public:
	ExcelSheet() : Data(0) {}

	// Observer 객체를 리스트에 추가
	void Attach(Observer* observer)
	{
		Observers.push_back(observer);
	}

	void Detach(Observer* observer)
	{
		auto it = find(Observers.begin(), Observers.end(), observer);

		if (it != Observers.end())
		{
			Observers.erase(it);
			cout << "Observer detached successfully" << endl;
		}
		else
		{
			cout << "Observer not found in the list" << endl;
		}
	}

	// 상태 변경시 알림 메서드
	// 등록된 전체 Observer들을 순회하며 'Update' 메서드를 호출하여 데이터 변경 사항을 알림
	void Notify()
	{
		for (Observer* observer : Observers)
		{
			observer->Update(Data);
		}
	}

	// 데이터 설정 메서드
	// 데이터 설정 후 변경사항을 알림
	void SetData(int NewData)
	{
		Data = NewData;
		cout << "ExcelSheet: Data updated to " << Data << endl;
		Notify();
	}
};


// 구체적인 Observer 클래스
// 데이터를 막대 그래프로 표현
class BarChart : public Observer
{
public:
	void Update(int Data) override
	{
		cout << "BarChart: Displaying data as vertical bars: ";
		for (int i = 0; i < Data; ++i)
		{
			cout << "|";
		}
		cout << " (" << Data << ")" << endl;
	}
};

// 구체적인 Observer 클래스
// 데이터를 바 형태로 표현
class LineChart : public Observer
{
public:
	void Update(int Data) override
	{
		cout << "LineChart: Plotting data as a line: ";
		for (int i = 0; i < Data; ++i)
		{
			cout << "-";
		}
		cout << " (" << Data << ")" << endl;
	}
};

int main()
{
	// Subject 생성
	ExcelSheet excelSheet;

	// Observer 객체 생성(동적 메모리 할당)
	BarChart* barChart = new BarChart();
	LineChart* lineChart = new LineChart();

	// ExcelSheet에 Observer 등록
	excelSheet.Attach(barChart);
	excelSheet.Attach(lineChart);

	// 데이터 설정
	excelSheet.SetData(5);

	// ExcelSheet에서 Observer 삭제
	excelSheet.Detach(barChart);

	cout << "===============\n";

	// 새로운 데이터 설정
	excelSheet.SetData(10);

	//동적으로 할당된 Observer 객체 삭제
	delete barChart;
	delete lineChart;

	return 0;
}

Observer Pattern

  • 객체 간 일대다 의존 관계를 정의하여, 한 객체의 상태가 변경될 때, 그 객체에 의존하는 다른 객체들이 자동으로 알림을 받고 갱신되도록 하는 디자인 패턴이다.
  • 주로 이벤트 기반 시스템에서 사용되며, 발행-구독(pub-sub) 모델이라고도 불린다.
  • 객체 간 결합도 감소: Subject와 Observer는 서로 독립적이므로 객체 간 강한 결합을 피할 수 있다.
  • 새로운 Observer를 추가해도 Subject를 수정할 필요가 없다.
  • 상태 변경 시 여러 객체가 자동으로 동기화된다.

1. Subject

  • 상태를 관리하고, 상태 변경을 Observer들에게 알리는 역할을 한다.
  • Observer를 등록(Attach)하거나 제거(Detach)하는 메서드를 제공한다.
  • 상태 변경 시 등록된 Observer들에게 알림(Notify) 기능을 수행한다.

2. Observer

  • 상태 변경 알림을 받기 위해 Subject에 등록된다.
  • Subject가 알림을 보내면 이를 받아들이고, 자신을 갱신(Update) 한다.
  • 구체적인 동작은 각 Observer가 정의한다.