動態地將責任附加到物件上。若要擴充套件功能,裝飾者提供了比繼承更有彈性的替代方案。
設計原則四:類應該對擴充套件開放,對修改關閉。星巴克的訂單系統系統中有個飲料抽象類 beverage,店內的飲料都必須繼承該類:如果使用過 python,應該聽過裝飾器,雖然概念有點不同,但都是通過動態新增的方式給物件擴充套件功能。
其中一些飲料:abstract class beverage
// 飲料價錢
public
abstract
float
cost();
}
現在,客戶想要在買的飲料裡加點調味料,比如買了杯咖啡,要加點牛奶、豆漿、巧克力等。這就需要訂單系統在統計飲料**時加上調味料的**。class coffee extends beverage
@override
public
float
cost()
}class milk extends beverage
@override
public
float
cost()
}// ...
每種可能的調味料的飲料都新建乙個類:
很明顯,調味料有很多,飲料也有很多,如果只加一種調味料,那搭配起來也有非常多的可能,如果都新建乙個類,那麼就會造成「類**」。而且這些調味料的**如果發生變化,就要將涉及的飲料都修改一遍,嚴重違反了設計原則中的「將變化與不變化的**分開」。class coffeewithmilk extends beverage
}class milkwithcoffee extends beverage
}// ....
既然違反了變化的原則,那麼嘗試把這些變化的調味料都放在飲料抽象類 beverage 中?
飲料只要設定好新增的調味料,最後計算下自身花費就好了:abstract class beverage
// 計算好新增的調味料**,讓子類直接呼叫
public
float
cost()
if (hasmilk())
return sum;
}protected
boolean
hascoffee()
protected
void
setcoffee(boolean coffee)
protected
boolean
hasmilk()
protected
void
setmilk(boolean milk)
}
呼叫:class coffee extends beverage
}class milk extends beverage
}
現在沒有了「類**」,就算調料**發生變化,只要修改下抽象類就好了,但是真的沒問題了嗎?public
class
main
}
有問題,而且挺多的:
1. 如果出現新的調味料,就需要在抽象類新增新的布林值成員,cost 方法也需要新增新的判斷,還要分別新增乙個 setter 和乙個 getter,如果是刪除乙個調味料呢?
2. 對於有些飲料來說,某些調味料並不能加(會拉肚子的!),比如冰紅茶 + 牛奶?
3. 如果客戶要一杯咖啡,加兩份牛奶呢?
不改變原有的飲料抽象和具體的飲料:
abstract class beverage
public
abstract
float
cost();
}
新增調味料(condiment)裝飾者:class coffee extends beverage
@override
public
float
cost()
}
abstract class condimentdecorator extends beverage
調味料繼承調味料裝飾者:
class milk extends condimentdecorator
@override
public string getdescription()
@override
public
float
cost()
}class mocha extends condimentdecorator
@override
public string getdescription()
@override
public
float
cost()
}
輸出:public
class
main
}
coffee
3.2cof
fee+
milk
+moc
ha3.2co
ffee
+mil
k+mo
ch
a3.9
coffee + milk + milk + milk + mocha + mocha $5.0999994
Head First 設計模式筆記
將變化部分和不變部分分離出來,讓 適應變化 封裝變化 針對介面程式設計,而不是針對實現程式設計 即,將一類行為抽象成行為類介面,可以應對變化,符合原則1 多用組合,少用繼承 這條原則,是建立在原則2的基礎上的,好處是系統有很大的彈性,執行時可以動態改變物件的行為 例如 策略模式 定義演算法簇 學會使...
Head First 設計模式筆記
1.找出應用中可能變化的地方,將它們獨立出來。不要和那些不需要變化的部分混在一起 2.針對介面程式設計,而不是針對實現程式設計 針對 介面程式設計 的意思是 針對超型別程式設計 針對介面程式設計關鍵在於多型。利用多型程式設計師可以針對超型別程式設計,編譯器執行會根據實際情況執行到真正的行為,而不會將...
head first 設計模式 工廠模式筆記
工廠模式 是舉了個做pizza的例子 有pizzastore抽象類裡邊有個pizza物件變數,orderpizza中裡面有個方法 叫做createpizza,同時外面定義了乙個createpizza抽象方法,然後實現裡面有個方法 叫做createpizza,此方法更具不同的引數new不同的對 象,如...