1. 情景

面館開張了,主營2種面:酸菜面、牛肉面;外加2種配料:雞蛋、豆皮
用裝飾者模式來設計這一訂單系統:
滿足要求:可以傳回點的名稱、計算總價格
2. 設計
大體思路:
這裡要說的是雞蛋、豆皮是裝飾者,為了讓他可以任意的加配料,傳回仍是面條類。
類設計圖:
3. 實作
面條抽象類
public abstract class Noodle {
String description = "Unknown Name";
public String getDescription() {
return description;
}
public abstract double cost();
}
裝飾者抽象類
public abstract class CondimentDecorator extends Noodle {
@Override
public abstract String getDescription();
}
面條具體類--酸菜面
public class SuancaiNoodle extends Noodle{
SuancaiNoodle() {
description = "Suancai Noodle";
}
@Override
public double cost() {
return 10;
}
}
面條具體類--牛肉面
public abstract class Noodle {
String description = "Unknown Name";
public String getDescription() {
return description;
}
public abstract double cost();
}
配料具體類--雞蛋
public class Egg extends CondimentDecorator{
private Noodle noodle;
Egg(Noodle noodle) {
this.noodle = noodle;
}
@Override
public String getDescription() {
return noodle.getDescription() + " + Egg";
}
@Override
public double cost() {
return noodle.cost() + 2;
}
}
配料具體類--豆皮
public class SkinOfTofu extends CondimentDecorator{
private Noodle noodle;
SkinOfTofu(Noodle noodle) {
this.noodle = noodle;
}
@Override
public String getDescription() {
return noodle.getDescription() + " + SkinOfTofu";
}
@Override
public double cost() {
return noodle.cost() + 1;
}
}
4. 測試
public class NoodleTest {
public static void main(String[] args) {
Noodle suancai = new SuancaiNoodle();
Noodle addEgg = new Egg(suancai);
Noodle addEggSkin = new SkinOfTofu(addEgg);
System.out.println(addEggSkin.getDescription());
System.out.println(addEggSkin.cost());
System.out.println("-----");
Noodle beef = new BeefNoodle();
Noodle addEgg2 = new Egg(beef);
System.out.println(addEgg2.getDescription());
System.out.println(addEgg2.cost());
}
}
結果
Suancai Noodle + Egg + SkinOfTofu
13.0
-----
Beef Noodle + Egg
14.0
5.java I/O
其中InputStream是抽象元件
其下一列如FileInputStream是抽象裝飾者,BufferedInputStream是具體裝飾者
用法舉例
public class ReadFileTest {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("jihite/test.json");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedInputStream bis2 = new BufferedInputStream(bis);
byte[] b = new byte[bis2.available()];
bis2.read(b);
System.out.println(new String(b));
bis2.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
6. 歸納
定義:
在不必改變原類檔案和使用繼承的情況下,動态地擴充一個對象的功能。它是通過建立一個包裝對象,也就是裝飾來包裹真實的對象。
設計原則:
- 多組合、少繼承
- 對擴充開放、對修改關閉
優點:
- Decorator模式與繼承關系的都是要擴充對象,但是Decorator可以提供比繼承更多的靈活性
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合
缺點:
- 比繼承更加靈活也同時意味着更加多的複雜性
- 導緻設計中出現許多小類,如果過度使用,會使程式變得很複雜