๊ด์ฐฐ์ ํจํด์ GoF ํจํด ์ค์์๋ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๊ณ ์ ์๋ ค์ก์ง๋ง,
์ธ์์ ๋ฑ์ง๊ณ ์ด์๊ฐ๋ ๊ฒ์ ๊ฐ๋ฐ์์๊ฒ๋ ์ํ ์ฒ์ ๋ฃ๋ ์ด์ผ๊ธฐ์ผ ์๋ ์๋ค.
{ ๊ด์ฐฐ์ ํจํด์ด๋? }
๊ด์ฐฐ์ ํจํด์ GoF์ ํ์ ํจํด ์ค ํ๋๋ก,
ํ ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณํํ๋ฉด ๊ฐ์ฒด์ ๊ด์ฐฐ์๋ก ๋ฑ๋ก๋์ด ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ค์๊ฒ ๋ณํ๋ ์ํ๋ฅผ ์ ๋ฌํ๋ ํจํด์ด๋ค.
์ฃผ๋ก ๋ถ์ฐ ์์คํ ๊ฐ์ ์ด๋ฒคํธ๋ฅผ ์์ฑ•๋ฐ์(Publish)ํ๊ณ , ์ด๋ฅผ ์์ (Subscribe)ํด์ผ ํ ๋ ์ด์ฉํ๋ค.
- ๊ด์ฐฐ์ ํจํด์ MVC(Model View Controller) ๊ตฌ์กฐ์ ๊ธฐ๋ฐ์ด๋ค.
- ์๋ฐ์ EventListener๋ C#์ delegate์ ๊ฐ์ด ๊ฐ์ ๋ชจ๋ OOP ์ธ์ด์์๋ ์์ฒด์ ์ผ๋ก ๊ด์ฐฐ์ ํจํด์ ์ง์ํ๋ค.
{ ๊ฒ์ ๊ฐ๋ฐ์์ ๊ด์ฐฐ์ ํจํด ํ์ฉํ๊ธฐ : ์ ์ ์์คํ }
๊ฒ์ ์ ์ ์ ์ข ๋ฅ๊ฐ ๋ง๊ณ ๊ทธ๋งํผ ๋ฌ์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ด ๋ค์ํด์ ๊น๋ํ๊ฒ ๊ตฌํํ๊ธฐ ์ด๋ ต๋ค.
์๋ฅผ ๋ค์ด '๋ค๋ฆฌ์์ ๋ํํ๊ธฐ'๋ผ๋ ์
์ ์ด ์๋ค๊ณ ํ์.
๋ฌผ๋ฆฌ ์์ง ํ ๊ฐ์ด๋ฐ์ UnlockFallOffBridge() ํจ์๋ฅผ ํธ์ถํ๋ ๋์ฐํ ์ง์ ํ๊ณ ์ถ์ ํ๋ก๊ทธ๋๋จธ๋ ์์ ๊ฒ์ด๋ค.
์ด๋ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด ๊ด์ฐฐ์ ํจํด์ด๋ค.
๊ด์ฐฐ์ ํจํด์ ์ ์ฉํ๋ฉด ์ด๋ค ์ฝ๋์์ ํน์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ๋๊ฐ ๋ฐ์ ์๊ด์์ด ์๋ฆผ์ ๋ณด๋ผ ์ ์๋ค.
void Physics::updateEntity(Entity& entity)
{
bool wasOnSurface = entity.isOnSurface();
entity.accelerate(GRAVITY);
entity.update();
if(wasOnSurface && !entity.isOnSurface())
{
notify(entity, EVENT_START_FALL);
}
}
์
์ ์์คํ
์ ๋ฌผ๋ฆฌ ์์ง์ด ์๋ฆผ์ ๋ณด๋ผ ๋๋ง๋ค ๋ฐ์ ์ ์๋๋ก ์ค์ค๋ก ๋ฑ๋กํ๋ค.
์
์ ์์คํ
์ ๋ฌผ๋ฆฌ ์์ง์ด ๋ณด๋ด์ค๋ ์๋ฆผ์ ๋ฐ์ผ๋ฉด ๋จ์ด์ง๋ ๋ฌผ์ฒด๊ฐ Player๊ฐ ๋ง๋์ง, Player๊ฐ ๋จ์ด์ง๊ธฐ ์ ์ ์๋ ๊ณณ์ด ๋ค๋ฆฌ์ธ์ง ํ์ธํ ๋ค์ ์
์ ์ ์ ๊ธ ํด์ ํ๋ค.
์ด๋ฐ ๊ณผ์ ์ ๋ฌผ๋ฆฌ ์์ง์ ์ ํ ๋ชฐ๋ผ๋ ๋๋ค.๋ฌผ๋ฆฌ ์์ง์ ๋๊ฐ ๋ฐ๋ ์๋ฐ๋ ํน์ ์กฐ๊ฑด์์ ๊ณ์ ์๋ฆผ์ ๋ณด๋ผ ๋ฟ์ด๋ค.
์ด๋ ๊ฒ ๊ด์ฐฐ์ ํจํด์ ์ฌ์ฉํด ๋ฌผ๋ฆฌ ์์ง๊ณผ ์ ์ ์์คํ ์ ์ปคํ๋ง์ ํด์ํ ์ ์๋ค.
{ ๊ด์ฐฐ์ ํจํด ์ธํฐํ์ด์ค }
1. ๊ด์ฐฐ์(Observer)
Observer ํด๋์ค๋ ์ด๋ฒคํธ๋ฅผ ์์ ํ๋ ํด๋์ค์ด๋ค. Observer ํด๋์ค์ ์ธํฐํ์ด์ค๋ ๋ค์๊ณผ ๊ฐ๋ค.
**์ธ์ด์ ๋ฐ๋ผ์ ์ ๋ค๋ฆญ(generic) ํน์ ํ ํ๋ฆฟ ๊ฐ์ ๊ฑธ ์จ๋ ๋์ง๋ง, ๊ทธ๋ฅ ํ์์ ๋ง๊ฒ ์ํ๋ ์๋ฃํ์ ์ ๋ฌํด๋ ๋๋ค. ์ฌ๊ธฐ์์๋ ๊ฒ์ ๊ฐ์ฒด์ ๋ฌด์จ ์ผ์ด์๋์ง๋ฅผ ์ค๋ช ํ๋ ์ด๊ฑฐํ ๊ฐ์ ํ๋์ฝ๋ฉํด์ ๋ฃ์๋ค.
class Observer
{
public: virtual ~Observer() {}
virtual void onNotify(const Entity& entity, Event event) = 0;
};
์ด๋ค ํด๋์ค๋ Observer ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ธฐ๋ง ํ๋ฉด ๊ด์ฐฐ์๊ฐ ๋ ์ ์๋ค. ์์๋ก ์ค๋ช ํ ์ ์ ์์คํ ์ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํ๋ ์ ์๋ค.
class Achievements : public Observer
{
public:
virtual void onNotify(const Entity& entity, Event event)
{
switch (event)
{
case EVENT_ENTITY_FELL:
if(entity.isHero() && heroIsOnBridge_)
{
unlock(ACHIEVEMENT_FELL_OFF_BRIDGE);
}
break;
// ๊ทธ ์ธ ๋ค๋ฅธ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๊ณ ...
// heroIsOnBridge_ ๊ฐ์ ์
๋ฐ์ดํธํ๋ค...
}
}
private:
void unlock(Achievement achievement)
{
// ์์ง ์
์ ์ด ์ ๊ฒจ ์๋ค๋ฉด ์ ๊ธํด์ ํ๋ค...
}
bool heroIsOnBridge_;
};
2. ๋์(Subject)
Subject ํด๋์ค๋ ์๋ฆผ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ํด๋์ค์ด๋ค.
- Subject ํด๋์ค ์๋ฆผ์ ๋ฐ์ ๊ด์ฐฐ์ ๋ชฉ๋ก์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ๋๊ตฌ๋ ๊ด์ฐฐ์๋ก ๋ฑ๋ก๋๊ณ ์ญ์ ๋ ์ ์๋๋ก API๋ฅผ ์ด์ด๋ฌ์ผ ํ๋ค.
- Subjectํด๋์ค๋ ๊ด์ฐฐ์๋ค์๊ฒ ์๋ฆผ์ ๋ณด๋ธ๋ค.
class Subject
{
private:
Observer* m_Observers[MAX_OBSERVERs];
int m_iNumOfObservers;
public:
void AddObserver(Observer* _obs)
{
// ๋ฐฐ์ด์ ์ต์ ๋ฒ ์ถ๊ฐ
}
void RemoveObserver(Observer* _obs)
{
// ๋ฐฐ์ด์ ์ต์ ๋ฒ ์ญ์
}
protected:
void notify(const Entitiy& entitiy, Event event)
{
for(const auto& o : m_Observers)
{
o->onNotify(entity, event);
}
}
}
Subject์ ์ต์ ๋ฒ ์ปจํ ์ด๋ ๊ฐ์ ํ๊ธฐ
์ ์ฝ๋์์๋ ์ ์ ๋ฐฐ์ด์ ์ฌ์ฉํ์ฌ ํ์ฌ ๊ด์ฐฐ์๋ค์ ์ ์ฅํ์์ง๋ง,
์ค์ ํ๋ก์ ํธ์์๋ ๋์ ๋ฐฐ์ด์ ์ฌ์ฉํ ๊ฐ๋ฅ์ฑ์ด ๋๋ค.
๋์ ๋ฐฐ์ด์ ์ฌ์ฉํ์ฌ ์ต์ ๋ฒ๋ฅผ ์ ์ฅํ ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค.
- ์ฆ์ ๋์ ํ ๋น
- ์ต์ ๋ฒ ์ถ๊ฐ, ์ญ์ ์ ๋ฐ๋ฅธ ๋น์ฉ
์ต์ ๋ฒ ์ปจํ ์ด๋๋ฅผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ก ๋ฐ๊พธ๋ฉด ์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
- ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋
ธ๋๋ค์ Pool๋ก ๊ด๋ฆฌ
์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋๋ค์ ๋ชจ๋ ํฌ๊ธฐ๊ฐ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ฆฌ ํ ๋นํ์ฌ Pool๋ก ๊ด๋ฆฌํ ์ ์๋ค.
Pool๋ก ๋ ธ๋๋ค์ ๊ด๋ฆฌํ๋ฉด, ์ต์ ๋ฒ๊ฐ ์ถ๊ฐ/์ญ์ ๋ ๋๋ง๋ค ๋์ ํ ๋น/ํด์ ๋ฅผ ํ๋ ์ผ์ด ์์ด์ ธ ์ฆ์ ๋์ ํ ๋น์ผ๋ก ์ธํ ๋ฉ๋ชจ๋ฆฌ ๋จํธํ๋ ์๋ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ค. - ๋ฆฌ์คํธ๋ ์ค๊ฐ ๊ฐ ์ญ์ ๋น์ฉ์ด O(1)์ด๋ค.
vector์ ๊ฒฝ์ฐ ์ค๊ฐ ๊ฐ์ ์ญ์ ํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ์ฎ๊ธฐ๋ ๊ณผ์ ์ด ์ผ์ด๋ O(n)์ ์๊ฐ์ด ๊ฑธ๋ฆฌ์ง๋ง ๋ฆฌ์คํธ๋ ์ค๊ฐ ๊ฐ ์ญ์ ์ O(1)์ ์๊ฐ์ด ๊ฑธ๋ ค ๋น ๋ฅด๋ค.
{ ์ฃผ์ํ ์ }
1. ๊ด์ฐฐ์ ํจํด์ ๋๊ธฐ์ ์์ ๊ธฐ์ตํ์.
๊ด์ฐฐ์ ํจํด์ ๋๊ธฐ์ ์ด๋ค.
๋์(Subject)์ด ๊ด์ฐฐ์(Observer) ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๊ด์ฐฐ์๊ฐ ์๋ฆผ ๋ฉ์๋๋ฅผ ๋ฐํํ๊ธฐ ์ ์๋ ๋ค์ ์์
์ ์ํํ ์ ์๋ค. ๊ด์ฐฐ์ ์ค ํ๋๋ผ๋ ๋๋ฆฌ๋ฉด ๋์์ด ๋ธ๋ก๋ ์๋ ์๋ค.
๋ฐ๋ผ์ ๊ด์ฐฐ์๋ฅผ ๋ฉํฐ ์ค๋ ๋, ๋ฝ(lock)๊ณผ ํจ๊ป ์ฌ์ฉํ ๋๋ ์ ๋ง ์กฐ์ฌํด์ผ ํ๋ค.
์ด๋ค ๊ด์ฐฐ์๊ฐ ๋์์ ๋ฝ์ ๋ฌผ๊ณ ์๋ค๋ฉด ๊ฒ์ ์ ์ฒด๊ฐ ๊ต์ฐฉ์ํ์ ๋น ์ง ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์์ง์์ ๋ฉํฐ ์ค๋ ๋๋ฅผ ๋ง์ด ์ฐ๊ณ ์๋ค๋ฉด ์ด๋ฒคํธ ํ๋ฅผ ์ด์ฉํด ๋น๋๊ธฐ์ ์ผ๋ก ์ํตํ๋ ๊ฒ์ด ์ข๋ค.
2. ์ฌ๋ผ์ง ๊ด์ฐฐ์์ ์๋ฆผ์ ๋ณด๋ด์ง ์๊ฒ ์ฃผ์ํ์.
๋์์ ๊ด์ฐฐ์๋ค์ ํฌ์ธํฐ๋ฅผ ์ฐธ์กฐํด ๊ด์ฐฐ์๋ค์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ๊ธฐ ๋๋ฌธ์,
๋์์ด ๋ฉ๋ชจ๋ฆฌ ํด์ ๋ ๊ด์ฐฐ์์ ์ ๊ทผํด ๋ฉ์๋ ํธ์ถ์ ์๋ํ๋ ์ผ์ด ๋ฐ์ํ๋ฉด ๊ฒ์์ด ๋ปฅ-! ํฐ์ง ์ ์๋ค.
๋ฐ๋ผ์ ๊ด์ฐฐ์์ ์๋ฉธ์์์ Subject::RemoveObserver(this) ๋ฅผ ๊ผญ ํธ์ถํด์ฃผ์.
3. ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ์ง์์ ๋ฐ๋๋ผ๋ ๋ ์ด์ ์ฌ์ฉํ์ง ์์ ๊ด์ฐฐ์๋ ๊ผญ RemoveObserver()๋ฅผ ํธ์ถํ์.
๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ง์์ ๋ฐ๋๋ผ๋ ์ฃผ์ํ ์ ์ด ์๋ค.
๋ ์ด์ ์ฌ์ฉํ์ง ์์ ๊ด์ฐฐ์๋ฅผ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์๋์ผ๋ก ์ญ์ ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๊ณ ๋ฐฉ์นํ์ง ๋ง์.
๋์์ด ํด๋น ๊ด์ฐฐ์๋ฅผ ์ฐธ์กฐํ๊ณ ์๋ ํ, ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ ํด๋น ๊ด์ฐฐ์๋ฅผ ์ญ์ ํ์ง ์๋๋ค.
์ด๋ฐ ์ํฉ์ ์๋ฆผ ์์คํ ์์ ๊ต์ฅํ ์์ฃผ ์ผ์ด๋๋ ์ผ๋ก '์ฌ๋ผ์ง ๋ฆฌ์ค๋ ๋ฌธ์ ' ๋ผ๋ ์ด๋ฆ๊น์ง ๋ถ์ ์ ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ์ง์์ ๋ฐ๋๋ผ๋ ๋ ์ด์ ์ฌ์ฉํ์ง ์์ ๊ด์ฐฐ์๋ ๊ผญ RemoveObserver()๋ฅผ ํธ์ถํ์.
reference
๋์ : ๊ฒ์ ํ๋ก๊ทธ๋๋ฐ ํจํด
'๐ฅ๏ธ Study Note > Design Patteren' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํ๋กํ ํ์ (ProtoType) ํจํด (0) | 2023.06.19 |
---|---|
๊ฒฝ๋(FlyWeight) ํจํด (2) | 2023.06.07 |
๋ช ๋ น(Command) ํจํด (2) | 2023.06.05 |
๋์์ธ ํจํด์ด๋? (0) | 2023.06.05 |