Java裝飾者模式
阿新 • • 發佈:2021-06-28
裝飾者模式目標
把許多要實現的功能,載入在子類上,類的繼承,顯得很臃腫,裝飾著模式是在不改變原有類檔案和使用繼承的情況下,通過建立一個包裝物件動態地擴充套件一個物件的功能,相比生成子類更為靈活
[Java] 純文字檢視 複製程式碼
?
“大聖本尊”是ConcreteComponent類,而“鳥兒”、“魚兒”是裝飾類。要裝飾的是“大聖本尊”,也即“猢猻”例項。
上面的例子中,系統把大聖從一隻猢猻裝飾成了一隻鳥兒(把鳥兒的功能加到了猢猻身上),然後又把鳥兒裝飾成了一條魚兒(把魚兒的功能加到了猢猻+鳥兒身上,得到了猢猻+鳥兒+魚兒)。
如上圖所示,大聖的變化首先將鳥兒的功能附加到了猢猻身上,然後又將魚兒的功能附加到猢猻+鳥兒身上。
裝飾模式的結構<ignore_js_op>
在裝飾模式中的角色有: ● 抽象構件(Component)角色:給出一個抽象介面,以規範準備接收附加責任的物件。 ● 具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類。 ● 裝飾(Decorator)角色:持有一個構件(Component)物件的例項,並定義一個與抽象構件介面一致的介面。 ● 具體裝飾(ConcreteDecorator)角色:負責給構件物件“貼上”附加的責任 原始碼
抽象構件角色
1 2 3 4 5 |
public interface Component {
public void sampleOperation();
}
|
具體構件角色
1 2 3 4 5 6 7 8 |
public class ConcreteComponent implements Component {
@Override
public void sampleOperation() { // 寫相關的業務程式碼
}
}
|
裝飾角色
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();
}
}
|
具體裝飾角色
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();
// 寫相關的業務程式碼
}
}
|
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();
// 寫相關的業務程式碼
}
}
|
齊天大聖的例子
原始碼
抽象構件角色“齊天大聖”介面定義了一個move()方法,這是所有的具體構件類和裝飾類必須實現的。
1 2 3 4 5 |
//大聖的尊號
public interface TheGreatestSage {
public void move();
}
|
具體構件角色“大聖本尊”猢猻類
1 2 3 4 5 6 7 8 9 |
public class Monkey implements TheGreatestSage {
@Override
public void move() {
//程式碼
System.out.println( "Monkey Move" );
}
}
|
抽象裝飾角色“七十二變”
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 ( ) ;
}
}
|
具體裝飾角色“魚兒”
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" );
}
}
|
具體裝飾角色“鳥兒”
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" );
}
}
|
客戶端類
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();
}
}
|
設計模式在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。