I. 引言
設計模式(Design Pattern)是一套被反復使用灼伤、多數(shù)人知曉的、經(jīng)過分類的咪鲜、代碼設計經(jīng)驗的總結(jié)狐赡。
使用設計模式的目的:為了代碼可重用性、讓代碼更容易被他人理解疟丙、保證代碼可靠性颖侄。 設計模式使代碼編寫真正工程化;設計模式是軟件工程的基礎(chǔ)享郊,如同大廈的結(jié)構(gòu)一樣览祖。
創(chuàng)建型模式:對類的實例化過程的抽象。一些系統(tǒng)在創(chuàng)建對象時炊琉,需要動態(tài)地決定怎樣創(chuàng)建對象展蒂,創(chuàng)建哪些對象又活,以及如何組合和表示這些對象。創(chuàng)建模式描述了怎樣構(gòu)造和封裝這些動態(tài)的決定锰悼。包含類的創(chuàng)建模式和對象的創(chuàng)建模式柳骄。
結(jié)構(gòu)型模式:描述如何將類或?qū)ο蠼Y(jié)合在一起形成更大的結(jié)構(gòu)。分為類的結(jié)構(gòu)模式和對象的結(jié)構(gòu)模式箕般。類的結(jié)構(gòu)模式使用繼承把類耐薯,接口等組合在一起,以形成更大的結(jié)構(gòu)丝里。類的結(jié)構(gòu)模式是靜態(tài)的曲初。對象的結(jié)構(gòu)模式描述怎樣把各種不同類型的對象組合在一起,以實現(xiàn)新的功能的方法丙者。對象的結(jié)構(gòu)模式是動態(tài)的复斥。
行為型模式:對在不同的對象之間劃分責任和算法的抽象化。不僅僅是關(guān)于類和對象的械媒,并是關(guān)于他們之間的相互作用目锭。類的行為模式使用繼承關(guān)系在幾個類之間分配行為。對象的行為模式則使用對象的聚合來分配行為纷捞。
設計模式分為三種類型痢虹,共23種。
創(chuàng)建型模式:單例模式主儡、抽象工廠模式奖唯、建造者模式、工廠模式糜值、原型模式丰捷。
結(jié)構(gòu)型模式:適配器模式、橋接模式寂汇、裝飾模式病往、組合模式、外觀模式骄瓣、享元模式停巷、代理模式。
行為型模式:模版方法模式榕栏、命令模式畔勤、迭代器模式、觀察者模式扒磁、中介者模式庆揪、備忘錄模式、解釋器模式妨托、狀態(tài)模式嚷硫、策略模式检访、責任鏈模式、訪問者模式仔掸。
下面將對一些常用的設計模式和軟件設計的六大原則進行介紹。
一. 創(chuàng)建型模式
1. Factory method 工廠方法(工廠模式)
作用
一個類需要一個產(chǎn)品來完成某項工作医清,但它不能確定起暮,也不關(guān)心具體拿到什么產(chǎn)品,因此它定義一個工廠方法会烙,將具體產(chǎn)品的生產(chǎn)延遲到子類決定负懦。
實現(xiàn)
- 父類可以選擇為工廠方法提供一個默認的實現(xiàn);
- 工廠方法通常在模板方法(Template method)中被調(diào)用柏腻,上圖中
AnOperation()
就是一個模板方法纸厉。
2. Abstract factory 抽象工廠
作用
系統(tǒng)有一組相互關(guān)聯(lián)的產(chǎn)品接口,及幾套不同的實現(xiàn)五嫂】牌罚客戶只依賴產(chǎn)品接口,并需要能靈活地在幾套實現(xiàn)中切換沃缘。
因此提供一個抽象工廠生產(chǎn)抽象的產(chǎn)品躯枢,每個產(chǎn)品在其中都對應一個工廠方法,產(chǎn)品族的每一套實現(xiàn)都提供一個具體工廠槐臀〕澹客戶通過抽象工廠獲取產(chǎn)品,當需要切換到產(chǎn)品的其他實現(xiàn)時只需要更換工廠的實現(xiàn)類水慨。
實現(xiàn)
應用
根據(jù)底層數(shù)據(jù)源的不同得糜,DAO的實現(xiàn)通常有幾套,當切換數(shù)據(jù)源時晰洒,系統(tǒng)使用的DAO的實現(xiàn)也應當能快速切換朝抖。這是使用抽象工廠的一個典型場景。
3. Singleton 單例
作用
保證一個類只有一個對象
實現(xiàn)
-
private
構(gòu)造器 -
private static
類變量 singleton -
public static
類方法getInstance()
返回singleton欢顷。
實例化時機:
- eager
- lazy
lazy init 多線程問題的解決辦法:Double Check
private volatile static A singleton = null;
public static A getInstance(){
if(singleton == null){
sychronized(A.class){
if(singleton == null) singleton = new A();
}
}
return singleton;
}
private A(){}
- 為什么要第二次的null判斷槽棍?
在第一次判null / 獲取鎖之間可能有其他線程實例化了。 - 為什么要
volatile
抬驴?
在上面提到的情況下炼七,如果沒有volatile
保證的可見性,在第二次null判斷時當前線程可能看不到別的線程創(chuàng)建的對象布持,從而通過并再創(chuàng)建一次豌拙。
static 內(nèi)部類
利用 “類的加載/static塊是線程安全的” 實現(xiàn)線程安全的lazy init:
public class A{
private static class Holder{
private static A singleton = new A();
}
public static A getInstance(){
return Holder.singleton;
}
private A(){}
}
4. Builder 建造者模式
作用
你有一個產(chǎn)品,該產(chǎn)品由若干part裝配而成题暖,裝配的邏輯是固定的按傅,但各個part的構(gòu)造是可切換選擇的捉超,Builder模式將 固定的裝配邏輯 與 易變的part構(gòu)造邏輯 分離開,可以方便地在不同的part實現(xiàn)邏輯之間切換唯绍。
實現(xiàn)
-
Director#construct()
負責固定的裝配邏輯拼岳; - 一個
Builder
實例負責一個產(chǎn)品內(nèi)部所有part的構(gòu)造(buildPart()
方法族),并向外部暴露方法况芒,在part都裝配完畢后獲取該產(chǎn)品惜纸。
交互
5. Prototype 原型模式
作用
用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象绝骚。
適用性
當要實例化的類是在運行時刻指定時耐版,例如,通過動態(tài)裝載压汪;
為了避免創(chuàng)建一個與產(chǎn)品類層次平行的工廠類層次時粪牲;
當一個類的實例只能有幾個不同狀態(tài)組合中的一種時。建立相應數(shù)目的原型并克隆它們可能比每次用合適的狀態(tài)手工實例化該類更方便一些止剖。
實現(xiàn)
二. 結(jié)構(gòu)型模式
1. Adapter 適配器
作用
在兩個不兼容的接口之間加一個中間層腺阳,用組合的方式將一個現(xiàn)有對象匹配到需要的接口。
Convert the interface of a class into another interface the client expects
實現(xiàn)
2. Proxy 代理
作用
Provide a surrogate or place holder for another object to control access to it
你有一個真正干活的對象RealSubject滴须,但需要向client控制對他的訪問舌狗,比如權(quán)限的控制 / Lazy load / 結(jié)果的緩存等等,因此在client和RealSubject之間增加一個中間層Proxy代替RealSubject扔水,Proxy包裹RealSubject痛侍,將具體功能實現(xiàn)委托給它,并在RealSubject執(zhí)行真正的功能前后插入自己的邏輯魔市;此外主届,Proxy向client隱藏了RealSubject的存在。
實現(xiàn)
與Decorator
模式的區(qū)別
Proxy與Decorator有著相似的結(jié)構(gòu)待德,** 他們都在client和真實對象之間增加一個與真實對象實現(xiàn)了相同接口的中間層君丁,這個中間層保留了對真實對象的引用并向他們發(fā)送請求**。然而他們的設計目的是不同的:
Decorator側(cè)重動態(tài)為實體增加功能将宪,因此在該模式中:
- 實體只實現(xiàn)了部分功能绘闷,Decorator實現(xiàn)了其他的增強功能;
- 支持遞歸組合(增加多重功能)较坛;
- Decorator不知道自己裝飾的是哪個具體對象印蔗,client必須自己手動將實體和Decorator關(guān)聯(lián)起來。
Proxy的目的則是當訪問一個特定實體不方便或不符合要求時丑勤,為這個實體提供一個替代者华嘹,因此:
- 實體實現(xiàn)了關(guān)鍵功能,Proxy提供(或拒絕)對它的訪問法竞;
- 不支持遞歸組合耙厚;
- Proxy向client屏蔽RealSubject的存在强挫,client只能拿到Proxy;
- Proxy確定地知道自己的代理目標是RealSubject薛躬,因此它和RealSubject相關(guān)聯(lián)而不是Subject接口俯渤;此外,它們的關(guān)系是靜態(tài)的型宝,無法在運行時改變Proxy代理的目標對象稠诲。
3. Bridge 橋接模式
作用
你有一個產(chǎn)品,它在兩個維度上都是可變化的诡曙,如果用繼承,則需要n*m個子類略水。Bridge模式將兩個維度的繼承體系獨立出來价卤,并在二者之間用組合進行裝配,避免類的泛濫渊涝。
進一步地考慮慎璧,一個產(chǎn)品的繼承體系應該只有一個維度,如果出現(xiàn)了其他維度上的繼承跨释,要考慮該維度是否是行為/實現(xiàn)相關(guān)的胸私。對于行為/實現(xiàn)方面的變化,應當先把行為獨立地抽象出來鳖谈,并與原產(chǎn)品組合(這就是策略模式
的含義)岁疼,而不應該直接在原產(chǎn)品上通過繼承表達該行為的變化。
舉個例子缆娃,假如系統(tǒng)內(nèi)要發(fā)送消息捷绒,消息按迫切程度分為普通/加急/特急,消息的發(fā)送形式也可以多樣贯要,比如站內(nèi)信/短信/email暖侨,每種消息都要求可以用任意方式發(fā)送:
如果簡單地用繼承,則需要33 = 9個類崇渗。但實際上字逗,消息的發(fā)送* 這個維度屬于行為,不要用繼承來表達行為的變化宅广,這樣會污染原本的抽象層次葫掉,應當用策略模式
將 消息發(fā)送 這個行為分離。
采用Bridge模式:
實現(xiàn)
產(chǎn)品的抽象 + 行為的分離(策略模式
)
總結(jié)
Bridge模式在我看來是對策略模式
的擴展乘碑,它的核心有兩點:
- 只在一個維度上用繼承挖息,出現(xiàn)了多個維度則考慮分離并用組合,避免類的泛濫和抽象維度的混雜兽肤;
- 用
策略模式
隔離行為的變化套腹,不要讓行為/實現(xiàn)的變化污染原本的繼承體系绪抛。
4. Decorator 裝飾者
作用
有一系列產(chǎn)品,你希望動態(tài)地為他們添加額外 / 可自由組合 的功能电禀,并且不影響產(chǎn)品本身幢码。
Attach additional responsibilities to an object dynamically.
實現(xiàn)
-
Decorator 裝飾器
繼承產(chǎn)品抽象接口尖飞,并在內(nèi)部持有一個產(chǎn)品(可能是具體產(chǎn)品,也有可能被裝飾過了)贞铣; -
Decorator
的具體實現(xiàn),為其裝飾的產(chǎn)品提供額外的功能沮明,類似遞歸的調(diào)用; - 可以同時反復應用多個
Decorator
酱畅,實現(xiàn)額外功能的動態(tài)組合。
應用
-
java的IO流的設計是一個典型的裝飾者模式:
ByteArrayInputStream | FileInputStream | ObjectInputStream | StringBufferInputStream
是具體的輸入流產(chǎn)品江场,根據(jù)數(shù)據(jù)來源區(qū)分;
FilterInputStream
是裝飾器餐蔬;
BufferedInputStream | DataInputStream | LineNumberInputStream | PushbackInputStream
是具體的裝飾器在张,分別為其他輸入流提供緩沖/類型讀寫/跟蹤行號/退回已讀數(shù)據(jù)的功能帮匾,這些裝飾器是可以組合使用的:
InputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
-
Decorator模式
也可以用來實現(xiàn)AOP
的類似功能(雖然實際大部分都是用JDK動態(tài)代理 / 運行時修改字節(jié)碼
)瘟斜,Decorator
的具體實現(xiàn)就是我們想要獨立出來的切面,產(chǎn)品的具體實現(xiàn)則是我們想要保持獨立的業(yè)務邏輯虽惭。
5. Composite 組合模式
作用
實現(xiàn)樹形結(jié)構(gòu)芽唇,并讓用戶可以用統(tǒng)一的接口對待葉子節(jié)點和非葉子節(jié)點匆笤。
實現(xiàn)
- 操作孩子的方法應該放在Component中嗎炮捧?畢竟Leaf是不支持這些操作的庶诡。
出于透明性考慮末誓,應該放在Component中喇澡,Leaf對這些方法就提供一個空的實現(xiàn)殊校。 - Component除了保存孩子箩艺,也可以記錄父親艺谆;
應用
UI / 人員組織管理這種典型的樹形結(jié)構(gòu)中用的比較廣泛静汤。
6. Facade 門面模式
作用
一個系統(tǒng)對外提供服務虫给,系統(tǒng)暴露的接口應該是簡單而統(tǒng)一的侠碧,客戶不應該直接和系統(tǒng)內(nèi)復雜的子部件進行交互弄兜,而應只依賴于一個單一的高層接口替饿,該組件為客戶屏蔽了內(nèi)部的復雜性视卢,降低了客戶和系統(tǒng)的耦合据过。
更像是一種設計思路,而非一個具體模式饥漫。
三. 行為模式
1. Chain of Responsibility 責任鏈
作用
客戶端發(fā)出一個請求庸队,有一系列的處理器都有機會處理這個請求闯割,但具體哪個是運行時決定的宙拉,客戶端也不知道究竟誰會來處理谢澈。
因此將所有處理器組成一個鏈條锥忿,將請求從鏈條中流過敬鬓,每個處理器查看是否應該處理它,如果不是础芍,則交給后面的處理器仑性,否則處理并退出虏缸。處理器在鏈中的位置決定其優(yōu)先級刽辙。
將請求者和處理者解耦宰缤,可以動態(tài)切換/組合處理者慨灭。
實現(xiàn)
擴展
客戶端發(fā)出一個請求氧骤,請求的處理分為很多步驟筹陵,這些步驟是不確定的/可以動態(tài)組合的朦佩,甚至需要支持在運行時改變步驟,或者在步驟間任意跳轉(zhuǎn)宋彼。
解決方案和責任鏈類似输涕,將處理流程抽象為一個處理器鏈條占贫,鏈條的組裝交給外部決定。每個處理器對請求完成自己負責的業(yè)務邏輯碉京,并看情況結(jié)束/傳遞給下一個處理器/跳轉(zhuǎn)到任意處理器谐宙。
這和標準的責任鏈的結(jié)構(gòu)基本一樣凡蜻,但他們的目的不一樣划栓。標準責任鏈目的是動態(tài) 找到請求的處理者 忠荞;擴展(某些地方稱為“功能鏈”委煤?)則是為了獲取 動態(tài)拼裝和改變處理流程 的能力碧绞。
應用
標準責任鏈
UI中的事件冒泡機制是責任鏈的一個典型應用讥邻。HTML中,點擊一個DOM元素袜香,產(chǎn)生的click事件將依次冒泡給它的父元素蜈首,每個父元素上都可以注冊對click事件的監(jiān)聽器欢策,監(jiān)聽器中除了對事件處理外踩寇,也可以結(jié)束事件的繼續(xù)冒泡俺孙。
擴展(功能鏈)
- Web應用中的各種filter/攔截器睛榄;
- Netty中的pipeline
2. Command 命令
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
你需要向一個對象提交請求场靴,但對請求的處理是動態(tài)的旨剥,無法寫死轨帜。比如一個菜單項阵谚,在不同的上下文中梢什,點擊它要做的事情顯然是不一樣的嗡午。
Command模式的思路是 抽象請求(及處理):
-
Client
裝配Invoker
和Command
狸演,** 如果需要不同的處理宵距,裝配不同的Command即可 **; -
Client
向Invoker
發(fā)出請求; -
Invoker
將請求的處理委托給Command#execute()
满哪。
很多時候Command不夠智能哨鸭,自己無法處理請求像鸡,需要將請求委托給另一個Receiver進行真正的處理只估,ConcreteCommand可以認為是Receiver的適配器:
可以看到蛔钙,Command模式的最大價值在于:隔離 請求的接收者
和 請求的處理邏輯
;
此外子漩,將請求及其處理邏輯抽象為Command后可以做很多有意思的事情:
1. 可撤銷的操作
在Command接口中增加一個接口 undo()
實現(xiàn)單個命令的撤銷動作幢泼,并用一個stack
保存所有Command缕棵;當用戶觸發(fā)撤銷時依次從stack pop出最近的Command招驴,執(zhí)行其undo()
方法别厘。
2. 宏命令
宏命令實質(zhì)是個樹形結(jié)構(gòu)氮发,對Command應用Composite 組合模式
即可實現(xiàn):
3. 排隊
4. 日志記錄和恢復
3. Memento 備忘錄
有些情況下你需要記錄一個對象(稱為Originator
)在某個時刻的狀態(tài)(snapshot)爽冕,以便后續(xù)恢復颈畸,我們可以用一個類Memento
表示snapshot承冰,它包含了Originator的部分或全部狀態(tài):
- Originator 負責創(chuàng)建Memento,以及恢復到某個Memento娜搂;
- Memento 即Originator的snapshot百宇;
- Caretaker 充當協(xié)調(diào)者携御,它負責向Originator請求當前Memento / 保存Memento / 在后續(xù)某個時刻讓Originator恢復到某個Memento啄刹。
但這里有一個問題誓军,為了隱藏Originator的實現(xiàn)細節(jié)昵时,Memento
必須向外部隱藏內(nèi)部數(shù)據(jù)壹甥,即不開放state
的 getter/setter 給外部盹廷,但這樣一來俄占,Originator也無法創(chuàng)建Memento
了渤弛。
為了解決這個問題她肯,在Memento模式的一般實現(xiàn)中晴氨,Memento
類被分為兩個部分:
- 標記接口
Memento
籽前,空的枝哄,Caretaker
只能得到這個接口挠锥; - Memento的真正實現(xiàn)
MementoImpl
,作為Originator
的 私有內(nèi)部類 蓖宦,這樣既允許Originator訪問Memento的內(nèi)部狀態(tài)球昨,又滿足了Memento向外部(主要是Caretaker)隱藏內(nèi)部細節(jié)的要求主慰。
如果對 Memento
的封裝性沒有嚴格的要求共螺,第一種實現(xiàn)顯然更簡單藐不。
4. Observer 觀察者
作用
定義一個一對多關(guān)系,在Subject狀態(tài)發(fā)生改變時挑秉,所有Observer獲得通知犀概。
解耦 事件發(fā)生者 & 事件接收者倘零,使得雙方的改動互不影響产喉,關(guān)聯(lián)關(guān)系也可動態(tài)改變。
實現(xiàn)
數(shù)據(jù)傳遞的兩種方式:
- 推:由 Subject 主動向 Observer 推送信息晦譬,而不管信息對后者而言是否需要/是否足夠敛腌。
- 拉:Subject 把自己傳遞給 Observer,由 Observer 從 Subject 拉取自己需要的信息惫皱。
擴展: Observer 注冊時可以指定自己感興趣的事件像樊。
擴展:EventBus
傳統(tǒng)的Observer模式中,事件發(fā)生者和接收者依然存在耦合旅敷,發(fā)生者需要管理接收者的集合生棍,我們可以進一步地,在Subject和Observer間增加一個中間層負責轉(zhuǎn)發(fā)事件媳谁,將它們徹底地解耦友酱;進一步,這個事件轉(zhuǎn)發(fā)者可以是通用的柔纵,支持任意發(fā)布者和接受者缔杉,通常稱之為EventBus
,是一種廣泛應用的架構(gòu)搁料。
5. State 狀態(tài)模式
作用
模擬狀態(tài)機或详,描述一個對象(Context)的狀態(tài)變遷,將特性狀態(tài)下的行為分割開來郭计,避免在Context中用大量的if維護所有狀態(tài)的變遷霸琴,而且容易擴展新的狀態(tài)。
實現(xiàn)
-
Context
中記錄它自己當前的狀態(tài)昭伸; -
Context
接收一個輸入動作沈贝,并將該輸入委托給當前所處State
處理; -
State
處理輸入勋乾,根據(jù)需要讓Context
躍遷到另一狀態(tài)宋下。
如果State
不保存狀態(tài)則可以是單例的,Java中辑莫,可以用enum
類型實現(xiàn)State
学歧。
6. Strategy 策略模式
作用
你有一個對象負責完成某件事情,但在不同時刻其使用的算法是不同的各吨,Strategy模式將可變的算法獨立并封裝枝笨,避免大量if條件判斷,并方便替換和擴展揭蜒。
Strategy
封裝了 相同行為的不同實現(xiàn)
實現(xiàn)
Strategy
的實現(xiàn)通常依賴Context
的數(shù)據(jù)横浑,后者在調(diào)用前者的方法時需要將自己傳遞過去。
實際應用中屉更,經(jīng)常會發(fā)現(xiàn)不同的策略其算法骨架類似徙融,只有某些具體步驟不同,此時可以對Strategy
應用Template Method
模式瑰谜。
7. Template Method 模板方法
作用
將一個算法的通用骨架抽象到父類以避免代碼重復欺冀,而將一些可變的步驟延遲到子類,子類不用關(guān)心算法結(jié)構(gòu)萨脑,只需關(guān)注自己需要實現(xiàn)的特定步驟隐轩。
實現(xiàn)
這個沒什么好說的。
四. 設計原則
-
SRP原則 - 單一職責原則(Single Responsibility Principle)
每個類實現(xiàn)單一職責渤早,并且單一職責都有清楚明確的定義职车,有利于降低軟件的復雜性, 提高可讀性、可維護性和可擴展性悴灵。
軟件設計應遵守單一職責原則军援,將不同的職責封裝到不同的類或模塊中。
-
OCP法則 - 開放-關(guān)閉原則
一個類應當對擴展開放称勋,對修改關(guān)閉。即當有新的需求時涯竟,不是修改已有的類赡鲜,而是對已有的類進行擴展。
- 通過擴展已有軟件系統(tǒng)庐船,可以提供新的行為银酬,以滿足對軟件的新的需求,使變化中的軟件有一定的適應性和靈活性筐钟。
- 已有軟件模塊揩瞪,特別是最重要的抽象層模塊不能再修改,這使變化中的軟件系統(tǒng)有一定的穩(wěn)定性和延續(xù)性篓冲。
實現(xiàn)開閉原則的關(guān)鍵在于 分離不變和變化的部分李破,并對變化的部分進行合理的高層抽象,并讓不變的部分依賴該高層抽象壹将,這樣就能在不同的實現(xiàn)間切換嗤攻,或者擴展新的實現(xiàn)。很多設計模式都體現(xiàn)了這一點诽俯,比如策略模式
將算法抽象出來妇菱,模板方法
將不變的算法骨架與易變的需要自定義的步驟隔離,裝飾者模式
將不變的核心功能對象和易變的增強功能隔離等等暴区。
LSP法則 - 里氏替換原則(Liskov Substitution Principle)
把抽象接口和實現(xiàn)分離,子類必須能替換掉父類闯团,這個原則通常由語言保證。DIP法則 - 依賴倒置原則(Dependence Inversion Principle)
抽象不應當依賴于細節(jié)仙粱;細節(jié)應當依賴于抽象房交;要針對接口編程,不針對實現(xiàn)編程伐割。具體講就是要依賴于抽象涌萤,不要依賴于具體。
高層不直接依賴底層口猜,而是高層定義自己需要底層提供什么樣的接口负溪,底層負責實現(xiàn),這樣就可以隨意切換底層的具體實現(xiàn)而不用影響高層济炎,但底層反而要依賴高層公布的接口川抡,所以稱為“依賴倒置”。ISP原則 - 接口分離原則 (Interface Segregation Principle)
每一個接口應該是一種角色,不多不少崖堤,不干不該干的事侍咱,該干的事都要干。這類似編碼原則中的最小權(quán)限法則密幔。軟件設計不應出現(xiàn)龐大的接口楔脯,迫使客戶在使用時必須從一大堆它不需要的方法中尋找目的方法。這樣的接口應該按照不同客戶的需求被分離成若干小接口胯甩。-
LKP原則 - 最少知識原則(Least Knowledge Principle)
也稱為迪米特法則昧廷。原則的核心思想即一個對象應對其他對象有盡可能少的了解。
類應當只與自己的朋友交互偎箫。該原則的思想是木柬,將類對外部的了解盡量保持在一定范圍內(nèi),盡量減少類之間的交互淹办,從而降低各個組件間的耦合眉枕。
“朋友”的定義:
- 當前對象的屬性
- 當前對象所創(chuàng)建的對象
- 方法參數(shù)傳遞進來的參數(shù)
- 方法內(nèi)創(chuàng)建的對象
五. 參考與推薦
- 《大話設計模式》
- 《深入淺出設計模式》
- 《Java與模式》
- 《敏捷軟件開發(fā)原則、模式與實踐》
- 《設計模式--可復用面向?qū)ο筌浖幕A(chǔ)》
- 《設計模式精解》