1.定義
動態(tài)地給一個對象添加一些額外的職責(zé)弄屡。就增加功能來說量承,裝飾模式相比生成子類更為靈活搬设。
也叫裝飾者模式或者裝飾器模式。
比如給一個人穿衣服裝飾撕捍。
抽象一個人拿穴,給他穿的動作。普通方式要再裝飾他就需要繼承它忧风,然后做修改默色,但是會對孫子類有影響。
現(xiàn)在是繼承這個抽象的人狮腿,然后再穿的動作之后進(jìn)行其他裝飾腿宰。
2.角色
- Component:定義一個對象接口,可以給這些對象動態(tài)添加職責(zé)缘厢。真實對象和裝飾者對象有相同的接口吃度,這樣客戶端不用知道內(nèi)部有裝飾者對象(Decorator)
存在的,還是以之前處理真實對象的相同方式來和裝飾者對象交互贴硫。
ConcreteComponent:是定義了一個具體的對象(例如:人)椿每,也可以給這個對象添加一些其他職責(zé)。
Decorator:裝飾抽象類,繼承了Component间护,從外類來擴(kuò)展Component類的功能删壮,但對Component來說,是無需知道Decorator存在的兑牡。
ConcreteDecorator:就是具體的裝飾對象了(衣服央碟,鞋子..),它起到了給Component添加職責(zé)的功能均函。
3.代碼實現(xiàn)
Component對象接口(ICar)亿虽,汽車移動
/**
* ICar表示Component:
*/
public interface ICar {
void move();//汽車移動
}
具體真實的對象ConcreteComponent:這里是Car,就是具體的汽車苞也,未裝飾的汽車
//ConcreteComponent:具體的對象
class Car implements ICar{
@Override
public void move() {
System.out.println("汽車移動");
}
}
裝飾抽象類Decorator:SuperCar這里需要持有一個真實對象的引用洛勉,也就是Car對象
//Decorator:裝飾抽象類
class SuperCar implements ICar{
protected ICar car;//持有一個真實對象的引用
@Override
public void move() {
car.move();//這里調(diào)用真實對象的移動方法
}
//構(gòu)造的時候傳參
public SuperCar(ICar car) {
super();
this.car = car;
}
}
實現(xiàn)具體的裝飾對象ConcreteDecorator
//ConcreteDecorator:就是具體的裝飾對象
class FlayCar extends SuperCar {
public FlayCar(ICar car) {
super(car);
}
//這里就是新增的功能
public void flay(){
System.out.println("---天上飛");
}
@Override
public void move() {
super.move();
flay();//在原有移動的基礎(chǔ)上,裝飾了一個fly的功能
}
}
//ConcreteDecorator:就是具體的裝飾對象
class WaterCar extends SuperCar {
public WaterCar(ICar car) {
super(car);
}
//這里就是新增的功能
public void swim(){
System.out.println("---水里游");
}
@Override
public void move() {
super.move();
swim();//在原有移動的基礎(chǔ)上如迟,裝飾了一個swim的功能
}
}
客戶端
public static void main(String[] args) {
Car car = new Car();
car.move();//這里打印未增加新功能的時候:汽車移動
System.out.println("--------增加飛行功能-------");
FlayCar flyCar = new FlayCar(car);//將真實對象傳入裝飾對象中
flyCar.move();//這里就是增加了飛行后的裝飾
System.out.println("--------增加潛水功能-------");
WaterCar waterCar = new WaterCar(car);//將真實對象傳入裝飾對象中
waterCar.move();//這里就是增加了潛水功能后的裝飾
}
打印結(jié)果
汽車移動
--------增加飛行功能-------
汽車移動
---天上飛
--------增加潛水功能-------
汽車移動
---水里游
4.總結(jié)
裝飾模式(Decorator)也叫包裝器模式(Wrapper)
裝飾模式降低系統(tǒng)的耦合度收毫,可以動態(tài)的增加或刪除對象的職責(zé),并使得需要裝飾的具體構(gòu)建類和具體裝飾類可以獨立變化殷勘,以便增加新的具體構(gòu)建類和具體裝飾類此再。
優(yōu)點:
擴(kuò)展功能強(qiáng),相比繼承來說更靈活玲销。繼承的話會導(dǎo)致子類個數(shù)增加输拇。而裝飾者模式不會出現(xiàn)這種情況。
可以對一個對象進(jìn)行多次裝飾贤斜,創(chuàng)造出不同行為的組合策吠,得到功能更加強(qiáng)大的對象。
具體構(gòu)建類和具體裝飾類可以獨立變化瘩绒,用戶可以根據(jù)需要自己增加新的構(gòu)件子類和具體裝飾類猴抹。
缺點:
產(chǎn)生很多小對象,大量小對象會占據(jù)內(nèi)存锁荔。一定程度上影響了性能蟀给。
裝飾模式易于出錯,調(diào)試排查比較麻煩堕战。
應(yīng)用的場景:
IO中輸入流和輸出流
Swing包中圖形界面構(gòu)件功能
Servlet API中提供了一個request對象的Decorator設(shè)計模式的默認(rèn)實現(xiàn)類HttpServletRequestWrapper,增強(qiáng)了request對象的功能坤溃。
Struts2中拍霜,request嘱丢,response,session對象的處理祠饺。
裝飾模式和橋接模式的區(qū)別:
兩個模式都是為了解決過多子類對象的問題越驻,橋接模式是對象自身有過多的維度,造成過多的子類。而讓維度分類后在搭建一個橋梁來聯(lián)系起來缀旁。
而裝飾模式是解決在增加新功能的時候產(chǎn)生多個類的問題记劈。
Android
android中Context和ContextImpl