1. 程式人生 > >設計模式之禪(3)-裝飾者模式

設計模式之禪(3)-裝飾者模式

文章目錄


更多關於設計模式的文章請點選設計模式之禪(0)-目錄頁


裝飾者模式是23種設計模式之中的一種常用的設計模式,英文叫Decorator Pattern。裝飾模式是在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。

一、裝飾者模式的特點

1、 裝飾物件和真實物件有相同的介面。這樣客戶端物件就能以和真實物件相同的方式和裝飾物件互動。
2、 裝飾物件包含一個真實物件的引用(reference。
3、 裝飾物件接受所有來自客戶端的請求。它把這些請求轉發給真實的物件。
4、 裝飾物件可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在執行時,不用修改給定物件的結構就可以在外部增加附加的功能。在面向物件的設計中,通常是通過繼承來實現對給定類的功能擴充套件。

二、裝飾者模式的使用情景

1、 需要擴充套件一個類的功能,或給一個類新增附加職責。
2、需要動態的給一個物件新增功能,這些功能可以再動態的撤銷。
3、要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。
4、 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充套件,為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。

三、裝飾者模式的一般關係圖

在這裡插入圖片描述

在這裡插入圖片描述

四、裝飾者模式的程式碼實現

在這裡插入圖片描述

  • Animal超類
/**
 * @Description:    Animal超類
 * @CreateDate: Created in 2018/11/25 11:03
 * @Author: <a href="https://blog.csdn.net/pbrlovejava">arong</a>
 */
public abstract class Animal {
    private String description;

    public abstract String getDescription
(); public void setDescription(String description) { this.description = description; } }
  • Dog子類
/**
 * @Description: Dog extends Animal
 * @CreateDate: Created in 2018/11/25 11:09
 * @Author: <a href="https://blog.csdn.net/pbrlovejava">arong</a>
 */
public class Dog extends Animal {

    @Override
    public String getDescription() {
        setDescription("dog");
        return "dog";
    }
}
  • Bigger -Animal的包裝類
/**
 * @Description: Bigger是一個裝飾者
 * @CreateDate: Created in 2018/11/25 11:12
 * @Author: <a href="https://blog.csdn.net/pbrlovejava">arong</a>
 */
public class Bigger extends Animal{
    private Animal animal;

    public Bigger(Animal animal){
        this.animal = animal;
    }
    @Override
    public String getDescription() {
        return animal.getDescription()+"Bigger";
    }
}
  • 使用Bigger包裝類去包裝Dog子類
/**
 * @Description: 測試裝飾者模式
 * @CreateDate: Created in 2018/11/25 11:21
 * @Author: <a href="https://blog.csdn.net/pbrlovejava">arong</a>
 */
public class TestDecoratorPattern {

    @Test
    public void BiggerDecorateDog(){
        Animal dog = new Dog();
        //使用裝飾者裝飾前
        String wrapBefore = dog.getDescription();
        System.out.println("使用裝飾者裝飾前"+wrapBefore);
        //建立裝飾者Bigger用以包裝Dog
        Animal biggerDog = new Bigger(dog);
        //使用裝飾者裝飾後
        String wrapAfter = biggerDog.getDescription();
        System.out.println("使用裝飾者裝飾後"+wrapAfter);
    }
}

在這裡插入圖片描述

五、裝飾者模式使用的設計原則

1、多組合,少繼承
每一個裝飾者都需要組合一個Animal,這樣才能在包裝時得到原先被裝飾者的屬性和方法等,支援在構造方法中動態地擴充套件。

2、類應設計的對擴充套件開放,對修改關閉。

六、I/O流-典型的裝飾者模式

Java標準庫中的I/O流庫是使用裝飾者模式實現的:
在這裡插入圖片描述
它們的方法和屬性繼承自超類InputStream,所以,它們在使用方面幾乎大同小異,但是會有少許的增強方法。

在這裡插入圖片描述

七、裝飾者模式的弊端

  1. 這種比繼承更加靈活機動的特性,也同時意味著更加多的複雜性。
  2. 裝飾模式會導致設計中出現許多小類,如果過度使用,會使程式變得很複雜。
  3. 裝飾模式是針對抽象元件(Component)型別程式設計。但是,如果你要針對具體元件程式設計時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然也可以改變Component介面,增加新的公開的行為,實現“半透明”的裝飾者模式。在實際專案中要做出最佳選擇。