반응형
엑셀을 사용할 때, 서로 연결된 표와 그래프를 생각해 보자.
표만 수정을 하면 그래프가 변화한다. 어떻게 구현할 수 있을까?
테이블을 만들고, 그 테이블에 여러가지 그래프들이 붙을 수 있게 한다.
그래프가 표를 관찰하고 있다가 변하면 본인도 변하게 한다.
관찰자 패턴이라 하지만... 개인적으로는 본인 밑에 달린 여러 클래스들에게 통보하는 느낌이 강하다.
ITable / Igraph를 생성.
graph를 table에 붙였다 땟다 할 수 있게 만들어 보자.
#include <iostream>
#include <vector>
class ITable; // class 전방선언
struct IGraph
{
virtual void Update() = 0;
virtual ~IGraph() {}
ITable* AttachedTable;
};
class ITable
{
std::vector<IGraph*> v;
public:
std::vector<int> datalist;
void attach(IGraph* p) {
v.push_back(p);
p->AttachedTable = this;
}
void detach(IGraph* p) {
auto it = std::find(v.begin(), v.end(), p);
v.erase(it);
}
void notify(){}
};
class Table : public ITable
{
public:
};
//----------------------
class BarGraph : public IGraph
{
public:
void Update() override {
}
};
class PieGraph : public IGraph
{
public:
void Update() override {
// pie graph 변경
}
};
int main()
{
Table t;
PieGraph pg; t.attach(&pg);
BarGraph bg; t.attach(&bg);
t.detach(&bg);
}
이런 식으로, table을 만들고 원한다면 그래프를 만들어 해당 테이블에 붙일 수 있게 해 두었다.
후, 테이블의 값 중 무언가가 변경되면 본인에게 붙어있는 graph들에게 알려주는 코드를 작성해 보자.
이를 위해 ITable에는 notify라는 함수를 추가하고, table에서 무언가 값을 변경 할 때마다 notify를 해 주었다.
graph가 시각적으로 변하는 것을 보기 위해, update될 때 print를 몇 개 해 보자.
#include <iostream>
#include <vector>
class ITable; // class 전방선언
struct IGraph
{
virtual void Update() = 0;
virtual ~IGraph() {}
ITable* AttachedTable;
};
class ITable
{
std::vector<IGraph*> v;
public:
std::vector<int> datalist;
void attach(IGraph* p) {
v.push_back(p);
p->AttachedTable = this;
}
void detach(IGraph* p) {
auto it = std::find(v.begin(), v.end(), p);
v.erase(it);
}
void notify()
{
for (auto p : v)
p->Update();
}
};
class Table : public ITable
{
public:
Table() {}
void AddData(int value) {
datalist.push_back(value);
std::cout << "Add data :" << value << "!" << std::endl;
notify();
}
};
//----------------------
class BarGraph : public IGraph
{
public:
void Update() override {
auto datalist = AttachedTable->datalist;
for (auto data : datalist) {
std::cout << data << std::endl;
}
}
};
class PieGraph : public IGraph
{
public:
void Update() override {
auto datalist = AttachedTable->datalist;
for (auto data : datalist) {
for (int i{ 0 }; i < data; i++) {
std::cout << "*";
}
std::cout << std::endl;
}
}
};
int main()
{
Table t;
PieGraph pg; t.attach(&pg);
BarGraph bg; t.attach(&bg);
t.AddData(2);
t.AddData(3);
t.AddData(4);
t.detach(&bg);
t.AddData(2);
}
이러한 식으로 observer pattern을 구현한다.
현재, 모델은 QT, MFC 등의 다양한 라이브러리에서 사용되는데..
대부분의 경우, graph의 update하는 부분에서 아래와 같은 casting 하는 코드가 자주 나타난다고 한다.
class Table : public ITable
{
std::vector<int> datalist;
public:
Table() {}
void AddData(int value) {
datalist.push_back(value);
std::cout << "Add data :" << value << "!" << std::endl;
notify();
}
std::vector<int> getData() { return datalist; }
};
//----------------------
class BarGraph : public IGraph
{
public:
void Update() override {
Table* pTable = static_cast<Table*>(AttachedTable);
auto datalist = pTable->getData();
for (auto data : datalist) {
std::cout << data << std::endl;
}
}
};
위의 코드를 반영하여 만든 최종 코드는 아래와 같다.
#include <iostream>
#include <vector>
class ITable; // class 전방선언
struct IGraph
{
virtual void Update() = 0;
virtual ~IGraph() {}
ITable* AttachedTable;
};
class ITable
{
std::vector<IGraph*> v;
public:
void attach(IGraph* p) {
v.push_back(p);
p->AttachedTable = this;
}
void detach(IGraph* p) {
auto it = std::find(v.begin(), v.end(), p);
v.erase(it);
}
void notify()
{
for (auto p : v)
p->Update();
}
};
class Table : public ITable
{
std::vector<int> datalist;
public:
Table() {}
void AddData(int value) {
datalist.push_back(value);
std::cout << "Add data :" << value << "!" << std::endl;
notify();
}
std::vector<int> getData() { return datalist; }
};
//----------------------
class BarGraph : public IGraph
{
public:
void Update() override {
Table* pTable = static_cast<Table*>(AttachedTable);
auto datalist = pTable->getData();
for (auto data : datalist) {
std::cout << data << std::endl;
}
}
};
class PieGraph : public IGraph
{
public:
void Update() override {
Table* pTable = static_cast<Table*>(AttachedTable);
auto datalist = pTable->getData();
for (auto data : datalist) {
for (int i{ 0 }; i < data; i++) {
std::cout << "*";
}
std::cout << std::endl;
}
}
};
int main()
{
Table t;
PieGraph pg; t.attach(&pg);
BarGraph bg; t.attach(&bg);
t.AddData(2);
t.AddData(3);
t.AddData(4);
t.detach(&bg);
t.AddData(2);
}
반응형
'Design Pattern' 카테고리의 다른 글
iterator pattern (0) | 2022.11.20 |
---|---|
Template Method (0) | 2022.09.06 |
Decorator pattern (0) | 2022.07.26 |
factory method (0) | 2022.06.07 |
Composite Pattern (0) | 2022.05.18 |