【設計模式 03】裝飾模式——俄羅斯套娃?

裝飾模式(俄羅斯套娃?)

裝飾模式:動態的給某些對象添加額外的功能

參考:

  • 簡書 | 裝飾模式

  • 博客園 | 簡說設計模式——裝飾模式

  • 博客園 | 裝飾器模式 Decorator 結構型 設計模式 (十)

什么是裝飾模式

裝飾模式也叫裝飾器模式,python中的裝飾器就是這種模式的體現,對于一個類,如果要添加一個新功能,除了修改代碼外(違反開閉原則),可以使用繼承,但通過繼承添加新功能并不適合所有場景,如

  1. 類不可見或不允許繼承
  2. 需要對一批類似的兄弟類添加同一個新功能時,繼承會產生大量的子類
  3. 希望新功能的添加和撤銷是動態的

裝飾模式中的對象包括:

  1. 裝飾器(用來為被裝飾對象動態添加新功能)

  2. 抽象被裝飾對象(所有能被裝飾對象的抽象)

  3. 被裝飾對象

客戶端如果希望給某個對象動態添加一個新功能,就可以把這個對象(被裝飾對象)傳遞給裝飾器,由裝飾器實現新功能,并保存一個被裝飾對象的引用,并返回給客戶端一個裝飾器對象,這樣,被裝飾對象原來的行為和屬性并沒有改變,甚至被裝飾對象本身就沒有改變,只是在外面套了一個殼子,新功能是這個殼子提供的。就像TCP/IP協議棧中,應用層的數據包到傳輸層通過加TCP或UDP首部來傳輸一樣。

裝飾模式優缺點

優點:

  1. 一個裝飾器可以給多個不同的類動態添加新功能
  2. 新功能由裝飾器實現,不需要修改被裝飾對象,有一定的安全性
  3. 多個裝飾器可以配合嵌套使用,以此實現更復雜的功能
  4. 新功能不影響原來的功能,添加和撤銷都方便

缺點:

  1. 過多的裝飾類可能使程序變得很復雜

  2. 裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構,以及裝飾者是否合適。當然也可以改變Component接口,增加新的公開的行為,實現“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。

    作者:慵懶的陽光丶

適用場景

  1. 要添加的新功能與原有類關聯不大時
  2. 新功能需要方便添加和撤銷時
  3. 不能或不方便通過繼承實現新功能時

比如賣烤冷面,最基本的就是面(抽象被裝飾對象)具體的就是烤冷面(被裝飾對象),然后可以往面里面加各種配料(抽象裝飾器),如雞蛋,辣條等(具體裝飾器),由于不同配料的加入順序對最后的烤冷面有影響,所以如果要用繼承拓展“烤冷面”,那先加雞蛋再加辣條和先加辣條再加雞蛋就需要寫兩個子類,造成冗余重復,這種場景就適合適用裝飾模式。

抽象被裝飾對象

package pers.junebao.decorator_pattern;public abstract class Noodles {public String rawMaterial;  // 配料public abstract void sayWhoAmI();
}

具體的被裝飾對象:

package pers.junebao.decorator_pattern;public class BakedColdNoodles extends Noodles {BakedColdNoodles() {this.rawMaterial = "面";  // 最原始的烤冷面,配料只有面}@Overridepublic void sayWhoAmI() {System.out.println("我是普通烤冷面!");}
}

抽象裝飾器:

package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public abstract class Burden extends Noodles {public Noodles noodles;  // 裝飾器中保留一份被裝飾對象的引用,方便客戶端使用public Burden(Noodles noodles) {this.noodles = noodles;}
}
  • 裝飾器是為某一類對象提供裝飾的(這里就是實現了Noodles 的類)

具體的裝飾器類:

  • 加雞蛋

    package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public class AddEggs extends Burden {public AddEggs(Noodles noodles) {super(noodles);this.rawMaterial = noodles.rawMaterial + ", 雞蛋";}@Overridepublic void sayWhoAmI() {System.out.println("我是加了雞蛋的烤冷面!!");}}
    
  • 加辣條

    package pers.junebao.decorator_pattern.decorator;import pers.junebao.decorator_pattern.Noodles;public class AddSpicyStrips extends Burden{public AddSpicyStrips(Noodles noodles) {super(noodles);this.rawMaterial = noodles.rawMaterial + " ,辣條";}@Overridepublic void sayWhoAmI() {System.out.println("我是加了辣條的烤冷面!!");}
    }
    

客戶端:

package pers.junebao.decorator_pattern;import pers.junebao.decorator_pattern.decorator.AddEggs;
import pers.junebao.decorator_pattern.decorator.AddSpicyStrips;public class Main {public static void main(String[] args) {Noodles bcn = new BakedColdNoodles();Noodles bcnAddEgg = new AddEggs(bcn);bcnAddEgg.sayWhoAmI();System.out.println(bcnAddEgg.rawMaterial);Noodles bcnEggSpicyS = new AddSpicyStrips(bcnAddEgg);bcnEggSpicyS.sayWhoAmI();System.out.println(bcnEggSpicyS.rawMaterial);}
}
/*
我是加了雞蛋的烤冷面!!
面, 雞蛋
我是加了辣條的烤冷面!!
面, 雞蛋 ,辣條*/

這樣如果想先加辣條在家雞蛋,就可以使用AddSpicyStrips先裝飾BakedColdNoodles,再用AddEggs裝飾AddSpicyStrips。

GitHub | 完整代碼

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/457446.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457446.shtml
英文地址,請注明出處:http://en.pswp.cn/news/457446.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

系統移植的四大步驟

最近在學習系統移植的相關知識,在學習和調試過程中,發現了很多問題,也解決了很多問題,但總是對于我們的開發結果有一種莫名其妙的感覺,糾其原因,主要對于我們的開發環境沒有一個深刻的認識,有時…

bem什么意思_bem是什么意思_bem的翻譯_音標_讀音_用法_例句_愛詞霸在線詞典

全部Methods Three different concentrations of the n - butanol extract of MOH ( BEM ) : 0.038 g L ~ ( - 1 ), 0.11 g L ~ ( - 1 ) and 0.34 g L ~ ( - 1 ) were prepared.巴戟天醇提取物 ( BEM ) 配成含生藥0.038gL~ ( -1)、0.11gL~ ( -1 ) 、 0.34gL~ ( -1 ) 三種濃度…

display:flex

flex:彈性布局 常用屬性介紹: flex-direction: column (設置主容器主軸方向) flex-flow: row wrap (第一個參數為flex-direction,第二個為flex-wrap) align-items: flex-start (設…

Linux(Ubuntu 19.10)下 Qt5 連接 MySQL(QMYSQL driver not loaded)

Linux(Ubuntu 19.10)下 Qt5 連接 MySQL 安裝好 MySQL 和 Qt Qt 連接 MySQL 的代碼 QSqlDatabase dQSqlDatabase::addDatabase("QMYSQL");//加載mysql驅動,這個字符串是固定的 d.setHostName("127.0.0.1"); d.setDatabas…

華為消息推送 有透傳通道嗎_求解在推送用透傳消息-使用廠商通道(我用的是基座測試) 用手機測試出現了“clientId離線”問題...

// #ifdef APP-PLUS// uni.showModal({// title: 提示,// content: 您的用戶在其它的app登錄,如果有問題,請修改密碼或重新登錄!,// cancelText:"修改密碼",// confirmText:"好的",// success: function (res) {// if (r…

oneuijs/You-Dont-Need-jQuery

oneuijs/You-Dont-Need-jQuery https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.mdYou Dont Need jQuery 前端發展很快,現代瀏覽器原生 API 已經足夠好用。我們并不需要為了操作 DOM、Event 等再學習一下 jQuery 的 API。同時由于 React…

Wpf 數據綁定簡介、實例1

簡介:1.WPF綁定使用的源屬性必須是依賴項屬性,這是因為依賴項屬性具有內置的更改通知支持,元素綁定表達式使用了Xaml擴展標記, WPF綁定一個控件是使用Binding.ElementName, 綁定非控件對象時使用Source,RelativeSource,DataContex…

【設計模式 04】代理模式

代理模式 代理模式( Proxy):為其他對象提供一種代理以控制對這個對象的訪問。 參考:refactoringguru | proxy 什么是代理模式 有時候如果想要訪問某個對象,但又沒辦法直接訪問或不方便直接訪問,可以使用代理模式,代理…

css 大于號 標簽_CSS設計基礎選擇器篇

點擊上方 Java項目學習 ,選擇 星標 公眾號重磅資訊、干貨,第一時間送達前言:如果將CSS樣式應用于特定的網頁對象上,需要先找到目標元素。在CSS樣式中執行這一任務的部分被稱為選擇器。1 標簽選擇器優點:為頁面中同類型…

CSDN博客投票活動開始了

自己堅持寫博客,一方面是為了將自己對知識點的理解做一個總結,另一方面也是因為自己看到了很多無私奉獻分享自己知識的小伙伴們,因此自己也想像他們那樣盡自己微薄之力把自己對某一知識點的理解分享給大家,或許算不上什么特高級的…

crontab 提示 command not found 解決方案

crontab 提示 command not found 解決方案 今天遇見一個問題,crontab的定時任務會報錯:java command not found,但是手動執行腳本一直能成功。 猜想是環境變量的問題。 在crontab里添加個打印環境變量的任務: * * * * * echo $PAT…

java中文亂碼decode_Java中文亂碼處理

java編碼轉換過程我們總是用一個java類文件和用戶進行最直接的交互(輸入、輸出),這些交互內容包含的文字可能會包含中文。無論這些java類是與數據庫交互,還是與前端頁面交互,他們的生命周期總是這樣的:1、程序員在操作系統上通過編…

【設計模式 05】工廠方法模式

工廠方法模式 define an interface or abstract class for creating an object but let the subclasses decide which class to instantiate. 參考: refactoringguru | factory-methodjavatpoint | factory-method-design-pattern博客園| 工廠方法 簡單工廠的問題 …

[C++]宏定義#define A B C

C關于宏定義的用法,有形如#define A B C的格式,此時B和C都是已知的字符串常量. 在宏定義中. 可以把兩個常量字符串連在一起 如果#define A "a" 那么宏定義#define STRING A "bc" 就相當于 #define STRING "abc" 這里&…

LinkedList類源碼淺析(二)

1、上一節介紹了LinkedList的幾個基本的方法,其他方法類似,就不一一介紹; 現在再來看一個刪除的方法:remove(Object o) remove方法接受一個Object參數,這里需要對參數做空與非空處理; 但是刪除一個Object元…

【設計模式 06】原型模式(克隆??)

原型模式(clone?) Prototype pattern refers to creating duplicate object while keeping performance in mind. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object. 參考: tutori…

2016OSC源創會年終盛典-綜合技術專場-張小剛

2019獨角獸企業重金招聘Python工程師標準>>> 綜合技術專場 講師/SPEAKERS 張小剛 網易云負載均衡項目負責人 《網易蜂巢負載均衡技術實踐》從網易蜂巢中的實踐出發,分享網易蜂巢負載均衡服務從無到有,從私有云到公有云過程中的技術實踐。重點…

python策略模式包含角色_詳解Python設計模式之策略模式

雖然設計模式與語言無關,但這并不意味著每一個模式都能在每一門語言中使用。《設計模式:可復用面向對象軟件的基礎》一書中有 23 個模式,其中有 16 個在動態語言中“不見了,或者簡化了”。1、策略模式概述策略模式:定義…

mysql 日期

數據類型 數據類型格式date YYYY-MM-DD datetime YYYY-MM-DD HH:MM:SS timestamp YYYY-MM-DD HH:MM:SS year YYYY 或 YY 具體實現的函數 1、now() 返回當前的日期和時間 SELECT NOW(); 2、curdate() 返回當前的日期 SELECT CURdate(); 3、curtime()返回當…

【Go】panic: reflect: call of reflect.Value.FieldByName on ptr Value

產生原因 調用 FieldByName()方法時,調用者與預期類型不相符。 // 錯誤代碼 func setNewArticleInfoToCache(article *Article) {fields : []string{"Title", "Abstract", "ID", "AuthorID", "CreateTime",}im…