소프트웨어 공부/디자인패턴

데코레이터 패턴(Decorator Pattern)

야곰야곰+책벌레 2022. 4. 6. 16:32
728x90
반응형
OCP(Open-Closed Principle)
기존 코드는 건드리지 않은 채로 확장을 통해서 새로운 행동을 간단하게 추가할 수 있도록 한다. 이것을 달성하면 새로운 기능을 추가하는 데 있어서 매우 유연해서 급변하는 주변 환경에 잘 적응할 수 있으면서도 강하고 튼튼한 디자인을 만들 수 있다.
코드에서 확장해야 할 부분을 선택할 때는 세심한 주의를 기울여야 한다. 무조건 OCP를 적용하는 것은 시간 낭비가 될 수도 있고, 괜히 쓸 데 없는 일을 하는 것일 수도 있다. 결과적으로 불필요하게 복잡하고 이해하기 힘든 코드만 만들게 되는 부작용이 있을 수도 있으니 주의해야 한다.

데코레이터 패턴(Decorator Pattern)에서는 객체에 추가적인 요건을 동적으로 첨가한다. 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다. 이해를 위해서 다이어그램을 살펴보도록 하자.

각 데코레이터 안에는 Component 객체가 들어 있다. 즉, 데코레이터에는 구성요소에 대한 레퍼런스가 들어있는 인스턴스 변수가 있다. 데코레이터는 자신이 장식할 구성요소와 같은 인터페이스 또는 추상 클래스를 구현한다. ConcreteComponent에 새로운 행동을 동적으로 추가하게 된다. ConcreteDecorator에는 그 객체가 장식하고 있는 것을 위한 인스턴스 변수가 있으며 Component의 상태를 확장할 수도 있다. 새로운 메소드를 추가할 수 있지만 일반적으로 새로운 메소드를 추가하는 대신 Component에 원래 있던 메소드를 호출하기 전, 또는 별도의 작업을 처리하는 방식으로 새로운 기능을 추가한다.

카페 메뉴 만들기

음료 코드 구현

///////////////////////////////////////////////////////////////////////////////////////////////////
// 음료 코드

class CEspresso : public CBeverage
{
public:
	CEspresso()
	{
		description = "에스프레소";
	}
	virtual double cost() override
	{
		return 1.99;
	}
};

첨가물 코드 구현

///////////////////////////////////////////////////////////////////////////////////////////////////
// 첨가물 코드

class CMocha : public CCondimentDecorator
{
public:
	shared_ptr<CBeverage> beverage;

	CMocha(shared_ptr<CBeverage> _beverage)
	{
		beverage = _beverage;
	}
	string getDescription() override
	{
		return beverage->getDescription() + ", 모카";
	}
	double cost()
	{
		return 0.2 + beverage->cost();
	}
};

커피 주문 코드

///////////////////////////////////////////////////////////////////////////////////////////////////
// 카페 코드
class CStarbuzzCoffee
{
public:
	CStarbuzzCoffee()
	{
		shared_ptr<CBeverage> beverage = make_shared<CEspresso>();
		cout << beverage->getDescription() << " $" << beverage->cost() << endl;

		shared_ptr<CBeverage> beverage2 = make_shared<CDarkRoast>();
		beverage2 = make_shared<CMocha>(beverage2);
		beverage2 = make_shared<CMocha>(beverage2);
		beverage2 = make_shared<CWhip>(beverage2);
		cout << beverage2->getDescription() << " $" << beverage2->cost() << endl;

		shared_ptr<CBeverage> beverage3 = make_shared<CHouseBlend>();
		beverage3 = make_shared<CSoy>(beverage3);
		beverage3 = make_shared<CMocha>(beverage3);
		beverage3 = make_shared<CWhip>(beverage3);
		cout << beverage3->getDescription() << " $" << beverage3->cost() << endl;
	}
};

int main()
{
	CStarbuzzCoffee starBuzz;
    return 0;
}

DecoratePattern.zip
0.01MB

 

728x90
반응형