Decorator模式也叫裝飾模式,是由GoF提出的23種軟件設計模式的一種。Decorator模式是構造型的設計模式之一,它爲類的實例對象動態追加附加功能,就好像裝飾了對象的行爲。
Decorator模式是構造型的設計模式之一,它可以動態地改變一個對象方法的行爲。
Component
原有類的接口
ConcreteComponent
功能實現類。Component的具體實現類
Decorator
裝
飾抽象類。與ConcreteComponent一樣都繼承了Component接口,但實現的方式與ConcreteComponent有區別。
ConcreteComponent通過單純繼承的方式來實現;而Decorator則通過對Component對象的封裝與動作委讓方式來實現。
下面是一個典型的Decorator的代碼爲:
清單1
public class Decorator implement Component {
Component component;
public Decorator(Component component) {
this.component = component;
}
public void doSomething() {
...
this.component.doSomething();
...
}
}
ConcreteDecoratorA
與 ConcreteDecorator
具體的裝飾類。Decorator的具體實現類
爲什麼要如清單1所示去構造類的關係呢?或者說,爲什麼不直接使用一般的繼承或其他方法呢?我們通過下面的範例來回答這個問題。
比如,汽車上色的過程:
要對從工廠剛出來的同一種汽車進行上色,
首先給汽車上相同的底色;
然後根據不同的要求,進行下面的操作:
有時希望上黃色;
有時希望上紅色;
有時希望先上黃色,再上紅色;
有時希望先上紅色,再上黃色;
如果要在汽車類中完成上面的功能,不管是通過橫向擴展(爲類增加方法)還是縱向擴展(子類),都很難設計出柔軟的可擴展的類結構。
上述過程用Decorator模式來描述:
汽車抽象類Car相當於Decorator模式類圖中的Component,該接口定義了一個makeColor()方法用來給汽車上色
卡車類Truck相當於ConcreteComponent
上色抽象類MakeColorCar相當於Decorator
上黃色類MakeYellowColorCar與上紅色類MakeRedColorCar就相當於ConcreteDecorator
代碼:
- public class Client {
- //測試類
- public static void main(String[] args) {
- //生產一輛卡車1(基本色)
- System.out.println("--Truck 1--" );
- Car truck = new Truck();
- MakeColorCar yellowCar = new MakeYellowColorCar(truck);
- MakeColorCar redCar = new MakeRedColorCar(yellowCar);
- redCar.makeColor();
- //生產一輛卡車2(基本色)
- System.out.println("--Truck 2--" );
- Car truck2 = new Truck();
- MakeColorCar redCar2 = new MakeRedColorCar(truck2);
- MakeColorCar yellowCar2 = new MakeYellowColorCar(redCar2);
- yellowCar2.makeColor();
- }
- }
- /**
- * Component class & subclass
- *
- */
- interface Car {
- //上色
- public void makeColor();
- }
- class Truck implements Car {
- public void makeColor() {
- System.out.println("Make basic-color for truck:" );
- }
- }
- /**
- * Decorator class & subclass
- *
- */
- class MakeColorCar implements Car {
- protected Car car;
- public MakeColorCar(Car car) {
- this .car = car;
- }
- public void makeColor() {
- this .car.makeColor();
- }
- }
- class MakeYellowColorCar extends MakeColorCar {
- public MakeYellowColorCar(Car car) {
- super (car);
- }
- public void makeColor() {
- super .makeColor();
- System.out.println("Add yellow." );
- }
- }
- class MakeRedColorCar extends MakeColorCar {
- public MakeRedColorCar(Car car) {
- super (car);
- }
- public void makeColor() {
- super .makeColor();
- System.out.println("Add red." );
- }
- }
public class Client {
//測試類
public static void main(String[] args) {
//生產一輛卡車1(基本色)
System.out.println("--Truck 1--");
Car truck = new Truck();
MakeColorCar yellowCar = new MakeYellowColorCar(truck);
MakeColorCar redCar = new MakeRedColorCar(yellowCar);
redCar.makeColor();
//生產一輛卡車2(基本色)
System.out.println("--Truck 2--");
Car truck2 = new Truck();
MakeColorCar redCar2 = new MakeRedColorCar(truck2);
MakeColorCar yellowCar2 = new MakeYellowColorCar(redCar2);
yellowCar2.makeColor();
}
}
/**
* Component class & subclass
*
*/
interface Car {
//上色
public void makeColor();
}
class Truck implements Car {
public void makeColor() {
System.out.println("Make basic-color for truck:");
}
}
/**
* Decorator class & subclass
*
*/
abstract class MakeColorCar implements Car {
protected Car car;
public MakeColorCar(Car car) {
this.car = car;
}
public void makeColor() {
this.car.makeColor();
}
}
class MakeYellowColorCar extends MakeColorCar {
public MakeYellowColorCar(Car car) {
super(car);
}
public void makeColor() {
super.makeColor();
System.out.println("Add yellow.");
}
}
class MakeRedColorCar extends MakeColorCar {
public MakeRedColorCar(Car car) {
super(car);
}
public void makeColor() {
super.makeColor();
System.out.println("Add red.");
}
}
執行Client,輸出結果:
C:/Decorator>java Client
--Truck 1--
Make basic-color for truck:
Add yellow.
Add red.
--Truck 2--
Make basic-color for truck:
Add red.
Add yellow.
C:/Decorator>
對於類的不同對象truck1與truck2,我們可以應用Decorator模式改變其行爲:我們爲truck1先上底色,然後上黃色,再上紅色;但爲truck2先上底色,然後上紅色,再上黃色。
有關Adapter模式和Builder模式的介紹,請參考下面2篇文章:
設計模式之Adapter - 適配器模式
設計模式之Bridge - 橋接模式
與Decorator模式一樣,它們具有以下相同點
:
- 都是構造型的設計模式
- 都是通過新類對原有類的封裝(繼承或委讓的方式)
它們的不同點
:
- 對象:Adapter強調外部接口,Bridge強調內部實現。Adapter通過提供新的接口形式隱蔽對原有類(功能)的調用,Bridge把同一事物的抽象與具體行爲分離。
- 封裝:Decorator可以不用修改原有對象接口,爲對象增加新的功能或改變其行爲;Adapter如需增加功能,則需修改接口。
舉例來說,比如有一樣東西,它提供a,b,c等功能,
採用Adapter模式來實現的話,就等於告訴用戶,我有a, b, c等功能,你可以使用,但這些功能都是通過外部(調用其它類)實現的。
Bridge則這樣告訴用戶:有一樣東西A,提供某項功能,這項功能可能是a, 或b, 或c功能,用戶自己在使用A時,可以選擇讓A組合a功能(A+a),或b功能(A+b),或c功能(A+c)。
Decorator則是這樣:有一樣東西A,提供一個基本功能a。另外給它做了具有功能b的封套B,具有功能c的封套C。你可以在使用A時,把A裝進B,或C裏,這樣就具有a+b,或a+c功能了,甚至還可以把裝有A的B裝入到C裏,這樣便具有a+b+c功能了。