設計模式-裝飾器模式

微信關注公衆號 JavaStorm 獲取最新內容。java

裝飾器模式(Decorator),動態地給一個對象添加一些額外的職責,就增長功能來講,裝飾器模式比生成子類更爲靈活;它容許向一個現有的對象添加新的功能,同時又不改變其結構。==裝飾器模式屬於結構型模式==。git

UML 類圖

裝飾器模式

  • Component:接口,定義一個抽象接口裝飾對象與真實對象具備相同的接口,以便裝飾器動態的添加職責。
  • ConcreteComponent: 接口的具體對象。
  • Decorator:裝飾類,繼承了 Component , 從外類來拓展 Component 的功能 而且持有一個 Component 的引用,經過構造器實例化,從而實現對真實對象的職責裝飾加強。
  • ConcreteDecorator:具體裝飾類,用於給實際對象添加職責。

使用場景

如今有一個場景:煎餅果子,科技園上班族早上去買煎餅果子(Pancake),有的人要加雞蛋 (Egg)、有的人加火腿 (Ham)、有的人加生菜 (Lettuce)。有的土豪煎餅果子來一套全都要。如今咱們來定義煎餅烹飪實現。(ps:留一個功能讀者本身實現:不一樣的套餐價格是不同的,如何計算出不一樣煎餅果子的價格?有興趣的讀者能夠留言或者微信公衆號後臺留言)。github

代碼實現

代碼能夠左右滑動bash

  1. 先定義煎餅接口也就是咱們的被裝飾類,以及烹飪的方法 。
package com.zero.headfirst.decorator;

public interface Pancake {
    /** * 烹飪方法 */
    void cook();
}
複製代碼
  1. 定義一個乞丐版煎餅,被裝飾對象。
package com.zero.headfirst.decorator;

/** * 被裝飾對象:定義最基本的乞丐版煎餅,啥都沒加 */
public class BeggarPancake implements Pancake {
    @Override
    public void cook() {
        System.out.println("乞丐版基本煎餅");
    }
}
複製代碼
  1. 定義抽象裝飾類 煎餅果子裝飾器 PancakeDecorator:抽象裝飾器角色,實現煎餅接口(被裝飾器接口),持有被裝飾器的引用 (pancake)將烹飪行爲轉發具體的裝飾器。
package com.zero.headfirst.decorator;

/** * 抽象裝飾器角色,實現煎餅接口(被裝飾器接口),持有被裝飾器的引用將烹飪行爲轉發具體的裝飾器。 */
public abstract class PancakeDecorator implements Pancake {

    private Pancake pancake;

    public PancakeDecorator(Pancake pancake) {
        this.pancake = pancake;
    }

    @Override
    public void cook() {
        if (pancake != null) {
            pancake.cook();
        }
    }
}
複製代碼
  1. 各類具體裝飾類對乞丐版煎餅進行不等級別的土豪加工。首先繼承 抽象出來的 PancakeDecorator ,重寫 cook 方法,實現加工。

EggDecorator 雞蛋裝飾器:繼承 PancakeDecorator,重寫 cook 方法。動態添加雞蛋,而後調用pancake 的cook。微信

package com.zero.headfirst.decorator;

/** * 雞蛋裝飾器:覆蓋cook方法,加入自身的實現,而且調用父類的cook方法,也就是構造函數中 * EggDecorator(Pancake pancake),這裏傳入的pancake的cook操做 */
public class EggDecorator extends PancakeDecorator {
    public EggDecorator(Pancake pancake) {
        super(pancake);
    }

    @Override
    public void cook() {
        System.out.println("加一個雞蛋;");
        super.cook();
    }
}

複製代碼

火腿裝飾器: HamDecoratoride

package com.zero.headfirst.decorator;

/** * 火腿裝飾器 */
public class HamDecorator extends PancakeDecorator {

    public HamDecorator(Pancake pancake) {
        super(pancake);
    }

    @Override
    public void cook() {
        System.out.println("加一個火腿;");
        super.cook();
    }

}

複製代碼

生菜裝飾器函數

package com.zero.headfirst.decorator;

/** * 生菜裝飾器 */
public class LettuceDecorator extends PancakeDecorator {

    public LettuceDecorator(Pancake pancake) {
        super(pancake);
    }

    @Override
    public void cook() {
        System.out.println("加生菜;");
        super.cook();
    }

}

複製代碼
  1. 定義一個煎餅果子攤位。
package com.zero.headfirst.decorator;

/** * 煎餅果子店 */
public class PancakeShop {
    public static void main(String[] args) {
        System.out.println("========土豪來了,全都加上。======");
        BeggarPancake beggarPancake = new BeggarPancake();
        EggDecorator eggDecorator = new EggDecorator(beggarPancake);
        HamDecorator hamAndEggDecorator = new HamDecorator(eggDecorator);
        LettuceDecorator lettuceAndHamAndEggDecorator = new LettuceDecorator(hamAndEggDecorator);
        lettuceAndHamAndEggDecorator.cook();

        System.out.println("========苦逼碼農來了,只要雞蛋補補腦。=====");
        BeggarPancake beggarPancake1 = new BeggarPancake();
        EggDecorator eggDecorator1 = new EggDecorator(beggarPancake1);
        eggDecorator1.cook();
    }
}

複製代碼
  1. 運行結果
========土豪來了,全都加上。======

加生菜;

加一個火腿;

加一個雞蛋;

乞丐版基本煎餅

========苦逼碼農來了,只要雞蛋補補腦。=====

加一個雞蛋;

乞丐版基本煎餅
複製代碼

總結

真實世界的裝飾: Java I/O。 注意事項與要點this

  • 抽象裝飾器與具體被裝飾對象實現同一個接口。
  • 抽象裝飾器持有被裝飾器接口對象,以便請求傳遞。
  • 具體裝飾器須要重寫抽象裝飾器的方法並引用super進行條用,轉發請求。

適用場景

  • 拓展一個類的功能。spa

  • 動態的添加與撤銷職責。code

優勢

  • 裝飾類與被裝飾類只關心本身的核心邏輯,實現瞭解耦。
  • 方便動態拓展,開閉原則。且比繼承靈活。

缺點

  • 若是功能拓展太多,將產生大量的類。
  • 多層裝飾會變得複雜。

以上代碼可參考個人 GitHub : github.com/UniqueDong/… JavaStorm 獲取最新文章,也可在後臺留言提出意見。收藏與關注是最大的鼓勵。

JavaStorm
相關文章
相關標籤/搜索