데코레이터 패턴 정의

파생클래스의 생성자 파라미터에 덮어씌우고자 하는 인스턴스를 매개변수로 넣음으로써 재귀적으로 현재 인스턴스의 상태를 추가하는 방법이다.  

필요한 상황

1. Open-Closed-Principle(OCP) 원칙을 지키면서 인스턴스의 현재 상태를 추가하고 싶을 때

2. 인스턴스의 상태를 자유롭게 누적시키는 로직이 필요할 때

Class 다이어그램

코드

1. Pizza class 코드

public abstract class Pizza
{
    protected string? strDescription;
    
    public abstract String getDescription();
    
    public abstract double cost();
}

2. Topping class 코드

public abstract class Topping : Pizza
{
    public override String getDescription() => this.strDescription;
}

3. Pizza class의 파생 코드

public class CheesePizza : Pizza
{
    public CheesePizza()
    {
        base.strDescription = "CheesePizza";
    }
    
    public override double cost()
    {
        return 2.33;
    }
    
    public override string getDescription()
    {
        return base.strDescription;
    }
}

public class MeatLoverPizza : Pizza
{
    public MeatLoverPizza()
    {
        base.strDescription = "MeatLoverPizza";
    }
    
    public override double cost()
    {
        return 3.5;
    }
    
    public override string getDescription()
    {
        return base.strDescription;
    }
}

4. Topping class의 파생 코드

public class CheeseTopping : Topping
{
	Pizza pizza;
	public CheeseTopping(Pizza pizza)
	{
		this.pizza = pizza;
	}
	
	public override double cost() => (pizza.cost() + 0.5);
	public override String getDescription() => (pizza.getDescription() + " CheeseTopping");
}

public class TomatoTopping : Topping
{
	Pizza pizza;
	public TomatoTopping(Pizza pizza)
	{
		this.pizza = pizza;
	}
	
	public override double cost() => this.pizza.cost() + 0.2;
	
	public override String getDescription() => this.pizza.getDescription() + " Tomato Topping";

}

5. main 코드

Pizza pizza = new CheesePizza();
Console.WriteLine($"{pizza.getDescription()} : {pizza.cost()}");
pizza = new CheeseTopping(pizza);
Console.WriteLine($"{pizza.getDescription()} : {pizza.cost()}");
pizza = new CheeseTopping(pizza);
Console.WriteLine($"{pizza.getDescription()} : {pizza.cost()}");
pizza = new TomatoTopping(pizza);
Console.WriteLine($"{pizza.getDescription()} : {pizza.cost()}");

코드 설명

1. Pizza class는 파생 클래스 모두 공통으로 사용할 클래스이다.

2. Topping class 는 Pizza class의 파생 클래스이다. Topping class는 계속 이전 인스턴스를 인자로 받아서 추가로 데이터를 추가한다.

3. CheesePizza, MeatLoverPizza class들은 Pizza class의 파생 클래스로써 기본 Pizza의 대분류로 나눈 것이다. 그 이상 그 이하도 없다.

4. Cheese Topping, Tomato Topping class들은 Topping class의 파생 클로스로써 중요한 점은 Pizza class의 인스턴스를 생성자에서 받아서 이전 상태의 인스턴스를 저장한다. 저장한 인스턴스는 다음 함수 호출 시 사용한다. 이는 결국 재귀적으로 내부 Pizza class의 인스턴스를 재귀적으로 호출하는 역할을 수행하게 된다.

5. 사용하는 코드이다.

설명 보충을 위한 그림 자료

클래스 다이어그램 하단에 별도 기입..

필요에 따라 추가 설명

딱히 어려운 건 없다.

정리 및 결론

데코레이터 패턴도 다양한 언어, API에서 제공하는 패턴 중 하나이다. 하지만 재귀함수적 특징으로 인해 코드의 가독성이 떨어지는 단점이 있다. 사용할지 말지는 본인 판단!!

'Program > SW Design Patterns' 카테고리의 다른 글

CH7 어댑터&퍼사드 패턴  (0) 2023.03.19
CH6 커맨드 패턴  (0) 2023.03.07
CH4 팩토리 패턴  (0) 2023.03.04
CH3 옵저버 패턴  (0) 2023.03.03
CH2 싱글턴 패턴  (0) 2023.03.02

+ Recent posts