裝飾者模式:
動態的將責任附加到對象上,若要擴充功能,裝飾者提供了比繼承更具有彈性的代碼方案。因爲基類加入新的功能時不一定適合所有的子類,這也導致了繼承不能解決所有的問題。
設計原則(開放-關閉):
類應該對擴展開放(能夠擴展),對修改關閉(不能修改現有的代碼)。
特點:
1. 裝飾者和被裝飾着具有相同的超類,這樣才能保證裝飾者與被裝飾者是相同的類型;
2. 可以用一個或者多個裝飾者包裝一個對象;
3. 既然裝飾者和被裝飾着具有相同的超類,所以在任何需要原始對象(被包裝的)的場合,可以用裝飾過的對象代替它;
4. 裝飾者可以在所委託被裝飾者的行爲之前或之後,加上自己的行爲,以達到待定的目的("關鍵點")。
用例:
場景描述:
假設我們做的是一個賣衣服有的功能,我們目前的衣服有Jockets、Clothes等,正常情況下每件衣服都有特定的價格cost()。但是最近雙11來了,所以公司要求做促銷活動,比如買一件衣服再加10元就能送襪子,加50元就能送鞋子等等。
思路:
1. 在Jockets、Clothes等衣服類裏面都加上各種活動商品,並重新計算價格。如果商品種數少還勉強可以,但是如果有很多商品了,那就傻眼了,所以這種不可行;
2. 在衣服的超類Goods裏面去加上各種活動商品的價格,這樣做看似可行,但是如果活動品的價格改變了怎麼辦? 客戶要雙份的活動品又該怎麼辦? 這樣只能在超類的cost()方法裏面做處理了,這就改變了我們現有的代碼,違反了我們的開放關閉原則,而且如果商品多了一不小心還會出錯,所以放棄了這種實現;
3. 利用裝飾者模式,這也是我採用的方式:
實現:
1. 首先創建一個商品的超類Goods:
public abstract class Goods { protected String DES = "this is a good"; public String des(){ return DES; } public abstract double cost();2. 創建衣服商品類(被裝飾者)來繼承這個超類:
public class Jackets extends Goods { public Jackets(){ DES = "this is jackets"; } @Override public double cost() { return 200; }3. 因爲裝飾者和被裝飾者必須是相同的類型,所以先創建一個Gadget來繼承Goods:
public abstract class Gadget extends Goods{ public abstract String des();//對商品的描述作用 }4. 創建襪子、鞋子等(裝飾者)類來繼承Gadget:
public class Shoes extends Gadget { private Goods goods;//拿到裝飾者的引用對象 public Shoes(Goods goods){ this.goods = goods; } @Override public String des() { return goods.des() + "And a shoes"; } @Override public double cost() { return goods.cost() + 20; }5. 這樣裝飾者也被裝飾者就大致創建好了,接下來就是使用了,比如要想知道Jackets加上Shoes的價格:
Goods goods = new Jackets(); goods = new Shoes(goods); tv_test.setText("描述:" + goods.des() + "價格: " + goods.cost());