Java設計模式之裝飾者模式

裝飾者模式
裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
具體被裝飾者和抽象裝飾類都繼承於相同的抽象類,繼承的是類型,而不是行爲 。行爲來自裝飾者和基礎組件,或與其餘裝飾者之間的組合關係。它也稱爲追MM模式。
在實際開發中,對於應用中,若是一個基類包含許多個不一樣的子類,而每個子類具備不一樣的附加物。此時就能夠考慮用裝飾者模式了。在裝飾者模式中,要劃分出哪些是主體部分,哪些是裝飾者。而一個主體能夠擁有多個裝飾者,裝飾者又能夠繼續裝飾裝飾者,則就須要主體和裝飾者繼承於一個相同的基類類型。這樣經過繼承後,繼承的就是類型,而不是行爲。每個裝飾者都「有一個」主體,裝飾者內部有一個實例變量做爲引用保存某一個主體的。全部的裝飾者統一實現一個裝飾者接口。
一般在裝飾者模式中,都採用抽象類。裝飾者模式,被裝飾者必須和裝飾者實現相同的接口,通常是在裝飾者行爲或方法中轉發被裝飾者行爲(即調用被裝飾者的行爲)。
在開發過程當中,若是過於依賴繼承,則類的行爲就會在編譯的時候靜態決定了,行爲若是不是來自超類,就是來自子類覆蓋後的版本。而若是利用組合,在能夠在運行中動態的組裝了。
具體事例:
一個酒店有多個飲料,可是全部的飲料都須要繼承同一個類,而每一個飲料卻又有不一樣的添加物.
抽象基類:
package com.whut.decorate;
//裝飾者模式
public abstract class Beverage {

String description= "Unknown Beverage";

public String getDescription()
{
return description;
}

public abstract double cost();
}
它有多個具體類型的飲料,也就是多個被裝飾者。列舉一個:
package com.whut.decorate;
//綜合咖啡
public class HouseBlend extends Beverage {

public HouseBlend()
{
description= "HouseBlend";
}

@Override
public double cost() {
// TODO Auto-generated method stub
return 0.89;
}
}
因爲每個 被裝飾者,即飲料均有多個不一樣的添加。裝飾者的抽象類類以下:
package com.whut.decorate;

//裝飾者基類
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
具體裝飾者:
package com.whut.decorate;

//摩卡裝飾者
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage)
{
this.beverage=beverage;
}

@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription()+ ",Mocha";
}

@Override
public double cost() {
// TODO Auto-generated method stub
return 0.2+beverage.cost();
}
}
測試類:
package com.whut.decorate;

public class CustomerDrink {

public static void main(String[] args)
{
Beverage beverage= new Espresso();
System.out.println(beverage.getDescription()+ " $"+beverage.cost());

//注意這種方式
//頂了兩個Mocha和Whip的DarkRoast咖啡
Beverage beverage2= new DarkRoast();
beverage2= new Mocha(beverage2);
beverage2= new Mocha(beverage2);
beverage2= new Whip(beverage2);
System.out.println(beverage2.getDescription()+ " $"+beverage2.cost());

Beverage beverage3= new HouseBlend();
beverage3= new Soy(beverage3);
beverage3= new Mocha(beverage3);
beverage3= new Whip(beverage3);
System.out.println(beverage3.getDescription()+ " $"+beverage3.cost());

}
}
這裏就是在運行中動態的裝飾飲料。
在java中,常見的裝飾者模式,就是I/O類。
設計原則 :類應該對擴展開放,對修改關閉。
主要的意思就是容許類容易擴展,在不修改現有的代碼狀況下,能夠搭配新的行爲,而這些行爲每每是在運行的時候搭配的,經過裝飾者模式動態的將責任附加到對象中。
要點總結
1)繼承屬於擴展形式之一,但不見得是達到彈性設計的最佳方式。
2)在設計中,應該容許行爲能夠被擴展,而無須修改現有的代碼。
3)組合和委託可用於在運行時動態地加上新的行爲。
4)除了繼承,裝飾者模式也可讓咱們擴展行爲。
5 )裝飾者模式意味着一羣裝飾者類,這些類用來包裝具體組件。
6)裝飾者類反映出被裝飾的組件類型(事實上,他們具備相同的類型,都通過接口或繼承實現)。
7)裝飾者能夠在被裝飾者的行爲前面與/或後面加上本身的行爲,甚至將被裝飾者的行爲整個取代掉,而達到特定的目的。
8)能夠用無數個裝飾者包裝一個組件。
9)裝飾者通常對組件的客戶是透明的,除非客戶程序依賴於組件的具體類型。
10)裝飾者會致使設計中出現許多小對象,若是過分使用,會讓程序變得很複雜。
相關文章
相關標籤/搜索