java裝飾者模式

裝飾者模式目標設計模式

把許多要實現的功能,加載在子類上,類的繼承,顯得很臃腫,裝飾着模式是在不改變原有類文件和使用繼承的狀況下,經過建立一個包裝對象動態地擴展一個對象的功能,相比生成子類更爲靈活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。

相關文章
相關標籤/搜索