定義:動態地將責任附加到對象上。若要擴展功能,裝飾着提供了比繼承更有彈性的替代方案html
圖片引用至博文「裝飾者模式」java
要點:less
1.ConcreteComponent具體組件(基礎組件)和Decorator裝飾着組件都是Component子類或子接口,它們擁有相同的超類ide
2.裝飾着擁有具體組件的應用,能夠在調用具體組件的行爲以前或以後加上本身的行爲。測試
3.具體組件能夠被1到N個裝飾着對象裝飾this
4.對象能夠在任什麼時候候被裝飾,因此能夠在運行時動態地、不限量地用你喜歡的裝飾着來裝飾具體組件code
實現:htm
定義抽象類或者接口,由於場景須要有一個公共的屬性(食物的份數),因此把經常使用的接口改爲了抽象類,或者頂層保持接口,再新增一個抽象類對象
package com.jv.designpatterns.decorator; public abstract class Food { int count = 1; public abstract Float cost(); public abstract String desc(); public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
定義重慶小面類blog
package com.jv.designpatterns.decorator; //重慶小面 public class Noodle extends Food { private final static Float price_1 = 6F; private final static Float price_2 = 8F; private final static Float price_3 = 10F; Sizer s ; public Noodle() {} public Noodle(Sizer s) { this.s = s; } @Override public Float cost() { switch(s.getSize()) { case 1: return price_1*getCount(); case 2: return price_2*getCount(); case 3: return price_3*getCount(); default: return price_2*getCount(); } } @Override public String desc() { return getCount()+"份"+s.getSize()+"兩重慶小面"; } }
定義小面的裝飾者抽象類
package com.jv.designpatterns.decorator; public abstract class FoodDecorator extends Food { Food f ; //子類必須實現cost方法 public abstract Float cost(); public abstract String desc(); }
定義牛肉臊子裝飾者
package com.jv.designpatterns.decorator; //牛肉 public class Beef extends FoodDecorator { private final static Float price = 4F; private final static String desc = "牛肉"; public Beef() {} public Beef(Food f) { this.f=f; } @Override public Float cost() { return f.cost() + price*count; } @Override public String desc() { return f.desc()+"加"+count+"份"+desc; } }
定義泡菜臊子裝飾者
package com.jv.designpatterns.decorator; //泡菜 public class Pickle extends FoodDecorator { private final static Float price = 1F; private final static String desc = "泡菜"; public Pickle() {} public Pickle(Food f) { this.f = f; } @Override public Float cost() { return f.cost() + price*count; } @Override public String desc() { return f.desc()+"加"+count+"份"+desc; } }
定義小面特有尺寸類,使用組合的方式讓小面具有改變單分量的能力,而不須要使用繼承
package com.jv.designpatterns.decorator; public class Sizer { private int size = 2; public Sizer() {} public Sizer(int size) { this.size = size; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
測試類
package com.jv.designpatterns.decorator; public class DecoratorTest { public static void main(String[] args) { Sizer s = new Sizer(3); Food f = new Noodle(s); f = new Beef(f); f.setCount(2); f = new Pickle(f); System.out.println(f.desc()+",總計:"+f.cost()+"元"); } }
輸出結果:
1份3兩重慶小面加2份牛肉加1份泡菜,總計:19.0元