데코레이터 패턴 시간입니당!!!!!!!!!!!!!!!!
책에는 "상속맨, 디자인에 눈을 뜨다"라고 써있네요!
상속을 남용하는 전형적인 예를 살펴보고 객체 작성이라는 형식으로 실행중에 클래스를 꾸미는(데코레이터하는) 패턴을 배워볼거에욧
데코레이터 패턴을 배우면!!
원래 클래스의 코드는 전혀 바꾸지 않고도 기존의 객체에 새로운 임무를 부여할 수 있어요!
기존 코드는 건드리지 않은 채로 확장을 통해서 새로운 행동을 간단하게 추가할 수 있도록 하는게 바 로 데코레이터 패턴이죠!
새로운 기능을 추가하는 데 있어서 매우 유연해서 급변하는 주변 환경에 잘 적응할 수 있으면서도 강하고 튼튼한 디자인 !!
OCP라는 디자인 원칙이 있는데요
클래스는 확장에 대해서는 열려있어야 하며, 코드 변경에 있어서는 닫혀있어야 한다는 뜻입니다.
이제부터 제대로 시작합니당!
데코레이터 패턴!!!!!
정의 : 객체에 추가적인 요건을 동적으로 첨가한다.
데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.
까페를 예로 들겠습니다.
상속을 써서 음료 가격과 첨가물(샷, 시럽, 우유, 휘핑 크림 등) 가격을 합한 총 가격을 계산하는 방법은 그리 좋은 방법이 아닙니다.
그 이유는
1. 클래스가 어마어마하게 많아짐.
2. 일부 서브클래스에는 적합하지 않은 기능을 베이스 클래스에 추가하게 됨.(아이스티에 휘핑크림을 추가할 필요는 없음)
그렇기 때문에 어떤 특정 음료에서 시작해서! 그 음료를 장식할겁니다.!!!!!!!!
하나의 예로 모카하고 휘핑 크림을 추가한 다크 로스트 커피를 들게요.
1. 다크로스트 객체를 가져온다.
2. 모카 객체로 장식한다.
3. 휘핑 객체로 장식한다.
4. 코스트 메소드를 호출한다. 이 때 첨가물의 가격을 계산하는 일은 해당 객체들에게 위임된다.
예제
추상클래스들을 먼저 보여드릴게용
음료 클래스
1 2 3 4 5 6 7 8 9 10 11 12 | package abstract_package; public abstract class Beverage { protected String description = "제목 없음"; public String getDescription() { return description; } public abstract double cost(); } | cs |
첨가물 클래스
1 2 3 4 5 6 | package abstract_package; public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); } | cs |
이제 음료 클래스들과, 첨과물 클래스들을 보여드릴게요.
먼저 음료클래스
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package beverage; import abstract_package.Beverage; public class DarkRoast extends Beverage { public DarkRoast() { description = "다크로스트"; } @Override public double cost() { return 0.99; } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package beverage; import abstract_package.Beverage; public class Decaf extends Beverage { public Decaf() { description = "디카페인"; } @Override public double cost() { return 1.05; } } | cs |
더 있는데 너무 많으므로 두개씩만 할게요 풀코드 보고싶은 분은 코드 다운로드해서 봐주세요
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package condiment; import abstract_package.Beverage; import abstract_package.CondimentDecorator; public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha (Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", 모카"; } public double cost() { return 0.20 + beverage.cost(); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package condiment; import abstract_package.Beverage; import abstract_package.CondimentDecorator; public class Whip extends CondimentDecorator{ Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", 휘핑"; } public double cost() { return beverage.cost() + 0.10; } } | cs |
이제 메인클래스입니당.
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 27 28 29 30 31 32 | import abstract_package.Beverage; import beverage.DarkRoast; import beverage.Espresso; import beverage.HouseBlend; import condiment.Mocha; import condiment.Soy; import condiment.Whip; public class StarbuzzCoffee { public static void main(String[] args) { // TODO Auto-generated method stub Beverage beverage[] = new Beverage[3]; beverage[0] = new Espresso(); beverage[0] = new Mocha(beverage[0]); beverage[0] = new Mocha(beverage[0]); beverage[0] = new Whip(beverage[0]); beverage[1] = new DarkRoast(); beverage[1] = new Soy(beverage[1]); beverage[1] = new Mocha(beverage[1]); beverage[2] = new HouseBlend(); for (int i = 0; i < beverage.length; i++) { System.out.println(beverage[i].getDescription() + " $" + beverage[i].cost()); } } } | cs |
[출력결과]
에스프레소, 모카, 모카, 휘핑 $2.49
다크로스트, 두유, 모카 $1.3399999999999999
하우스 블렌드 커피 $0.89
1.3399999999999999
다 보고 싶으신 분은 풀 코드 다운로드하세요~~
'CS기본지식 > 디자인 패턴' 카테고리의 다른 글
옵저버 패턴(Observer Pattern) (0) | 2017.08.25 |
---|---|
스트래티지 패턴(Strategy Pattern) (0) | 2017.08.23 |