디자인 패턴 - 데코레이터 패턴

안성은·2022년 4월 24일
0

Disign Pattern

목록 보기
8/9

데코레이터 패턴

정의

  • 객체에 추가적인 요건을 동적으로 첨가한다. 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.

사용하는 이유 및 특징

  • 기존 코드를 수정하지 않고 데코레이터 패턴을 통해 행동을 확장시킬 수 있다.
  • 구성과 위임을 통해서 실행중에 새로운 행동을 추가할 수 있습니다.
  • 하지만 데코레이터를 너무 많이 사용하면 코드가 필요 이상으로 복잡해실 수 있다.

UML

  • UML

  • 실제 적용 UML

데코레이터 패턴을 사용하지 않을 경우 문제점

  • 객체마다 추가되는 재료가 다르기 때문에 Cost() 함수는 각각의 음료가 override 해야하기 때문에 너무 많은 구현 클래스가 생성된다.

개선 과정 및 코드

  • EXAMPLE1

    • LowerCaseInputStream -> FilterInputStream -> InputStream
  public class LowerCaseInputStream extends FilterInputStream {

    protected LowerCaseInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        int c = super.read();
        return (c == -1 ? c : Character.toLowerCase((char)c));
    }

    @Override
    public int read(byte[] b, int offset, int len) throws IOException {
        int result = super.read(b, offset, len);
        for (int i = offset; i < offset + result; i++) {
            b[i] = (byte) Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}
  • TEST CODE
public class InputTest {
    public static void main(String[] args) throws IOException {
        int c;
        try {
            InputStream in =
                    new LowerCaseInputStream(
                            new BufferedInputStream(new FileInputStream("test.txt")));

            while( (c = in.read()) >= 0) {
                System.out.println((char)c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • EXAMPLE2
    • Beverage
      • Espresso
      • DarkRoast
      • HouseBlend
    • CondimentDecorator
      • Mocha
      • Whip
  • Beverage
public abstract class Beverage {
    String description = "제목없음";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}
  • Espresso
public class Espresso extends Beverage{

    public Espresso() {
        description = "에스프레소";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}
  • CondimentDecorator
public abstract class CondimentDecorator extends Beverage{

    public abstract String getDescription();
}
  • Mocha
public class Mocha extends CondimentDecorator {

    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", 모카";
    }

    @Override
    public double cost() {
        return beverage.cost() + 0.20;
    }
}
  • TEST CODE
public class StarbucksCoffee {

    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $ " + beverage.cost());

        Beverage beverage1 = new DarkRoast();
        beverage1 = new Mocha(beverage1);
        beverage1 = new Mocha(beverage1);
        beverage1 = new Whip(beverage1);
        System.out.println(beverage1.getDescription() + "$" + beverage1.cost());

        Beverage beverage2 = new HouseBlend();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription() + "$" + beverage2.cost());
    }
}

참고

0개의 댓글