概念:動態的給一個對象添加一些額外的功能。就增長功能來講,裝飾模式比生成自子類更加的靈活。cookie
舉個例子,筆者本身之前喜歡吃手抓餅。天天都要去十字路口大爺那裏買手抓餅,可是大爺賣的手抓餅有大份,小份等等,還有各類口味的配料添加。好比我比較喜歡變態辣,喜歡加火腿,喜歡加雞蛋,因此每次去買手抓餅都會在最基礎的手抓餅上加上"裝飾",讓他變成豪華版手抓餅,這其實就是裝飾模式的一個體現。ide
手抓餅其實就是一個組件(Component),以後會有不少的裝飾類(Decorate)對它進行裝飾,好比加雞蛋,變態辣等等。測試
Cookie類,組件接口,僅僅包含一個售價方法,cost()this
public interface Cookie { public double cost(); }
BigCookie類,大份手抓餅,具體的手抓餅實現類spa
public class BigCookie implements Cookie { @Override public double cost() { return 6.0; } }
BatchCookie類,裝飾的抽象類,此處演示並無將它設爲抽象設計
public class BatchCookie implements Cookie { private Cookie cookie; public BatchCookie(Cookie cookie){ this.cookie = cookie; } @Override public double cost() { return cookie.cost(); } }
AddEgg類,AddHam類都是繼承了BatchCookie類,爲具體的裝飾方法,加雞蛋加兩元,加火腿加一塊code
public class AddEgg extends BatchCookie { public AddEgg(Cookie cookie) { super(cookie); } @Override public double cost() { return super.cost() + 2; } }
public class AddHam extends BatchCookie { public AddHam(Cookie cookie) { super(cookie); } @Override public double cost() { // TODO Auto-generated method stub return super.cost() + 1; } }
客戶端代碼component
public class Show2 { public static void main(String[] args) { Cookie cookie = new BigCookie(); cookie = new AddEgg(cookie); cookie = new AddHam(cookie); double money = cookie.cost(); System.out.println("大份手抓餅加雞蛋加火腿一塊兒" + money + "元"); } }
測試結果對象
大份手抓餅加雞蛋加火腿一塊兒9.0元
能夠看到手抓餅能夠加雞蛋加火腿,手抓餅被裝飾了,本來普通的手抓餅添加了新的功能,而這就是裝飾模式的最直接的體現,接下來看看裝飾模式的具體結果。blog
Component類,組件抽象類,被裝飾對象的抽象類
public abstract class Component { public abstract void opreate(); }
ConcreteComponent類,具體的組件實現類,也能夠對該對象進行動態的裝飾,即添加新功能
public class ConcreteComponent extends Component { @Override public void opreate() { System.out.println("具體對象的操做"); } }
Decorate類,裝飾的抽象類,也繼承了Component對象
public class Decorate extends Component { private Component component; public Component getComponent() { return component; } //設置Component public void setComponent(Component component) { this.component = component; } //重寫operate(),實際執行的是component的operate() @Override public void opreate() { if (component != null) { component.opreate(); } } }
ConcreteDecorateA類,具體的裝飾類,實現了Decorate類,並提供了該裝飾對象獨特的裝飾方法
public class ConcreteDecorateA extends Decorate { //本類獨有的裝飾功能,區別於ConcreteDecorateB private String addedState; public String getAddedState() { return addedState; } public void setAddedState(String addedState) { this.addedState = addedState; } @Override public void opreate() { super.opreate(); this.addedState = "New State"; System.out.println("具體裝飾對象A的操做"); } }
ConcreteDecorateB類,也提供了該對象獨特的裝飾方法
public class ConcreteDecorateB extends Decorate { private void addedBehavior(){ System.out.println("裝飾類B添加行爲"); } @Override public void opreate() { super.opreate(); System.out.println("具體裝飾對象B的操做"); addedBehavior(); } }
客戶端代碼
public class Show { //首先用ConcreteComponent實例對象component,而後用ConcreteDecorateA //對象d1來包裝component,再用ConcreteDecorateB對象d2來包裝d1,最後是用 //d2執行opreate() public static void main(String[] args) { ConcreteComponent component = new ConcreteComponent(); ConcreteDecorateA d1 = new ConcreteDecorateA(); ConcreteDecorateB d2 = new ConcreteDecorateB(); d1.setComponent(component); d2.setComponent(d1); d2.opreate(); } }
測試結果
具體對象的操做
具體裝飾對象A的操做
具體裝飾對象B的操做
裝飾類B添加行爲
上面就是裝飾模式的節本構造,雖然不是很好懂,可是結合實際生活的場景就很容易理解。
Component是定義一個對象接口,能夠給這些對象動態的添加功能。ConcreteComponent是定義了一個具體的對象,也能夠給這個對象添加一些功能。Decorate類,裝飾抽象類,也繼承了從外來類擴展Component的功能,可是對於Component來講,沒有必要知道Decorate的存在。至於ConcreteDecorate就是具體的裝飾對象,起到了給Component添加功能的做用。
裝飾模式是爲已有的功能動態的添加更多功能的一種方式。當系統須要添加新功能的時候,是向舊的類中添加新代碼,這是設計之初的想法,可是嚴重違反了開放-封閉原則,這些新加的功能嚴重和原有的類耦合在一塊兒了,由於新加入的功僅僅是爲了知足一些只在某種特定狀況下才會執行的特殊行爲的須要。可是裝飾模式提供了一個很是好的解決方案,它把每一個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,所以,當須要執行特殊行爲時,客戶端代碼就能夠在運行時根據須要有選擇的、按順序的使用裝飾功能的包裝對象。