職責:
- 動態的爲一個對象增加新的功能
- 裝飾模式是一種代替繼承的技術,無需通過繼承增加子類就能擴展對象的新功能。使用對象的關聯關係代替繼承關係,更加靈活,同時避免類型體系的快速膨脹。
實現細節:
- Component抽象構件角色
- 真實對象和裝飾對象有相同的接口。這樣,客戶端對象就能夠以與真實對象相同的方式同裝飾對象交流。
- ConcreteComponent 具體構建角色(真實對象):
- IO流中的FileInputStream FileOutputStream
- Decorator裝飾角色:
- 持有一個抽象構件的引用。裝飾對象接受所有客戶端的請求,並把這些請求轉發給真實的對象。這樣,就能在真實對象的調用前後增加新的功能。
- ConcreteDecorator具體裝飾角色:
- 負責給構件對象增加新的責任
開發中使用的場景:
- IO中輸入流和輸出流的設計
- Swing包中圖形界面的構件功能
- Servlet API中提供了一個request對象的Decorator設計模式的默認實現類HttpServletRequestWrapper, HttpServletRequestWrapper類,增強了request對象的功能。
- Struts2 中,request,response,session對象的處理
總結
- 裝飾模式(Decorator)也叫包裝器模式(Wrapper)
- 裝飾模式降低系統的耦合度,可以動態的增加或刪除對象的職責,並使得需要裝飾的具體構建類和具體裝飾類可以獨立變化,以便增加新的具體構建類和具體裝飾類。
優點
- 擴展對象功能,比繼承靈活,不會導致類個數的急劇增加
- 可以對一個對象進行多次裝飾,創造出不同行爲的組合,得到功能更加強大的對象。
- 具體構建類和具體裝飾類可以獨立變化,用戶可以根據需要自己增加新的具體構建子類和具體裝飾子類。
缺點
- 產生很多小對象。大量小對象佔據內存,一定程度上影響性能。
- 裝飾模式容易出錯,調試排查比較麻煩。
裝飾模式和橋接模式的區別:
- 兩個模式都是爲了解決過多子類對象的問題。但是他們的誘因不一樣。橋接模式是對象自身現有機制沿着多個維度變化,是既有部分不穩定。裝飾模式是爲了增加新的功能。
一種代碼實現
package com.coderbean.decorator;
/**
* Created by Chang on 15/10/1.
*/
public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move();
System.out.println();
ICar newCar = new FlyCar(car);
newCar.move();
System.out.println();
new WaterCar(car).move();
System.out.println();
new AICar(newCar).move();
System.out.println();
new AICar(new FlyCar(new WaterCar(new Car()))).move();
}
}
package com.coderbean.decorator;
/**
* 抽象組件
* Created by Chang on 15/9/30.
*/
public interface ICar {
void move();
}
//ConcreteComponent 具體構件角色(真實對象)
class Car implements ICar {
@Override
public void move() {
System.out.println("陸地上跑");
}
}
//Decorator裝飾角色
class SuperCar implements ICar {
private ICar car;
public SuperCar(ICar car) {
this.car = car;
}
@Override
public void move() {
car.move();
}
}
//ConcreteDecorator具體裝飾角色
class FlyCar extends SuperCar {
public FlyCar(ICar car) {
super(car);
}
public void Fly(){
System.out.println("在天上飛");
}
@Override
public void move() {
super.move();
Fly();
}
}
class WaterCar extends SuperCar {
public WaterCar(ICar car) {
super(car);
}
public void swim(){
System.out.println("水中游");
}
@Override
public void move() {
super.move();
swim();
}
}
class AICar extends SuperCar {
public AICar(ICar car) {
super(car);
}
public void autoMove(){
System.out.println("自動駕駛!");
}
@Override
public void move() {
super.move();
autoMove();
}
}