裝飾者模式目標設計模式
把許多要實現的功能,加載在子類上,類的繼承,顯得很臃腫,裝飾着模式是在不改變原有類文件和使用繼承的狀況下,經過建立一個包裝對象動態地擴展一個對象的功能,相比生成子類更爲靈活ide
裝飾模式的結構性能
在裝飾模式中的角色有:this
● 抽象構件(Component)角色:給出一個抽象接口,以規範準備接收附加責任的對象。spa
● 具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類。設計
● 裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。3d
● 具體裝飾(ConcreteDecorator)角色:負責給構件對象「貼上」附加的責任code
源代碼
抽象構件角色 component
[Java]純文本查看__複製代碼對象
1
2
3
4
5
public
interface
Component {
public
void
sampleOperation();
}
具體構件角色
[Java]純文本查看__複製代碼
1
2
3
4
5
6
7
8
public
class
ConcreteComponent
implements
Component {
@Override
public
void
sampleOperation() {
// 寫相關的業務代碼
}
}
裝飾角色
[Java]純文本查看__複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
13
14
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
12
public
class
ConcreteDecoratorA
extends
Decorator {
public
ConcreteDecoratorA(Component component) {
super
`(component);`
}
@Override
public
void
sampleOperation() {
super
`.sampleOperation();`
// 寫相關的業務代碼
}
}
[Java]純文本查看__複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
public
class
ConcreteDecoratorB
extends
Decorator {
public
ConcreteDecoratorB(Component component) {
super
`(component);`
}
@Override
public
void
sampleOperation() {
super
`.sampleOperation();`
// 寫相關的業務代碼
}
}
齊天大聖的例子
孫悟空有七十二般變化,他的每一種變化都給他帶來一種附加的本領。他變成魚兒時,就能夠到水裏游泳;他變成鳥兒時,就能夠在天上飛行。
本例中,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
8
9
public
class
Monkey
implements
TheGreatestSage {
@Override
public
void
move() {
//代碼
System.out.println(
`"Monkey Move"`);
}
}
抽象裝飾角色「七十二變」
[AppleScript]純文本查看__複製代碼
01
02
03
04
05
06
07
08
09
10
11
12
13
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
12
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
12
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
12
13
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。