Decorator Pattern
단계별 선택지 존재하는 경우
- Choice Step 1 = Big/Small
- Choice Step 2 = Fast/Mid/Slow
- Choice Step 3 = Robot/Tank
이를 구현하기 위한 방법
1. 모든 케이스에 대한 클래스를 다 만들어주기
ex) BigFastRobot(), BigFastTank() ....
- 모든 것을 다 만들어야 함 -> 추가/삭제 등의 유지보수의 어려움
2. 단계별 Class 생성
ex) Step1 { //Big, Small // }
Step2 { //Fast/Mid/Slow // }
Step3 { //Robot/Tank // }
3. new Big(new Slow(new Robot())) 와 같이 사용할 수 있도록 하는 방법 -> 이게 Decorator Pattern
개요
- 객체의 결합 을 통해 기능을 동적으로 유연하게 확장 할 수 있게 해주는 패턴
구현 방법 -1 (interface 이용)
public class main {
public static void main(String[] args) {
Pizza myp = new Cheddar(new CombiPizza());
//Pizza p = new Cheddar(new SuperPizza());
System.out.println(myp.getProduct());
System.out.println(myp.getPrice());
myp = new GogumaDow(myp);
System.out.println(myp.getProduct());
System.out.println(myp.getPrice());
}
}
interface Pizza {
String getProduct();
int getPrice();
}
class SuperPizza implements Pizza { // [1] 1번째 선택
@Override
public String getProduct() { return "SupperPizza"; }
@Override
public int getPrice() { return 100; }
}
class CombiPizza implements Pizza {
@Override
public String getProduct() { return "CombiPizza"; }
@Override
public int getPrice() { return 200; }
}
interface Ingredient extends Pizza { // [2] 이후 추가되는 부분을 위한 interface
}
class GogumaDow implements Ingredient {
private Pizza pz; // [3]
public GogumaDow(Pizza pz) {
this.pz = pz;
}
@Override // [4]
public String getProduct() { return pz.getProduct()+" + GogumaDow"; }
@Override
public int getPrice() { return pz.getPrice()+50; }
}
class Cheddar implements Ingredient {
private Pizza pz;
public Cheddar(Pizza pz) {
this.pz = pz;
}
@Override
public String getProduct() { return pz.getProduct()+" + Cheddar"; }
@Override
public int getPrice() { return pz.getPrice()+80; }
}
- [1] 첫번째 선택 -> Parameter 없이 수행되는 첫번째
- [2] 추가되는 선택을 위한 interfac
- [3] 이전 Pizza의 instance를 저장하기 위한 변수
- [4] 현 instance의 이름을 재귀 형태로 가져옴
구현 방법 -2 (abstract class이용 & 중복부분 제거)
public class main {
public static void main(String[] args) {
//Pizza myp = new CombiPizza();
Pizza myp = new Cheddar(new CombiPizza());
//Pizza myp = new Cheddar(new SuperPizza());
System.out.println(myp.getProduct());
System.out.println(myp.getPrice());
myp = new GogumaDow(myp);
System.out.println(myp.getProduct());
System.out.println(myp.getPrice());
}
}
abstract class Pizza { // [1] abstract class
protected int price;
protected String name;
public String getProduct() { return name; }
public int getPrice() { return price; }
}
class SuperPizza extends Pizza {
SuperPizza() {
price = 1000;
name = "SuperPizza";
}
}
class CombiPizza extends Pizza {
CombiPizza() {
price = 1500;
name = "CombiPizza";
}
}
abstract class Ingredient extends Pizza {
protected Pizza pz;
protected String name;
protected int price;
public String getProduct() {
return pz.getProduct()+" + "+name;
}
public int getPrice() { return pz.getPrice()+price; }
}
class GogumaDow extends Ingredient {
public GogumaDow(Pizza pz) {
this.pz = pz;
name = "GogumaDow";
price = 300;
}
}
class Cheddar extends Ingredient {
public Cheddar(Pizza pz) {
this.pz = pz;
name = "Cheddar";
price = 500;
}
}
- [1] 중복적인 부분을 제거하기 위해 abstract class를 활용
> abstract class 내에서 변수 사용하기 위해서 protected 사용
> 모듈은 interface 사용핼 때와 같이 extends 하는 class에서 구현
[참고] 커피 주문 PJT
import java.util.Scanner;
public class main {
static Scanner scanner = new Scanner(System.in);
static Coffee step1() {
System.out.print("[Step-1]\n- Choose Cup (1. Big Cpu, 2. Small Cup) : ");
int stepIn = scanner.nextInt();
if (stepIn == 1) return new BigCup();
else return new SmallCup();
}
static Coffee step2(Coffee myCoffee) {
System.out.print("[Step-2]\n- Choose Drink (1. Americano, 2. Milk, 3. Cream) : ");
int stepIn = scanner.nextInt();
if (stepIn == 1) return new Ameri(myCoffee);
else if (stepIn == 2) return new Milk(myCoffee);
else return new Cream(myCoffee);
}
static Coffee step3(Coffee myCoffee) {
System.out.print("[Step-3]\n- Choose Cyrup (1. Strawberry, 2. Milk, 3. Banana) : ");
int stepIn = scanner.nextInt();
if (stepIn == 1) return new Strawberry(myCoffee);
else return new Banana(myCoffee);
}
public static void main(String[] args) {
Coffee myCoffee;
myCoffee = step1();
myCoffee = step2(myCoffee);
myCoffee = step3(myCoffee);
//Coffee myCoffee = new Strawberry(new Ameri(new BigCup()));
System.out.println("Result : ");
System.out.println("Prod = "+ myCoffee.getProd() );
System.out.println("Price = "+ myCoffee.getPrice());
}
}
abstract class Coffee {
protected String cName;
protected int cPrice;
String getProd() { return null; }
int getPrice() { return 0; }
}
abstract class Cup extends Coffee {
String getProd() { return cName; }
int getPrice() { return cPrice; }
}
class BigCup extends Cup {
public BigCup() { cName = "BigCup" ; cPrice = 400; }
}
class SmallCup extends Cup {
public SmallCup() { cName = "SmallCup"; cPrice = 200; }
}
abstract class Addition extends Coffee {
protected Coffee coffee;
public String getProd() {
return coffee.getProd()+" + "+ cName;
}
public int getPrice() {
return cPrice+ coffee.getPrice();
}
}
class Ameri extends Addition {
public Ameri(Coffee coffee) { this.coffee = coffee; cName = "Americano" ; cPrice = 200; }
}
class Milk extends Addition {
public Milk(Coffee coffee) { this.coffee = coffee; cName = "Milk" ; cPrice = 1400;}
}
class Cream extends Addition {
public Cream(Coffee coffee) { this.coffee = coffee; cName = "Cream" ; cPrice = 700; }
}
class Strawberry extends Addition {
public Strawberry(Coffee coffee) { this.coffee = coffee; cName = "StrawBerry"; cPrice = 250; }
}
class Banana extends Addition {
public Banana(Coffee coffee) { this.coffee = coffee; cName = "Banana" ; cPrice = 150; }
}
=============================================================================
[Step-1]
- Choose Cup (1. Big Cpu, 2. Small Cup) : 1
[Step-2]
- Choose Drink (1. Americano, 2. Milk, 3. Cream) : 2
[Step-3]
- Choose Cyrup (1. Strawberry, 2. Milk, 3. Banana) : 1
Result :
Prod = BigCup + Milk + StrawBerry
Price = 2050
'Software Architect' 카테고리의 다른 글
[Design Pattern] Flyweight pattern (0) | 2022.03.25 |
---|---|
[Design Pattern] Observer Pattern (0) | 2022.03.25 |
[Design Pattern] Adapter Pattern (0) | 2022.03.24 |
[Design Pattern] Facade Pattern (0) | 2022.03.24 |
[Design Pattern] Singleton Pattern (0) | 2022.03.24 |