Java 디자인 패턴-11.Decorator

(Java 디자인 패턴 스터디 모집 중 : https://github.com/bluedskim/javaDesignPatterns)

Decorator 패턴

IEC 61131-3: The Decorator Pattern

(출처:https://stefanhenneken.net/2019/02/16/iec-61131-3-the-decorator-pattern)

해결하려는 문제

특징/용도

  1. 런타임에 객체에 동적으로 기능을 추가하기 위한 structural 패턴
  2. 래퍼wrapper 클래스로 구현.
  3. chain of responsibility pattern과 유사함
  4. 생성자 혹은 다른 메소드에서 해당 클래스 자체를 인수로 받는 경우 데코레이터라 볼 수 있다(https://refactoring.guru/design-patterns/decorator/java/example)

고려사항

클래스 다이어그램

Decorator 패턴(김동석)

소스

  • 꾸며질decorated 객체
    • BeverageBase.java : 부모 abstract 객체
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      
      package net.dskim.desingpattern.decorator;
      abstract class BeverageBase {
      
      	protected String description = "";
      
      	public String getDescription() {
      		return description;
      	}
      
      	/**
      	 * 가격을 계산하는 로직은 하위 객체가 구현해야 한다.
      	 * @return
      	 */
      	public abstract double getCost();
      }
    • BlackTea.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      package net.dskim.desingpattern.decorator;
      
      class BlackTea extends BeverageBase {
      
      	public BlackTea() {
      		description = "Black tea from teabag";
      	}
      
      	@Override
      	public double getCost() {
      		return 5;
      	}
      }
    • Espresso.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      package net.dskim.desingpattern.decorator;
      
      abstract class BeverageBase {
      
      	protected String description = "";
      
      	public String getDescription() {
      		return description;
      	}
      
      	/**
      	 * 가격을 계산하는 로직은 하위 객체가 구현해야 한다.
      	 * @return
      	 */
      	public abstract double getCost();
      }
    • GreenTea.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      package net.dskim.desingpattern.decorator;
      
      class GreenTea extends BeverageBase {
      
      	public GreenTea() {
      		description = "Green leaf tea";
      	}
      
      	@Override
      	public double getCost() {
      		return 8;
      	}
      }
  • 꾸미는decorator 객체
    • CondimentsDecoratorBase.java : 부모 abstract 객체
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      package net.dskim.desingpattern.decorator;
      
      /**
       * 데코레이터 객체
       */
      abstract class CondimentsDecoratorBase extends BeverageBase {
      	BeverageBase beverage;
      
      	/**
      	 * 생성자에서 BeverageBase의 참조를 받아서 멤버변수에 할당
      	 * @param beverage
      	 */
      	protected CondimentsDecoratorBase(BeverageBase beverage) {
      		this.beverage = beverage;
      	}
      }
    • CholateCondiment.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      package net.dskim.desingpattern.decorator;
      
      class ChocolateCondiment extends CondimentsDecoratorBase {
      	/**
      	 * 생성자에서 해당 클래스 자체를 인수로 받는다
      	 */
      	public ChocolateCondiment(BeverageBase beverage) {
      		super(beverage);
      		description = beverage.getDescription() + " + Chocolate";
      	}
      
      	@Override
      	public double getCost() {
      		return beverage.getCost() + 4;
      	}
      }
    • MilkCondiment.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      package net.dskim.desingpattern.decorator;
      
      class MilkCondiment extends CondimentsDecoratorBase {
      	public MilkCondiment(BeverageBase beverage) {
      		super(beverage);
      		description = this.beverage.getDescription() + " + Milk";
      	}
      
      	@Override
      	public double getCost() {
      		return beverage.getCost() + 3;
      	}
      }
    • SugarCondiment.java
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      package net.dskim.desingpattern.decorator;
      
      class SugarCondiment extends CondimentsDecoratorBase {
      	public SugarCondiment(BeverageBase beverage) {
      		super(beverage);
      		description = beverage.getDescription() + " + Sugar";
      	}
      
      	@Override
      	public double getCost() {
      		return beverage.getCost() + 1;
      	}
      }

참고