GO BEYOND YOURSELF
學過面向物件的我們都知道,通過繼承:能夠重用和擴充套件已經被徹底測試過的程式碼,且無需修改之。但就像策略模式中所講到的,繼承會禁錮類的方法。那麼如果要擴充套件功能,我們還是必須使用繼承嗎?
答案當然是否定的,因為設計模式中為我們提供了一個很好的模式--裝飾模式:動態地將責任附加到物件上。這裡所謂的動態可以簡單理解為靈活。那麼不使用繼承,又要如何幫助我們達到目的呢?下面一起來看。
先來看一個例子,我們去咖啡店買咖啡,光咖啡型別就有不同的選擇:綜合、深焙、低咖啡因、濃縮。但喝咖啡可沒這麼簡單,它還需要加入相應的配料來滿足顧客口味需求:牛奶、豆漿、摩卡、奶泡。現在咖啡店要增加一些新口味和型別,那麼原先使用繼承的系統將不再適用,一旦增加的型別和種類增多下面的這張圖就變成一坨了吧:
那麼使用裝飾模式應該是什麼樣的呢?
像上面這幅圖顯示的這樣,我們將具體的咖啡型別和配料都作為一個類的子類,通過型別和配料的自由組合實現功能的同時實現程式碼的複用性,提高後期的可維護性。其程式碼如下:
1.抽象類
<span style="font-size:18px;">package 巴茲咖啡; //這是一個抽象類。 public abstract class Beverage { String description ="Unknown Beverage"; public String getDescription (){ //獲取咖啡調配方法 return description; } public abstract double cost(); } </span>
2.具體元件
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
public class DarkRoast extends Beverage {
public DarkRoast() {
description ="DarkRoast Coffee";
}
public double cost(){
return .99;
}
}
</span>
public class Espresso extends Beverage { public Espresso () { description ="Espresso"; } public double cost(){ return 1.99; } }
public class HouseBlend extends Beverage {
public HouseBlend(){
description ="House Blend Coffee";
}
public double cost(){
return .89;
}
}
</span>
其他幾個類和上面列舉的類似,大家可以動手實現。最終會實現下面的效果:
如果店內有需求,要實現杯型大小來進行收費,那麼我們可以在CondimentDecorator中新增中杯、小杯、大杯三個類,抽象類中新增方法:getSize()對杯型進行獲取,然後通過杯型、咖啡型別和配料的不同搭配來實現靈活收費。這樣一來也就實現了動態的新增的同時也達到了解耦的效用。豈不是一舉兩得?
總結:
1.裝飾模式中使用組合和委託在系統執行時對系統動態的增加功能。而該模式也就意味著我們要建立一堆的裝飾者類,而它們又恰好是用來裝飾元件的,比如:Mocha、Whip等四個配料都是用來裝飾HouseBlend、 DarkRoast這 些咖啡型別的。
2.我們可以使用一個或者多個裝飾者包裝一個元件:調配出一箇中杯的,加入牛奶、摩卡等的低咖啡因咖啡。
3.裝飾者會導致設計中出現許多小物件,如果過度使用,程式依舊會變得複雜。也就是說,我們不能將咖啡的型別和配料的種類無限的擴張,否則系統會因為過多的咖啡種類和配料而執行緩慢甚至癱瘓。凡事遵循一個度的問題,東西再好吃也不能撐死,模式再好用也不能拖死系統。
所以說,在一定程度上,裝飾者模式還是很棒的呢。
最後祝大家軟考順利,考試加油,let's go !!
相關推薦
GO BEYOND YOURSELF
學過面向物件的我們都知道,通過繼承:能夠重用和擴充套件已經被徹底測試過的程式碼,且無需修改之。但就像策略模式中所講到的,繼承會禁錮類的方法。那麼如果要擴充套件功能,我們還是
Be yourself and Beyond yourself
傳統的開發團隊通常按角色就行分工, 開發人員只管開發, 測試人員只管測試, 在自己的職責之外的事, 要麼是看不見, 要麼是覺得不是我的活,我不用去管,做好做壞和我沒有關係。 而敏捷軟體開發恰恰相反, 更加強調“Whole Team”, 即整個團隊對外做出承諾, 團隊中的所
No one can go beyond !
大多數人認為的Linux系統安裝軟體都比較麻煩,Linux系統的軟體也非常少,其實不然,Ubuntu發行版的Linux安裝軟體非常簡單,軟體應用也非常多,今天小編就給大家分享Ubuntu系統中如何安裝軟體。 我們就以安裝Chrome瀏覽器為例來說明如何在Ubuntu系統中安裝Chrome瀏覽器。
How to go from a Blockchain Tourist to a Blockchain Citizen: Beyond the Hype
How to go from a Blockchain Tourist to a Blockchain Citizen: Beyond the HypeHow to go from a Blockchain Tourist to a Blockchain CitizenBlockchain tourism a
go 自己封的postgresql操作包
rep make query res urn mod .exe errors exe 1 package myDB 2 3 import ( 4 "database/sql" 5 "errors" 6 7 _ "g
go-005-變量
整數 func 基礎 字型 開始 import open spl 註意 概述 變量來源於數學,是計算機語言中能儲存計算結果或能表示值抽象概念。變量可以通過變量名訪問。 Go 語言變量名由字母、數字、下劃線組成,其中首個字母不能為數字。 聲明變量的一般形式是
GO中常用包筆記 bytes(四)
g 學習筆記 bytes包Package bytes對字節數組進行操作的包。功能和strings包相似.bytes包提供的功能有:和另一個字節數組切片的關系(逐字節比較大小,是否相等/相似,是否包含/包含次數,位置搜索,是否是前綴後綴)2.字節數組切片和字符串的關系(字符串中是否含有字節數組所包含的rune,
CDOJ 1221 Ancient Go
cout#include<bits/stdc++.h>using namespace std;bool ok;char maze[15][15];char Map[12][12];bool vis[15][15];int x[4] = {0,0,1,-1};int y[4] = {1,-1,0,0
Go - 數組
索引 創建 16px class 表示 int32 部分 func amp 數組: Array 1. 定義: var <arrayName> [n] (n>=0) <type> 註: 數組的長度n,也是數組定義的組成部分;所以:var i
Go語言之嵌入類型
go 類型 嵌入類型,或者嵌套類型,這是一種可以把已有的類型聲明在新的類型裏的一種方式,這種功能對代碼復用非常重要。在其他語言中,有繼承可以做同樣的事情,但是在Go語言中,沒有繼承的概念。Go提倡的代碼復用的方式是組合,所以這也是嵌入類型的意義所在。組合而不是繼承,所以Go才會更靈活。type Rea
後端程序員之路 52、A Tour of Go-2
run arrays primes var auto 程序 pointer ase tex # flowcontrol - for - for i := 0; i < 10; i++ { - for ; sum < 1000;
go語言的優點
程序編寫 執行文件 語言培訓 多線程 老男孩 老男孩教育go語言培訓是國內首家go語言培訓機構,主講老師是小米架構資深架構師,有多年go開發經驗。小編現將go語言優點整理如下,希望能幫到你們 1.部署簡單Go 編譯生成的是一個靜態可執行文件,除了 glibc 外沒有其他外部依賴。這讓部署變
Go - 切片(Slice)
什麽 部分 pri 長度 code ron logs 內存 tro 定義 切片本身不是數組,它指向底層的數組或者數組的一部分。因此,可以使用Slice來處理變長數組的應用場景。 Silice 是一種引用類型。 1、定義一個空的Slice package main
JavaScript ,Python,java,Go系列算法之選擇排序
javascript java python go系列算法之選擇排序 常見的內部排序算法有:插入排序、希爾排序、選擇排序、冒泡排序、歸並排序、快速排序、堆排序、基數排序等。用一張圖概括:選擇排序 選擇排序是一種簡單直觀的排序算法,無論什麽數據進去都是O(n2) 的時間復雜度。所以用到它的
Go -- log4go日誌
全部 導入 ren tle ack stat body utm app 折騰: 【已解決】go語言中實現log信息同時輸出到文件和控制臺(命令行) 期間,已經通過io的MultiWriter搞定了同時輸出信息到文件和console,但是不支持level。 所以,再去試
Go的微服務庫kite
targe post 服務 core 調用 protocol tag 運行 interface Kite Kite是用Go開發的一套RPC庫,很適合作為分布式微服務的開發框架。 Kite 的傳輸層使用 SockJS 提供的WebSocket服務, 瀏覽器Javascri
go語言筆記——append是內置的函數!!!new是一個函數!!!調試可以使用閉包,本質上是print調試,尼瑪!
... -c map blob 名稱 ebo bsp 處理機制 它的 內置函數 Go 語言擁有一些不需要進行導入操作就可以使用的內置函數。它們有時可以針對不同的類型進行操作,例如:len、cap 和 append,或必須用於系統級的操作,例如:panic。因此,它們需要直接
go語言筆記——切片函數常見操作,增刪改查和搜索、排序
通過 學習 strings 完整 官方文檔 二分 func fun 必須 7.6.6 搜索及排序切片和數組 標準庫提供了 sort 包來實現常見的搜索和排序操作。您可以使用 sort 包中的函數 func Ints(a []int) 來實現對 int 類型的切片排序。例如
go語言筆記——map map 默認是無序的,不管是按照 key 還是按照 value 默認都不排序
pcr 錯誤 固定 pre text 輸出結果 示例 operation frequency 示例 8.1 make_maps.go package main import "fmt" func main() { var mapLit map[string]int
GO語言 --socket.io
broadcast logfile hub println ogg sta out his ror socket.io是對websocket的封裝以及擴展, 可以跨平臺使用, 具體可看官網.. GO語言實現: package main import (