1. 程式人生 > >結構型模式————裝飾器模式(3.1)

結構型模式————裝飾器模式(3.1)

什麼是裝飾器模式?


【先吃三顆栗子:】


1.PC=主機+顯示器+鍵盤+滑鼠+滑鼠墊

主機是核心,而其他的組成部分都是裝飾。


2.手抓餅=餅+雞蛋+培根+黃瓜

餅是核心,雞蛋,培根是可選的,可以理解為裝飾。


3.咖啡=咖啡+牛奶+冰+方糖

咖啡是核心,牛奶等可選。


比喻雖然形象生動,但是與實際或多或少會產生偏差。


抽象的解釋:裝飾器模式的目的——核心部分和裝飾部分可以自由組合。

裝飾器模式的功能

對於軟體開發來說,聚焦於軟體的靈活性和可擴充套件性。

裝飾器模式要求:

  • 裝飾可選
  • 裝飾可擴充套件
  • 核心部分可擴充套件

手抓餅中的裝飾器模式

實現餅加各種配料的價格計算。

思路:

1.定義抽象類手抓餅,其中包含獲取種類的抽象方法和獲取價格的抽象方法。

2.然後定義兩個分別為大份手抓餅和中份手抓餅來繼承這個抽象類,重寫兩個方法定義種類和價格。

3.定義具體的配料類繼承手抓餅抽象類,先定義構造器傳入已經建立的手抓餅種類,然後重寫種類和價格方法。


在網上看的一些部落格,是創建出一個抽象的配料類來繼承抽象產品類,然後用具體的配料類來實現抽象配料類,實現裝飾。

可是如果直接將抽象產品類的方法全部定義抽象方法,配料類直接繼承重寫,實現裝飾,功能上也是可以實現的,如下所示,Bacon類直接繼承HandPancake,然後重寫getName和getCost方法,實現裝飾。似乎也沒有問題:

但是設計模式畢竟是一種經驗總結,如果有已經看出端倪的小夥伴們在下方留言交流一下吧!

直接繼承HandPancake:

abstract class HandPancake
{
    public abstract String getName();

    public abstract int getCost();
}

class HandPancake_Big extends HandPancake
{
    @Override
    public String getName() {
        return "大份手抓餅";
    }

    @Override
    public int getCost() {
        return 10;
    }
}

class HandPancake_Mid extends HandPancake
{
    @Override
    public String getName() {
        return "中份手抓餅";
    }

    @Override
    public int getCost() {
        return 8;
    }
}
class Bacon extends HandPancake
{
    private HandPancake handPancake;

    Bacon(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加培根";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}
class Cucumber extends HandPancake
{
    private HandPancake handPancake;

    Cucumber(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加黃瓜";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+2;
    }
}
class Ham extends HandPancake
{
    private HandPancake handPancake;

    Ham(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加火腿";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}


public class APPlication
{
    public static void main(String[] args) {
        HandPancake handPancake_big = new HandPancake_Big();

        System.out.println("啥也不加"+handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Ham(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Cucumber(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Bacon(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        System.out.println("==============================");
        HandPancake handPancake_mid = new HandPancake_Mid();
        System.out.println("啥也不加"+handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Ham(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Cucumber(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Bacon(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());


    }
}

官方做法:

abstract class HandPancake
{
    String name;                      //1
    public  String getName()
    {
        return name;
    }

    public abstract int getCost();
}

class HandPancake_Big extends HandPancake
{
    HandPancake_Big()         //2.通過構造器賦值
    {
        name="大份手抓餅";
    }


    @Override
    public int getCost() {
        return 10;
    }
}

class HandPancake_Mid extends HandPancake
{
    HandPancake_Mid()         //2.通過構造器賦值
    {
        name="中份手抓餅";
    }


    @Override
    public int getCost() {
        return 8;
    }
}

abstract class Condiments  extends HandPancake   //3.定義抽象介面
{
    public abstract String getName();
}

class Bacon extends Condiments     //4.繼承抽象介面
{
    private HandPancake handPancake;

    Bacon(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加培根";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}
class Cucumber extends Condiments
{
    private HandPancake handPancake;

    Cucumber(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加黃瓜";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+2;
    }
}
class Ham extends Condiments
{
    private HandPancake handPancake;

    Ham(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加火腿";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}


public class APPlication
{
    public static void main(String[] args) {
        HandPancake handPancake_big = new HandPancake_Big();

        System.out.println("啥也不加"+handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Ham(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Cucumber(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Bacon(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        System.out.println("==============================");
        HandPancake handPancake_mid = new HandPancake_Mid();
        System.out.println("啥也不加"+handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Ham(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Cucumber(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Bacon(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());


    }
}

手抓餅的擴充套件性

  • 建立手抓餅的種類
  • 建立配料種類

官方的擴充套件:建立一個小份手抓餅繼承Hanpancake,然後建立配料繼承Condiments。

貼一下直接繼承HandPancake的情況:

class HandPancake_Smalll extends HandPancake
class Egg extends HandPancake

abstract class HandPancake
{
    public abstract String getName();

    public abstract int getCost();
}

class HandPancake_Big extends HandPancake
{
    @Override
    public String getName() {
        return "大份手抓餅";
    }

    @Override
    public int getCost() {
        return 10;
    }
}

class HandPancake_Mid extends HandPancake
{
    @Override
    public String getName() {
        return "中份手抓餅";
    }

    @Override
    public int getCost() {
        return 8;
    }
}
class Bacon extends HandPancake
{
    private HandPancake handPancake;

    Bacon(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加培根";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}
class Cucumber extends HandPancake
{
    private HandPancake handPancake;

    Cucumber(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加黃瓜";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+2;
    }
}
class Ham extends HandPancake
{
    private HandPancake handPancake;

    Ham(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加火腿";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}
//========================

class HandPancake_Smalll extends HandPancake
{
    @Override
    public String getName() {
        return "小份手抓餅";
    }

    @Override
    public int getCost() {
        return 5;
    }
}


class Egg extends HandPancake
{
    private HandPancake handPancake;

    Egg(HandPancake handPancake)
    {
        this.handPancake=handPancake;
    }

    @Override
    public String getName() {
        return handPancake.getName()+"加雞蛋";
    }

    @Override
    public int getCost() {
        return handPancake.getCost()+1;
    }
}


public class APPlication
{
    public static void main(String[] args) {
        HandPancake handPancake_big = new HandPancake_Big();

        System.out.println("啥也不加"+handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Ham(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Cucumber(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        handPancake_big = new Bacon(handPancake_big);

        System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost());

        System.out.println("==============================");
        HandPancake handPancake_mid = new HandPancake_Mid();
        System.out.println("啥也不加"+handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Ham(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Cucumber(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());

        handPancake_mid = new Bacon(handPancake_mid);

        System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost());


        System.out.println("擴充套件性測試:");

        HandPancake handPancake_small = new HandPancake_Smalll();
        System.out.println("啥也不加"+handPancake_small.getName()+":"+handPancake_small.getCost());

        handPancake_small = new Egg(handPancake_small);

        System.out.println(handPancake_small.getName()+":"+handPancake_small.getCost());






    }
}

執行結果:

相關推薦

結構模式————裝飾模式3.1

什麼是裝飾器模式? 【先吃三顆栗子:】 1.PC=主機+顯示器+鍵盤+滑鼠+滑鼠墊 主機是核心,而其他的組成部分都是裝飾。 2.手抓餅=餅+雞蛋+培根+黃瓜 餅是核心,雞蛋,培根是可選的,可以理解為裝飾。 3.咖啡=咖啡+牛奶+冰+方糖 咖啡是核心,牛奶等可選。 比喻雖然形象生動,但是與實際或多或少

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

trac 價格 div desc number one 添加 imp esc 裝飾器模式(Decorator Pattern) 概念 裝飾器模式 允許向一個現有的對象添加新的功能,同時又不改變其結構。裝飾者可以在所委托被裝飾者的行為之前或之後加上自己的行為,以達到特定

重走Java設計模式——裝飾模式Decorator Pattern

裝飾器模式 定義 裝飾器模式(Decorator Pattern)允許向一個現有的物件新增新的功能,同時又不改變其結構。這種型別的設計模式屬於結構型模式,它是作為現有的類的一個包裝。 這種模式建立了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外

結構裝飾模式及相關應用

文章目錄 裝飾者(Decorator) 優缺點 應用場景 Java I/O中的應用 Spring中的應用 MyBatis中的應用 參考資料 裝飾者(Decorator) 在不

Scala設計模式UML圖例和程式碼實現實戰 結構模式--裝飾模式

Scala設計模式UML圖例和程式碼實現實戰 結構模式中的 裝飾器設計模式 在某些情況下,我們可能希望為應用程式中的類新增一些額外的功能。這可以通過繼承來完成;但是,我們可能不想這樣做,或者它可能會影響我們應用程式中的所有其他類。這是裝飾器設計模式有用的地

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

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

【一起學設計模式】狀態模式+裝飾模式+簡單工廠模式實戰:提交個訂單我到底經歷了什麼鬼?

前言 之前在我的部落格(一枝花算不算浪漫)中已經更新過兩篇設計模式相關的內容 【一起學設計模式】策略模式實戰一:基於訊息傳送的策略模式實戰 【一起學習設計模式】策略模式實戰二:配合註解 幹掉業務程式碼中冗餘的if else... 【一起學設計模式】訪問者模式實戰:許可權管理樹刪節點操作 【一起學設計模式】命

C#設計模式-裝飾模式Decorator Pattern

引言 當我們完成一個軟體產品開發後就需要對其進行各種測試,適配快速迭代下質量的保障。當有一個完善的產品的物件後,如果我們想要給他新增一個測試功能,那麼我們可以用一個新的類去裝飾它來實現對原有物件職責的擴充套件。新的類稱為“裝飾者”,原有的物件稱為“被裝飾者”。這

適配器模式/代理模式/裝飾模式/工廠模式

取數 取數據 cat remote struct catch span 擁有 rto 適配器模式 要對原有的類的功能進行擴展,但又不希望改變原有類的功能,來適應新的需求,這時候可以從原有類繼承,實現一個適配器,這不會改變原有類的功能,又可以添加新的功能. 1.類適配器 c

設計模式裝飾模式

component 動態擴展 @override 額外 添加 膨脹 裝飾模式 dci 不想 裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作為現有的類的一個包裝。 這種模式創建了一

Java設計模式 - 裝飾模式

 裝飾器模式 裝飾器模式就是在不改變原來設計的同時,動態的給物件新增一些額外的功能(加強原來的功能/拓展原來物件沒有的功能)。 UML圖示 裝飾器模式中的角色 抽象元件(Component):抽象類,規定了被裝飾者需要進行修飾的方法。 具體元件(Compone

設計模式-裝飾模式

在不改變原有結構的基礎上增加新的功能這是在專案裡經常遇到了問題,舉一個例子就明白了。 比如說自然界的動物只能夠奔跑,但是有些動物經過人類的馴化已經慢慢學會了開車;所以我們要給特定的動物增加開車這項本領

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

裝飾器模式 定義:用於替代繼承,無需通過繼承增加子類就能擴充套件物件的新功能。 作用:用於包裝原有的類,並在保持類方法簽名完整性的前提下,提供額外的功能。 優劣: 優點: 裝飾類和被裝飾類可以獨立發展,不會耦合,裝飾器模式是繼承的一個替代方案,

C++設計模式——裝飾模式

裝飾模式能夠實現動態的為物件新增功能,是從一個物件外部來給物件新增功能。在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。 裝飾器模式剛開始看非常難看懂。其實可以想象這種模式如同資料結構的連

從ES6重新認識JavaScript設計模式: 裝飾模式

1 什麼是裝飾器模式 向一個現有的物件新增新的功能,同時又不改變其結構的設計模式被稱為裝飾器模式(Decorator Pattern),它是作為現有的類的一個包裝(Wrapper)。 可以將裝飾器理解為遊戲人物購買的裝備,例如LOL中的英雄剛開始遊戲時只有基礎的攻擊力和法強

移動開發之設計模式- 裝飾模式(IOS&Android)

資源 完全參照 裝飾器模式|菜鳥教程 ,但不包括IOS程式碼 裝飾器模式 裝飾器模式(Decorator Pattern)允許向一個現有的物件新增新的功能,同時又不改變其結構。這種型別的設計模式屬於結構型模式,它是作為現有的類的一個包裝。 這種模式建立了一個裝飾類,用來包裝原有的

C++設計模式-裝飾模式詳解

裝飾器模式:可以動態地給物件新增一下額外的職責或者功能。 張三要出去見女朋友,但是身上的衣服比較破舊,這怎麼能去見自己心愛的女朋友呢?俗話說:人靠衣裝。要給女朋友展示最好的形象包括自己的穿著。 首先定義一個展示基類; #pragma once class IShow { pu

6-Python與設計模式--裝飾模式

一、快餐點餐系統 又提到了那個快餐點餐系統,不過今天我們只以其中的一個類作為主角:飲料類。首先,回憶下飲料類: class Beverage(): name = "" price = 0.0 type = "BEVERAGE" def getPrice

PHP設計模式——裝飾模式

宣告:本系列部落格參考資料《大話設計模式》,作者程傑。         裝飾器模式又叫裝飾者模式。裝飾模式是在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物

PHP-設計模式-裝飾模式

裝飾器類的作用:不使用繼承,也能是物件使用新方法。重點是類例項化出來的物件。 裝飾器類(配菜類)也必須繼承food類,否則就不是裝飾器類了(嗯!就是這樣) 裝飾器: 手抓餅實現。 1:food抽象類 -》cake類 2:food抽象類-》peicai抽象類