728x90
데코레이터 패턴 (Decorator Pattern)
객체에 추가 요소를 동적으로 더할 수 있다. 데코레이터를 사용하면 서브 클래스를 만드는 것보다 훨씬 유연하게 기능을 확장할 수 있다.
객체지향 원칙
OCP (Open-Closed Principle)
클래스는 확장에 대해서는 열려 있지만, 변경에 대해서는 닫혀 있어야 한다.
장점과 단점
장점
- 데코레이터를 끼워도 클라이언트 쪽에서 데코레이터를 사용하고 있다는 것을 전혀 알지 못한다.
단점
- 자잘한 클래스들이 많이 추가된다. 남들이 보기에 한 눈에 이해하기 어려울 수 있다.
- 특정 형식에 의존하는 코드에 데코레이터를 적용하면, 원래 의도와 맞지 않는다.
- 구성 요소를 초기화하는 데 필요한 코드가 훨씬 복잡해진다.
다이어그램
Java.IO 클래스 다이어그램
FilterInputStream 클래스가 InputStream 클래스를 구성요소로 갖고있는 데코레이터 클래스다.
예제 코드
- Beverages/Beverage.java
1 2 3 4 5 6 7 8 9 10 11 12 | package Beverages; public abstract class Beverage { String description = "제목 없음"; public String getDescription() { return description; } public abstract double cost(); } | cs |
- Beverages/CondimentDecorator.java
1 2 3 4 5 6 | package Beverages; public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } | cs |
- Beverages/Espresso.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package Beverages; public class Espresso extends Beverage { public Espresso() { description = "에스프레소"; } public double cost() { return 1.99; } } | cs |
- Beverages/DarkLoast.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package Beverages; public class DarkRoast extends Beverage { public DarkRoast() { description = "다크 로스트 커피"; } public double cost() { return .99; } } | cs |
- Beverages/HouseBlend.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package Beverages; public class HouseBlend extends Beverage { public HouseBlend() { description = "하우스 블렌드 커피"; } public double cost() { return .89; } } |
- Beverages/DeCaffeine.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package Beverages; public class DeCaffeine extends Beverage { public DeCaffeine() { description = "디카페인"; } public double cost() { return 1.05; } } | cs |
- Beverages/Mocha.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package Beverages; public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", 모카"; } public double cost() { return .20 + beverage.cost(); } } | cs |
- Beverages/SoybeanMilk.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package Beverages; public class SoybeanMilk extends CondimentDecorator { Beverage beverage; public SoybeanMilk(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", 두유"; } public double cost() { return .15 + beverage.cost(); } } | cs |
- Beverages/SteamMilk.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package Beverages; public class SteamMilk extends CondimentDecorator { Beverage beverage; public SteamMilk(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", 스팀밀크"; } public double cost() { return .10 + beverage.cost(); } } | cs |
- Beverages/WhippingCream.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package Beverages; public class WhippingCream extends CondimentDecorator { Beverage beverage; public WhippingCream(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", 휘핑크림"; } public double cost() { return .10 + beverage.cost(); } } | cs |
- Beverages/StarbuzzCoffee.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package Beverages; public class StarbuzzCoffee { public static void main(String[] args) { Beverage beverage = new Espresso(); System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new WhippingCream(beverage2); System.out.println(beverage2.getDescription() + " $" + beverage2.cost()); Beverage beverage3 = new HouseBlend(); beverage3 = new SoybeanMilk(beverage3); beverage3 = new Mocha(beverage3); beverage3 = new WhippingCream(beverage3); System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); } } | cs |
- IODecorator/LowerCaseInputStream.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package IODecorator; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; public class LowerCaseInputStream extends FilterInputStream { public LowerCaseInputStream(InputStream in) { super(in); } public int read() throws IOException { int c = super.read(); return (c == -1 ? c : Character.toLowerCase((char)c)); } public int read(byte[] b, int off, int len) throws IOException { int result = super.read(b, off, len); for (int i = off; i < off + result; i++) { b[i] = (byte)Character.toLowerCase((char)b[i]); } return result; } } | cs |
- IODecorator/InputTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package IODecorator; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class InputTest { public static void main(String[] args) { int c; try { InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt"))); while ((c=in.read()) >= 0) { System.out.print((char)c); } in.close(); } catch (IOException e) { e.printStackTrace(); } } } | cs |
'자바 > 자바 자료실' 카테고리의 다른 글
[디자인 패턴] 06. 커맨드 패턴 (Command Pattern) (0) | 2018.10.23 |
---|---|
[디자인 패턴] 05. 싱글턴 패턴 (Singleton Pattern) (0) | 2018.10.23 |
[디자인 패턴] 04. 팩토리 패턴 (Factory Pattern) (0) | 2018.10.23 |
[디자인패턴] 02. 옵저버 패턴 (Observer Pattern) (0) | 2018.10.19 |
[디자인패턴] 01. 스트래티지 패턴 (Strategy Pattern) (0) | 2018.10.19 |
댓글