2009年7月28日 星期二

Design Pattern - Decorator

Decorator Pattern 裝飾者模式

假設現在的例子是一間咖啡店, 可以產生各種飲料並計算價錢

老樣子, 先用繼承看看長怎樣 把共用的調味料寫在Beverage中, 例如milk,ice等

 
public class

Beverage{
public String description;
public int milk;
public int ice;

public getDescription();
public int calcCost(){
//計算調味料的價錢
}

//field get/set
}

public class Espresso() extends Beverage{

public int calcCost(){
//計算espresso的價錢
}
}

public class Decaf() extends Beverage{ }


Decorator Pattern 就想成是用一層層包起來的方式,

是利用組合的方式 例如 你點了一杯黑咖啡, 但你想加milk,whip ,

最後, 要計算價格 所以, 黑咖啡 <--裝飾 milk <--裝飾 whip

一些觀念:

1.裝飾者與被裝飾者要extends相同class(這裡所謂的接口是用繼承)

2.可以用一到多個去裝飾一個object

3.



public abstract class Beverage {

String description = "none";
public String getDescription(){
return description;
}

public abstract int calcCost();
}

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

public class Espresso extends Beverage{

public Espresso() {
System.out.println("new Espresso");
description = "buy Espresso"; //記在Beverage class
}

@Override
public int calcCost() {
System.out.println("calcCost by Espresso");
return 10;
}
}

public class Mocha extends CondimentDecorator {

Beverage beverage;
public Mocha(Beverage beverage) {
//就是這裡, 讓Mocha(裝飾者)能引用Beverage(被裝飾者)
this.beverage = beverage;
}

@Override
public String getDescription() {
System.out.println("new Mocha");
return beverage.getDescription() + ", Mocha";
}

@Override
public int calcCost() {
System.out.println("calcCost by Mocha");
return 1 + beverage.calcCost();
}
}

public class Whip extends CondimentDecorator {

Beverage beverage;
public Whip(Beverage beverage) {
//就是這裡, 讓Whip(裝飾者)能引用Beverage(被裝飾者)
this.beverage = beverage;
}

@Override
public String getDescription() {
System.out.println("new Whip");
return beverage.getDescription() + ", Whip";
}

@Override
public int calcCost() {
//自己的處理, 再加上呼叫引用的object
System.out.println("calcCost by Whip");
return 2 + beverage.calcCost();
}
}



public class DecoratorDemo {
public static void main(String[] args) {

Beverage beverage = new Espresso();
beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.calcCost());

Beverage beverage2 = new Espresso();
beverage2 = new Mocha(beverage2); //點二份Mocha, 用new Mocha去裝飾Beverage,
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);

System.out.println(beverage2.getDescription() + " $" + beverage2.calcCost());


/*
* 這裡印出來是
*
* calcCost by Whip
* calcCost by Mocha
* calcCost by Mocha
* calcCost by Espresso
* buy Espresso, Mocha, Mocha, Whip $14
*
* 這裡new了四個object, beverage2只有一份
* 分別引用了 new Espresso() <-- new Mocha() <-- new Mocha() <-- new Whip()
* 所以最後呼叫calcCost()時, calcCost()又遞迴的呼叫 beverage.calcCost();
*
*/
}
}

0 意見: