裝飾者模式目標
把許多要實現的功能,加載在子類上,類的繼承,顯得很臃腫,裝飾着模式是在不改變原有類文件和使用繼承的狀況下,經過建立一個包裝對象動態地擴展一個對象的功能,相比生成子類更爲靈活
裝飾模式的結構
在裝飾模式中的角色有:
● 抽象構件(Component)角色:給出一個抽象接口,以規範準備接收附加責任的對象。
● 具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類。
● 裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。
● 具體裝飾(ConcreteDecorator)角色:負責給構件對象「貼上」附加的責任
源代碼
抽象構件角色
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
public interface Component {設計模式
public void sampleOperation();
}
具體構件角色
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
public class ConcreteComponent implements Component {ide
@Override public void sampleOperation() { // 寫相關的業務代碼 }
}
裝飾角色
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
public class Decorator implements Component{性能
private Component component; public Decorator(Component component){ this.component = component; } @Override public void sampleOperation() { // 委派給構件 component.sampleOperation(); }
}
具體裝飾角色
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public class ConcreteDecoratorA extends Decorator {this
public ConcreteDecoratorA(Component component) { super(component); } @Override public void sampleOperation() {
super.sampleOperation();設計
// 寫相關的業務代碼 }
}
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public class ConcreteDecoratorB extends Decorator {code
public ConcreteDecoratorB(Component component) { super(component); } @Override public void sampleOperation() {
super.sampleOperation();component
// 寫相關的業務代碼 }
}
齊天大聖的例子
孫悟空有七十二般變化,他的每一種變化都給他帶來一種附加的本領。他變成魚兒時,就能夠到水裏游泳;他變成鳥兒時,就能夠在天上飛行。
本例中,Component的角色便由鼎鼎大名的齊天大聖扮演;ConcreteComponent的角色屬於大聖的本尊,就是猢猻本人;Decorator的角色由大聖的七十二變扮演。而ConcreteDecorator的角色即是魚兒、鳥兒等七十二般變化對象
源代碼
抽象構件角色「齊天大聖」接口定義了一個move()方法,這是全部的具體構件類和裝飾類必須實現的。
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
//大聖的尊號
public interface TheGreatestSage {繼承
public void move();
}
具體構件角色「大聖本尊」猢猻類
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
7
public class Monkey implements TheGreatestSage {接口
@Override public void move() { //代碼 System.out.println("Monkey Move"); }
}
抽象裝飾角色「七十二變」
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
public class Change implements TheGreatestSage {
private TheGreatestSage sage; public Change(TheGreatestSage sage){ this.sage = sage; } @Override public void move() { // 代碼 sage.move(); }
}
具體裝飾角色「魚兒」
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public class Fish extends Change {
public Fish(TheGreatestSage sage) { super(sage); } @Override public void move() { // 代碼 System.out.println("Fish Move"); }
}
具體裝飾角色「鳥兒」
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public class Bird extends Change {
public Bird(TheGreatestSage sage) { super(sage); } @Override public void move() { // 代碼 System.out.println("Bird Move"); }
}
客戶端類
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public class Client {
public static void main(String[] args) { TheGreatestSage sage = new Monkey(); // 第一種寫法 TheGreatestSage bird = new Bird(sage); TheGreatestSage fish = new Fish(bird); // 第二種寫法 //TheGreatestSage fish = new Fish(new Bird(sage)); fish.move(); }
}
「大聖本尊」是ConcreteComponent類,而「鳥兒」、「魚兒」是裝飾類。要裝飾的是「大聖本尊」,也即「猢猻」實例。
上面的例子中,系統把大聖從一隻猢猻裝飾成了一隻鳥兒(把鳥兒的功能加到了猢猻身上),而後又把鳥兒裝飾成了一條魚兒(把魚兒的功能加到了猢猻+鳥兒身上,獲得了猢猻+鳥兒+魚兒)。
如上圖所示,大聖的變化首先將鳥兒的功能附加到了猢猻身上,而後又將魚兒的功能附加到猢猻+鳥兒身上。
設計模式在JAVA I/O庫中的應用
裝飾模式在Java語言中的最著名的應用莫過於Java I/O標準庫的設計了。
因爲Java I/O庫須要不少性能的各類組合,若是這些性能都是用繼承的方法實現的,那麼每一種組合都須要一個類,這樣就會形成大量性能重複的類出現。而若是採用裝飾模式,那麼類的數目就會大大減小,性能的重複也能夠減至最少。所以裝飾模式是Java I/O庫的基本模式。
Java I/O庫的對象結構圖以下,因爲Java I/O的對象衆多,所以只畫出InputStream的部分。
根據上圖能夠看出: ● 抽象構件(Component)角色:由InputStream扮演。這是一個抽象類,爲各類子類型提供統一的接口。 ● 具體構件(ConcreteComponent)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream等類扮演。它們實現了抽象構件角色所規定的接口。 ● 抽象裝飾(Decorator)角色:由FilterInputStream扮演。它實現了InputStream所規定的接口。 ● 具體裝飾(ConcreteDecorator)角色:由幾個類扮演,分別是BufferedInputStream、DataInputStream以及兩個不經常使用到的類LineNumberInputStream、PushbackInputStream。