Decorator 패턴
- 실행 시간에 객체에 기능을 추가
- 객체에 동적으로 새로운 서비스를 추가
- 기능 추가를 위해 서브 클래스를 사용하는 것 보다 융통성 있는 방법을 제공
#include <iostream>
using namespace std;
class SpaceCraft
{
int color;
int speed;
public:
void Fire() { cout << "Space Craft : ------------" << endl; }
};
int main()
{
SpaceCraft sc;
sc.Fire();
}
// 상속을 써보자.
class LeftMissile : public SpaceScraft
{
public:
void Fie()
{
SpaceCraft::Fire();
cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
}
};
int main()
{
SpaceCraft sc;
sc.Fire();
// 문제는 위의 sc와는 전혀 관계없는 새로운 오브젝트가 생긴것이다.
LeftMissile lm;
lm.Fire();
}
// 구성(Composition)을 통한 기능추가
class LeftMissile
{
SpaceCraft* craft;
public:
LeftMissile(SpaceCraft* p) : craft(p) {}
void Fire()
{
craft->Fire();
cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
}
};
int main()
{
SpaceCraft sc;
sc.Fire();
LeftMissile lm(&sc);
lm.Fire();
}
- 상속에 의한 기능추가 : 클래스에 추가, 코드 작성시 기능 추가 가능
- 구성에 의한 기능추가 : 객체에 추가, 실행시간에 기능 추가 가능
class RightMissile
{
SpaceCraft* craft;
public:
RightMissile(SpaceCraft* p) : craft(p) {}
void Fire()
{
craft->Fire();
cout << "Right Missile : >>>>>>>>>>>>>>>>" << endl;
}
};
int main()
{
SpaceCraft sc;
sc.Fire();
LeftMissile lm(&sc);
lm.Fire();
RightMissile rm(&sc); // ??? -> lm을 주소로 보내야하지 않나? -> 현재는 불가능
rm.Fire();
}
struct Component
{
virtual void Fire() = 0;
virtual ~Component() {}
};
class SpaceCraft : public Component
{
int color;
int speed;
public:
void Fire() { cout << "Space Craft : ------------" << endl; }
};
class LeftMissile : public Component
{
Component* craft;
public:
LeftMissile(Component* p) : craft(p) {}
void Fire()
{
craft->Fire();
cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
}
};
class RightMissile : public Component
{
Component* craft;
public:
RightMissile(Component* p) : craft(p) {}
void Fire()
{
craft->Fire();
cout << "Right Missile : >>>>>>>>>>>>>>>>" << endl;
}
};
int main()
{
SpaceCraft sc;
sc.Fire();
LeftMissile lm(&sc);
lm.Fire();
RightMissile rm(&lm); // ok
rm.Fire();
}
조금 더 진화해보자.
struct IDecorator : public Component
{
Component* craft;
public:
IDecorator(Component* p) : craft(p) {}
void Fire() { craft->Fire(); }
};
class LeftMissile : public IDecorator
{
public:
LeftMissile(Component* p) : IDecorator(p) {}
void Fire()
{
IDecorator::Fire();
cout << "Left Missile : >>>>>>>>>>>>>>>>" << endl;
}
};
class RightMissile : public IDecorator
{
public:
RightMissile(Component* p) : IDecorator(p) {}
void Fire()
{
IDecorator::Fire();
cout << "Right Missile : >>>>>>>>>>>>>>>>" << endl;
}
};