1. 程式人生 > >裝飾者模式(Decorator Pattern)——給愛用繼承的人一個全新的設計眼界

裝飾者模式(Decorator Pattern)——給愛用繼承的人一個全新的設計眼界

概述

裝飾者模式(Decorator Pattern),別名(Warpper)。 動態的將責任附加到物件上。若要擴充套件功能,裝飾者提供比繼承更有彈性的替代方案。

裝飾者模式從屬的大類是結構型模式(該大類下的設計模式關注類和物件的組合。繼承的概念被用來組合介面和定義組合物件獲得新功能的方式)。

涉及的設計原則:

1. 開放–關閉原則類(應該對擴充套件開放,對修改關閉)

2. 多用組合,少用繼承

類圖

這裡寫圖片描述

需要注意的東西

由上面類圖可知,裝飾者模式,由Component(抽象元件)、ConcreteComponent(具體元件)、Decorator(抽象裝飾類)、ConcreteDecorator(具體裝飾類)組成。其主要功能從上面類圖可以看出。在此需要注意幾點:

  1. 上述中Components和Decorator均可以是介面也可以是抽象類。
  2. 裝飾者和被裝飾者需要實現相同的介面或者抽象類。即裝飾者和被裝飾者物件擁有相同的超類。
  3. 可以用一個或多個裝飾者包裝一個物件。
  4. 裝飾者模式的用意是包吃介面並增加物件的職責。
  5. 一張圖看懂裝飾者模式流程。

這裡寫圖片描述

應用場景

星巴克咖啡對其出售的咖啡的一種銷售策略的價格做一下統計、這樣當顧客點了他們想要的搭配的時候我們就可以知道最後的價格是多少。

假設有四種咖啡:HouseBlend、DarkRoaat、Decaf、Espresso。

同樣有四種配料可以選擇:Milk、Mocha、Soy、Mocha。

這四種咖啡有不同的價格、同樣四種搭配也有不同的價格。當我們把這個單子拿給顧客的時候、顧客可以任意點一種咖啡、可以任意搭配。我們的目的是要統計每種搭配的價格、那我們要怎麼來實現呢?當我們要新增一個或多個新的品種或者配料的時候,又如何有效的解決這個問題呢?這就是裝飾者模式的解決的問題。

程式碼實現

這裡為了簡化程式碼,只採用兩種咖啡HouseBlend、Espresso,兩種配料Mocha、Mocha,這樣的搭配。

package decorator;

/**
 * <p>ClassName      Beverage
 * <p>Description    超類
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 0:51
 */
public abstract class Beverage {
    String description = "unknow Beverage"
; public String getDescription() { return description; } /** * 計算花費 * * @return */ public abstract Double cost(); }
package decorator;

/**
 * <p>ClassName      CondimentDecorator
 * <p>Description   配料抽象類
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 0:55
 */
public abstract class CondimentDecorator extends Beverage {
    /**
     * 所有的配料裝飾者都需要重寫getDescription
     */
    public abstract String getDescription();
}
package decorator;

/**
 * <p>ClassName      Espresso
 * <p>Description    一種飲品(具體的元件)
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:01
 */
public class Espresso extends Beverage {
    public Espresso() {
        description = "Espresso";
    }

    public Double cost() {
        return 1.99;
    }
}
package decorator;

/**
 * <p>ClassName      HouseBlend
 * <p>Description    另外一種飲品(具體的元件)
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:04
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "HouseBlend";
    }

    public Double cost() {
        return 0.89;
    }
}
package decorator;

/**
 * <p>ClassName      Mocha
 * <p>Description    具體裝飾者
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:05
 */
public class Mocha extends CondimentDecorator {
    Beverage beverage; //被裝飾者

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ",Mocha";
    }

    public Double cost() {
        return 0.2 + beverage.cost();
    }
}
package decorator;

/**
 * <p>ClassName      Whip
 * <p>Description    具體裝飾者
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:12
 */
public class Whip extends CondimentDecorator {
    Beverage beverage; //被裝飾者

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ",Whip";
    }

    public Double cost() {
        return 66.66 + beverage.cost();
    }
}
package decorator;

/**
 * <p>ClassName      TestDecorator
 * <p>Description    測試類
 * <p>Author         ChongLou
 * <p>Version
 * <p>Date           2017/7/24 1:09
 */
public class TestDecorator {
    public static void main(String[] args) {
        /**
         * 一杯Espresso,不加配料
         */
        Beverage beverage = new Espresso();
        System.out.println( beverage.getDescription() + " $" + beverage.cost() );

        /**
         * 一杯Houseblend,加Mocha,Whip
         */
        Beverage beverage1 = new HouseBlend();
        beverage1 = new Mocha( beverage1 );
        beverage1 = new Whip( beverage1 );
        System.out.println( beverage1.getDescription() + " $" + beverage1.cost() );
    }
}

執行結果

這裡寫圖片描述

總結

又get一種新的pattern。

裝飾者模式比繼承更加靈活機動,但是不要忘記了裝飾者模式的別名warpper,如果過度使用,多層warpper,會使程式變得很複雜。

相關推薦

裝飾模式(Decorator Pattern)——繼承的人一個全新設計眼界

概述 裝飾者模式(Decorator Pattern),別名(Warpper)。 動態的將責任附加到物件上。若要擴充套件功能,裝飾者提供比繼承更有彈性的替代方案。 裝飾者模式從屬的大類是結構型模式

08 裝飾模式(Decorator Pattern)

描述性文字 還記得工廠方法模式中示例程式碼中的奶茶店嗎?在那一節中講解的是通過工廠方法模式來做奶茶,做奶茶的工作都已經交給小弟了, 小豬的工作量少了很多。於是,寫出所有飲品的價格: 奶茶: 原味奶茶:5塊 珍珠奶茶:7塊 椰果奶茶:7塊 珍珠椰果奶茶:9

Android設計模式之一個例子讓你徹底明白裝飾模式(Decorator Pattern)

導讀 這篇文章中我不會使用概念性文字來說明裝飾者模式,因為通常概念性的問題都很抽象,很難懂,使得讀者很難明白到底為什麼要使用這種設計模式,我們設計模式的誕生,肯定是前輩們在設計程式的時候遇到了某種困難,為了避免這種苦難的發生,從而設計出來的這種設計模式,所以這

設計模式(三):“花瓶+鮮花”中的裝飾模式(Decorator Pattern)

在前兩篇部落格中詳細的介紹了"策略模式"和“觀察者模式”,今天我們就通過花瓶與鮮花的例子來類比一下“裝飾模式”(Decorator Pattern)。在“裝飾模式”中很好的提現了開放關閉原則,即類應該對擴充套件開放對修改關閉。裝飾者模式可以讓我們在不對原來程式碼的修改的情況下對類進行擴充套件。這也好比我們往花

Android設計模式裝飾模式(Decorator Pattern)

概論 在Android原始碼裡很多時候會看到這個模式。下面來講一些這個模式。 裝飾者模式主要的優點是動態給一個物件新增一些額外的職責。使用Decorator模式相比用生成子類方式達到功能的擴充顯得更為靈活。缺點是,要建立比繼承更多的物件。 先來個熱身,

設計模式(結構型)之裝飾模式(Decorator Pattern)

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 概述 裝飾模式可以在不改變一個物件本身功能的基礎上給物件增加額外的新行為。裝飾模式是一種用於替代繼承的技術,它通過一

設計模式學習筆記--裝飾模式(Decorator Pattern)

概念 動態地將行為附加到物件上。提供了比繼承更具有彈性的替代方案 所謂”動態”,是指在執行時根據具體的需求新增行為,相對的,”靜態”則是在編譯時就確定了具體的行為,兩者的區別很明顯,動態新增行為具有很好的可擴充套件性,不需要修改已有的程式碼,這對於維護更新是

c++設計模式裝飾模式(Decorator Pattern)

定義: 裝飾者模式動態的將責任附加到物件上。若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。 場景: 我們購買咖啡的時候,可以要求在其中加入各種調料,例如:蒸奶、豆漿、摩卡或覆蓋奶泡,而咖啡店也會根據所加入的調料收取不同的費用,所以當我們設計訂單系統的時候就

設計模式裝飾模式(decorator pattern)

名稱:裝飾者模式 說說:哥哥吞併了弟弟後,獲得了弟弟的能力,本是同根生... 動機: 適用性:如功能擴充套件 參與者: 結果:動態地將責任附加到物件上,實現新的擴充套件 類圖: 說明:實際上是在執行時實現了繼承的功能(繼承兄弟而非父親,或者說吞併兄弟的屬性),繼承本身是在

裝飾模式decorator)--繼承的人一個全新設計眼界

[color=red][b]裝飾者模式:動態的將責任附加到物件上,若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。 設計原則:對擴充套件開放,對修改關閉。 [/b][/color]jdk中io採用了這種設計模式,來看一下io的類圖先。 [img]http://dl.i

設計模式(三)裝飾模式Decorator

不知道 operation 總結 界面 都是 per @override stat override   裝飾者模式針對的問題是:對一個結構已經確定的類,在不改變該類的結構的情況下,動態增加一些功能。   一般來說,都是對一些已經寫好的架構增加自己的功能,或者應對多種情況,

設計模式-裝飾模式(Decorator)

概述 定義 : 在不改變原有物件的基礎之上, 將功能附加到物件上 提供了比繼承更有彈性的替代方案(擴充套件原有物件功能) 又叫包裝器Wrapper, 介面卡模式也被稱之為包裝器 型別 : 結構型 適用場景 擴充套件一個類的功能或給一個類

裝飾模式--Decorator

1: 作用 動態的給物件增加執行的業務,不受數量限制。可以代替子類,同時避免子類與父類的高耦合。增加靈活性。 2:構成 2.1 裝飾者抽象類--Decorator (可以是介面) 最終生成一個指向被裝飾物件基類(Component)例項的引用,並定義一個與被裝飾物件基

JavaEE之裝飾模式-Decorator

裝飾者模式-Decorator        裝飾者模式:當開發者覺得某些類的某些方法不滿足需要,向增強這些類的方法。這是就可以使用裝飾者模式去裝飾這些類。不滿足需求的這些類,叫被裝飾類。開發者需要重新編寫裝飾類去覆蓋被裝飾類。                  Buffer

裝飾模式 Decorator

專案:咖啡計費系統 背景:現有系統中有一個抽象類Beverage,有2個抽象方法GetDescription和Cost。 1 namespace DecoratorPattern 2 { 3 /// <summary> 4 /// 飲料抽象類 5 ///

7,裝飾模式Decorator Pattern)動態的一個對象添加一些額外的職責。就增加功能來說,此模式比生成子類更為靈活。繼承關系的一個替換方案。

做到 活性 splay .com 重新 裝飾 run play 情況 裝飾( Decorator )模式又叫做包裝模式。通過一種對客戶端透明的方式來擴展對象的功能,是繼承關系的一個替換方案。 裝飾模式就是把要添加的附加功能分別放在單獨的類中,並讓這個

繼承的人一個全新設計眼界-----裝飾模式(java I/O的原始碼思想就是基於這個來的)

導讀:如果感覺有點困難,請看後面的例子和最後一句話 開始的思維: 這是一個父類,假設是某種產品的總稱,比如:飲料(beverage): public class Beverage { private String description;//產品的描述 pu

C#設計模式(9)——裝飾模式Decorator Pattern

pre 現在 接受 () spa 對象 如何 缺點 重寫 一、引言 在軟件開發中,我們經常想要對一類對象添加不同的功能,例如要給手機添加貼膜,手機掛件,手機外殼等,如果此時利用繼承來實現的話,就需要定義無數的類,如StickerPhone(貼膜是手機類)、Accessori

設計模式之(三)——裝飾模式Decorator Pattern

    裝飾者模式:動態將責任附加到物件上,要拓展功能,提供了比繼承更有彈性的方案。 很多文章也是拿了書上的例子來講,同時寫到,有的調料裝飾者都必須實現 getDescription() 大家可以先考慮下,稍後我們會說。最後都是沒說,還有思考的

設計模式Decorator Pattern)——裝飾模式

一、裝飾者模式簡介在HeadFirst 介紹裝飾者模式的導論中,這麼介紹裝飾者模式給愛用繼承的人一個全新的設計眼界那麼更通俗講,什麼是裝飾者模式呢?裝飾者,包裝原有的物件,使之變成具有包裝著功能的新事物。舉個栗子,你去一家麵館吃麵,這是一家專門做麵食的餐館,有面條,湯料,獅子