裝飾者模式就是這麼簡單

定義

一、裝飾模式又稱爲包裝模式,是結構型設計模式的一種。
二、裝飾者模式的理念是在對客戶端透明的方式下動態的給對象附加一些額外的功能,使得對象的功能更加完善。
三、裝飾模式區別於繼承,是繼承關係的替代。裝飾模式將客戶端的調用委派給被裝飾類。java

UML結構

上圖中存在四個角色

  • 抽象構件角色(Component):一般是一個接口或者抽象類,定義須要裝飾的方法,通常是該角色的主要功能。
  • 具體構件角色(ConcretComponent):抽象構件角色的具體實現,也就是咱們要裝飾的具體對象。
  • 抽象裝飾角色(Decorator):持有組件(Component)的實例引用,該類的職責是爲了裝飾具體組件對象,能夠在須要裝飾的方法的開始或者結束加上一些額外的功能。
  • 具體裝飾角色(ConcreteDecorator):抽象裝飾角色的不一樣實現,表示加強裝飾方法,加上不一樣的功能。

實戰

案例

在咱們生活的周邊,會有不少的便利店,這些便利店主要功能就是賣東西,可能剛開始只是賣零食和飲料這些食品,後來便利店規模擴大了,開始賣一些紙巾,洗髮水等一些生活用品。不只如此,店鋪的業務也在擴展,不只賣東西,還能夠寄存相似中通,韻達的快遞。用裝飾者模式怎麼表示呢?設計模式

建立抽象構件角色

按照UML模型,咱們須要建立一個抽象構件接口或抽象類bash

/**
 * 抽象構建角色:定義一個功能方法
 */
public interface Component {

    void function();
}
複製代碼

建立具體構件角色

而後咱們建立咱們的構件角色,就是便利店,便利店的基本功能就是買零食和飲料這些食品。ide

/**
 * 具體構件角色,此處是一個店鋪
 */
public class ShopComponent implements Component{

    /**
     * 實現function()方法,店鋪的主要功能就是買東西,此處假設這家店鋪是家便利店,
     * 賣的東西都是零食飲料之類的
     */
    @Override
    public void function() {
        System.out.println("基本功能:賣零食和飲料");
    }
}
複製代碼

建立裝飾者

這裏咱們建立了咱們建立了裝飾者的基類,它不必定是抽象類或者接口。它持有一個構件角色Component的對象引用,而後實現其基本方法。而後在它的子類中對基本方法進行裝飾。測試

/**
 * 抽象裝飾角色
 */
public class ShopDecorator implements Component{

    //持有一個Component類型的對象引用
    private Component component;

    ShopDecorator(Component component) {
        this.component = component;
    }

    @Override
    public void function() {
        //客戶端的調用委派給具體的子類
       component.function();
    }
}
複製代碼

建立具體裝飾者

首先,咱們建立了一個裝飾者,裝飾基本方法function(),表示便利店規模擴大了,開始賣一些生活用品this

/**
 * 具體裝飾角色,繼承抽象裝飾角色
 */
public class ShopSizeDecorator extends ShopDecorator {

    ShopSizeDecorator(Component component) {
        super(component);
    }

    /**
     * 在基本功能以後進行擴展
     */
    @Override
    public void function() {
        super.function();
        System.out.print("店鋪規模擴大了:");
        sellLifeThings();
    }

    private void sellLifeThings() {
        System.out.println("開始賣一些生活用品");
    }
}
複製代碼

而後,又建立了一個裝飾者,仍是裝飾基本方法function(),表示便利店業務範圍擴大了,能夠寄存快遞了。加密

/**
 * 具體裝飾角色,繼承抽象裝飾角色
 */
public class ShopBusinessDecorator extends ShopDecorator{

    ShopBusinessDecorator(Component component) {
        super(component);
    }

    /**
     * 在基本功能以後進行擴展
     */
    @Override
    public void function() {
        super.function();
        System.out.print("店鋪業務範圍擴大了:");
        acceptShipping();
    }

    private void acceptShipping() {
        System.out.println("能夠寄存快遞了");
    }
}
複製代碼

測試類

注意雙層裝飾的地方,是否是很熟悉呢?(java的IO流是否是很像)spa

public class ShopDecoratorTest {

    public static void main(String [] args) {
        //裝飾前,店鋪的基本功能就是賣一些零食和飲料
        Component component = new ShopComponent();
        System.out.println("裝飾前:");
        component.function();

        //第一層裝飾,店鋪的規模擴大了,開始賣一些生活用品
        Component component1 = new ShopSizeDecorator(component);
        System.out.println("第一層裝飾:");
        component1.function();

        //雙層裝飾,店鋪的業務範圍也擴大了,有了寄存快遞的業務
        Component component2 = new ShopBusinessDecorator(new ShopSizeDecorator(component));
        System.out.println("雙層裝飾:");
        component2.function();
    }
}
複製代碼

運行結果:設計

理理java IO的裝飾者

public static void main(String [] args) throws Exception{
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("path")));

        Base64InputStream base64InputStream = new Base64InputStream(bufferedInputStream);
    }
複製代碼

第一層裝飾,加了緩衝區功能,第二層裝飾,進行了簡單的加密處理。爲啥能裝飾呢?關鍵是BufferedInputStream(具體裝飾者)的父類FilterInputStream(裝飾者)中持有InputStream(抽象構件角色)的對象引用,並且實現了InputStream中基本功能,那麼在BufferedInputStream中我也實現相同的功能,想加點什麼功能就能夠加點什麼功能,簡單吧!code

相關文章
相關標籤/搜索