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可以提供比繼承更多的靈活性
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合
缺點:
- 比繼承更加靈活也同時意味着更加多的復雜性
- 導致設計中出現許多小類,如果過度使用,會使程序變得很復雜