1.單例模式:
實現(xiàn)方式:
a.將被實現(xiàn)的類的構造方法設計成private的。
b.添加此類引用的靜態(tài)成員變量,并為其實例化。
c.在被實現(xiàn)的類中提供公共的CreateInstance函數(shù),返回實例化的此類,就是b中的靜態(tài)成員變量。
應用場景:
優(yōu)點:
1.在單例模式中,活動的單例只有一個實例,對單例類的所有實例化得到的都是相同的一個實例。這樣就防止其它對象對自己的實例化,確保所有的對象都訪問一個實例
2.單例模式具有一定的伸縮性,類自己來控制實例化進程,類就在改變實例化進程上有相應的伸縮性。
3.提供了對唯一實例的受控訪問。
4.由于在系統(tǒng)內(nèi)存中只存在一個對象,因此可以節(jié)約系統(tǒng)資源,當需要頻繁創(chuàng)建和銷毀的對象時單例模式無疑可以提高系統(tǒng)的性能。
5.允許可變數(shù)目的實例。
6.避免對共享資源的多重占用。
缺點:
1.不適用于變化的對象,如果同一類型的對象總是要在不同的用例場景發(fā)生變化,單例就會引起數(shù)據(jù)的錯誤,不能保存彼此的狀態(tài)。
2.由于單利模式中沒有抽象層,因此單例類的擴展有很大的困難。
3.單例類的職責過重,在一定程度上違背了“單一職責原則”。
4.濫用單例將帶來一些負面問題,如為了節(jié)省資源將數(shù)據(jù)庫連接池對象設計為的單例類,可能會導致共享連接池對象的程序過多而出現(xiàn)連接池溢出;如果實例化的對象長時間不被利用,系統(tǒng)會認為是垃圾而被回收,這將導致對象狀態(tài)的丟失。
使用注意事項:
1.使用時不能用反射模式創(chuàng)建單例,否則會實例化一個新的對象
2.使用懶單例模式時注意線程安全問題
3.單例模式和懶單例模式構造方法都是私有的,因而是不能被繼承的,有些單例模式可以被繼承(如登記式模式.
適用場景:
單例模式只允許創(chuàng)建一個對象,因此節(jié)省內(nèi)存,加快對象訪問速度,因此對象需要被公用的場合適合使用,如多個模塊使用同一個數(shù)據(jù)源連接對象等等。如:
1.需要頻繁實例化然后銷毀的對象。
2.創(chuàng)建對象時耗時過多或者耗資源過多,但又經(jīng)常用到的對象。
3.有狀態(tài)的工具類對象。
4.頻繁訪問數(shù)據(jù)庫或文件的對象。
以下都是單例模式的經(jīng)典使用場景:
1.資源共享的情況下,避免由于資源操作時導致的性能或損耗等。如上述中的日志文件,應用配置。
2.控制資源的情況下,方便資源之間的互相通信。如線程池等。
應用場景舉例:
1.外部資源:每臺計算機有若干個打印機,但只能有一個PrinterSpooler,以避免兩個打印作業(yè)同時輸出到打印機。內(nèi)部資源:大多數(shù)軟件都有一個(或多個)屬性文件存放系統(tǒng)配置,這樣的系統(tǒng)應該有一個對象管理這些屬性文件
2.Windows的TaskManager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想想看,是不是呢,你能打開兩個windowstaskmanager嗎?不信你自己試試看哦~
3.windows的RecycleBin(回收站)也是典型的單例應用。在整個系統(tǒng)運行過程中,回收站一直維護著僅有的一個實例。
4.網(wǎng)站的計數(shù)器,一般也是采用單例模式實現(xiàn),否則難以同步。
5.應用程序的日志應用,一般都何用單例模式實現(xiàn),這一般是由于共享的日志文件一直處于打開狀態(tài),因為只能有一個實例去操作,否則內(nèi)容不好追加。
6.Web應用的配置對象的讀取,一般也應用單例模式,這個是由于配置文件是共享的資源。
7.數(shù)據(jù)庫連接池的設計一般也是采用單例模式,因為數(shù)據(jù)庫連接是一種數(shù)據(jù)庫資源。數(shù)據(jù)庫軟件系統(tǒng)中使用數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關閉數(shù)據(jù)庫連接所引起的效率損耗,這種效率上的損耗還是非常昂貴的,因為何用單例模式來維護,就可以大大降低這種損耗。
8.多線程的線程池的設計一般也是采用單例模式,這是由于線程池要方便對池中的線程進行控制。
9.操作系統(tǒng)的文件系統(tǒng),也是大的單例模式實現(xiàn)的具體例子,一個操作系統(tǒng)只能有一個文件系統(tǒng)。
10.HttpApplication也是單位例的典型應用。熟悉ASP.Net(IIS)的整個請求生命周期的人應該知道HttpApplication也是單例模式,所有的HttpModule都共享一個HttpApplication實例.
2.策略模式:
實現(xiàn)方式:
a.提供公共接口或抽象類,定義需要使用的策略方法。(策略抽象類)
b.多個實現(xiàn)的策略抽象類的實現(xiàn)類。(策略實現(xiàn)類)
c.環(huán)境類,對多個實現(xiàn)類的封裝,提供接口類型的成員量,可以在客戶端中切換。
d.客戶端調(diào)用環(huán)境類進行不同策略的切換。
注:Jdk中的TreeSet和TreeMap的排序功能就是使用了策略模式。
優(yōu)點:
1.策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行為族。恰當使用繼承可以把公共的代碼移到父類里面,從而避免代碼重復。
2.使用策略模式可以避免使用多重條件(if-else.語句。多重條件語句不易維護,它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起,統(tǒng)統(tǒng)列在一個多重條件語句里面,比使用繼承的辦法還要原始和落后。
缺點:
1.客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。這就意味著客戶端必須理解這些算法的區(qū)別,以便適時選擇恰當?shù)乃惴?。換言之,策略模式只適用于客戶端知道算法或行為的情況。
2.由于策略模式把每個具體的策略實現(xiàn)都單獨封裝成為類,如果備選的策略很多的話,那么對象的數(shù)目就會很可觀。
3.代理模式:(一)靜態(tài)代理
實現(xiàn)方式:
a.為真實類和代理類提供的公共接口或抽象類。(租房)
b.真實類,具體實現(xiàn)邏輯,實現(xiàn)或繼承a。(房主向外租房)
c.代理類,實現(xiàn)或繼承a,有對b的引用,調(diào)用真實類的具體實現(xiàn)。(中介)
d.客戶端,調(diào)用代理類實現(xiàn)對真實類的調(diào)用。(租客租房)
(二)動態(tài)代理
實現(xiàn)方式:
a.公共的接口(必須是接口,因為Proxy類的newproxyinstance方法的第二參數(shù)必須是個接口類型的Class)
b.多個真實類,具體實現(xiàn)的業(yè)務邏輯。
c.代理類,實現(xiàn)InvocationHandler接口,提供Object成員變量,和Set方法,便于客戶端切換。
d.客戶端,獲得代理類的實例,為object實例賦值,調(diào)用Proxy.newproxyinstance方法在程序運行時生成繼承公共接口的實例,調(diào)用相應方法,此時方法的執(zhí)行由代理類實現(xiàn)的Invoke方法接管。
jdk動態(tài)代理使用的局限性:
通過反射類Proxy和InvocationHandler回調(diào)接口實現(xiàn)的jdk動態(tài)代理,要求委托類必須實現(xiàn)一個接口,但事實上并不是所有類都有接口,對于沒有實現(xiàn)接口的類,便無法使用該方方式實現(xiàn)動態(tài)代理。
4.觀察者模式:
觀察者模式是對象的行為模式,又叫發(fā)布-訂閱(Publish/Subscribe.模式、模型-視圖(Model/View.模式、源-監(jiān)聽器(Source/Listener.模式或從屬者(Dependents.模式。
實現(xiàn)方式:
a.角色抽象類(提供對觀察者的添加,刪除和通知功能)。
b.角色具體類,實現(xiàn)a,維護一個c的集合(對角色抽象類的實現(xiàn))。
c.觀察者抽象類(被角色通知后實現(xiàn)的方法)。
d.觀察者實現(xiàn)類,實現(xiàn)c(多個)。
注:JDK提供了對觀察者模式的支持,使用Observable類和Observer接口
兩種模型(推模型和拉模型):
■推模型是假定主題對象知道觀察者需要的數(shù)據(jù);而拉模型是主題對象不知道觀察者具體需要什么數(shù)據(jù),沒有辦法的情況下,干脆把自身傳遞給觀察者,讓觀察者自己去按需要取值。
■推模型可能會使得觀察者對象難以復用,因為觀察者的update()方法是按需要定義的參數(shù),可能無法兼顧沒有考慮到的使用情況。這就意味著出現(xiàn)新情況的時候,就可能提供新的update()方法,或者是干脆重新實現(xiàn)觀察者;而拉模型就不會造成這樣的情況,因為拉模型下,update()方法的參數(shù)是主題對象本身,這基本上是主題對象能傳遞的最大數(shù)據(jù)集合了,基本上可以適應各種情況的需要。
5.裝飾模式:
實現(xiàn)方式:
a.抽象的被裝飾角色(所有的角色都要直接或間接的實現(xiàn)本角色)
b.具體的被裝飾角色,實現(xiàn)或繼承a(被功能擴展的角色)
c.裝飾角色,實現(xiàn)或繼承a(本類有對a的引用,所有的具體裝飾角色都需要繼承這個角色)
d.多個具體修飾角色,繼承c(對被裝飾角色的功能擴展,可以任意搭配使用)
意圖:
動態(tài)地給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。該模式以對客戶端透明的方式擴展對象的功能。
適用環(huán)境:
1.在不影響其他對象的情況下,以動態(tài)、透明的方式給單個對象添加職責。
2.處理那些可以撤消的職責。
3.當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
6.適配器模式:
適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
1.類適配器(子類繼承方式)
實現(xiàn)方式:
a.目標抽象角色(定義客戶要用的接口)
b.適配器(實現(xiàn)a繼承c,作為一個轉換器被客戶調(diào)用)
c.待適配器(真正需要被調(diào)用的)
d.客戶端(借用a的實例調(diào)用c的方法)
2.對象適配器(對象的組合方式)
實現(xiàn)方式:
a.目標抽象角色(定義客戶要用的接口)
b.適配器(實現(xiàn)a,維護一個c的引用,作為一個轉換器被d調(diào)用)
c.待適配器(真正需要被調(diào)用的)
d.客戶端(此類,借用a類的實例調(diào)用c類的方法,類似靜態(tài)代理,但是解決的問題不同)
3.缺省的方式
實現(xiàn)方式:
a.抽象接口
b.實現(xiàn)a的適配器類(空實現(xiàn))
c.客戶端,繼承b,調(diào)用b中的方法,不必直接實現(xiàn)a(直接實現(xiàn)a需要實現(xiàn)a中的所有的方法)
優(yōu)點:
1.更好的復用性
系統(tǒng)需要使用現(xiàn)有的類,而此類的接口不符合系統(tǒng)的需要。那么通過適配器模式就可以讓這些功能得到更好的復用。
2.更好的擴展性
在實現(xiàn)適配器功能的時候,可以調(diào)用自己開發(fā)的功能,從而自然地擴展系統(tǒng)的功能。
?
缺點:
過多的使用適配器,會讓系統(tǒng)非常零亂,不易整體進行把握。比如,明明看到調(diào)用的是A接口,其實內(nèi)部被適配成了B接口的實現(xiàn),一個系統(tǒng)如果太多出現(xiàn)這種情況,無異于一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統(tǒng)進行重構。
7.命令模式
將一個請求封裝為一個對象,從而可用不同的請求對客戶進行參數(shù)化;對請求排隊或記錄日志,以及支持可撤銷的操作
將“發(fā)出請求的對象”和”接收與執(zhí)行這些請求的對象”分隔開來。
實現(xiàn)方式:
a.抽象的命令角色,如:菜單(規(guī)定可以點哪些菜)
b.具體的命令角色(實現(xiàn)a維護一個對c的引用),如:訂單(已點的菜)
c.接收者(具體執(zhí)行命令的角色),實際操作時,很常見使用"聰明"命令對象,也就是直接實現(xiàn)了請求,而不是將工作委托給c(弊端?)如:廚師接收訂單后做菜
d.調(diào)用者(維護一個對a的引用),如:服務員負責點菜并把訂單推給廚師
e.客戶端調(diào)用d發(fā)出命令進而執(zhí)行c的方法,如:顧客點餐
效果:
1)、command模式將調(diào)用操作的對象和實現(xiàn)該操作的對象解耦
2)、可以將多個命令裝配成一個復合命令,復合命令是Composite模式的一個實例
3)、增加新的command很容易,無需改變已有的類
適用性:
1)、抽象出待執(zhí)行的動作以參數(shù)化某對象
2)、在不同的時刻指定、排列和執(zhí)行請求。如請求隊列
3)、支持取消操作
4)、支持修改日志
5)、用構建在原語操作上的高層操作構造一個系統(tǒng)。支持事物
8.組合模式
將對象組合成樹形結構以表示“部分整體”的層次結構。組合模式使得用戶對單個對象和復雜對象的使用具有一致性。
實現(xiàn)方式:
a.抽象的構件接口(規(guī)范執(zhí)行的方法),b及c都需實現(xiàn)此接口,如:Junit中的Test接口
b.葉部件(實現(xiàn)a,最小的執(zhí)行單位),如:Junit中我們所編寫的測試用例
c.組合類(實現(xiàn)a并維護一個a的集合[多個b的組合]),如:Junit中的TestSuite
d.客戶端可以隨意的將b和c進行組合,進行調(diào)用
什么情況下使用組合模式:
當發(fā)現(xiàn)需求中是體現(xiàn)部分與整體層次結構時,以及你希望用戶可以忽略組合對象與單個對象的不同,統(tǒng)一地使用組合結構中的所有對象時,就應該考慮組合模式了。
9.簡單工廠模式
就是建立一個工廠類,對實現(xiàn)了同一接口的一些類進行實例的創(chuàng)建。簡單工廠模式的實質(zhì)是由一個工廠類根據(jù)傳入的參數(shù),動態(tài)決定應該創(chuàng)建哪一個產(chǎn)品類(這些產(chǎn)品類繼承自一個父類或接口)的實例。
實現(xiàn)方式:
a.抽象產(chǎn)品類(也可以是接口)
b.多個具體的產(chǎn)品類
c.工廠類(包括創(chuàng)建a的實例的方法)
優(yōu)點:
工廠類是整個模式的關鍵.包含了必要的邏輯判斷,根據(jù)外界給定的信息,決定究竟應該創(chuàng)建哪個具體類的對象.通過使用工廠類,外界可以從直接創(chuàng)建具體產(chǎn)品對象的尷尬局面擺脫出來,僅僅需要負責“消費”對象就可以了。而不必管這些對象究竟如何創(chuàng)建及如何組織的.明確了各自的職責和權利,有利于整個軟件體系結構的優(yōu)化。
缺點:
由于工廠類集中了所有實例的創(chuàng)建邏輯,違反了高內(nèi)聚責任分配原則,將全部創(chuàng)建邏輯集中到了一個工廠類中;它所能創(chuàng)建的類只能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類了。當系統(tǒng)中的具體產(chǎn)品類不斷增多時候,可能會出現(xiàn)要求工廠類根據(jù)不同條件創(chuàng)建不同實例的需求.這種對條件的判斷和對具體產(chǎn)品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統(tǒng)的維護和擴展非常不利;
10.模板方法模式
實現(xiàn)方式:
a.父類模板類(規(guī)定要執(zhí)行的方法和順序,只關心方法的定義及順序,不關心方法實現(xiàn))
b.子類實現(xiàn)類(實現(xiàn)a規(guī)定要執(zhí)行的方法,只關心方法實現(xiàn),不關心調(diào)用順序)
優(yōu)點:
1.封裝不變部分,擴展可變部分:把認為不變部分的算法封裝到父類實現(xiàn),可變部分則可以通過繼承來實現(xiàn),很容易擴展。
2.提取公共部分代碼,便于維護。
3.行為由父類控制,由子類實現(xiàn)。
缺點:
模板方法模式顛倒了我們平常的設計習慣:抽象類負責聲明最抽象、最一般的事物屬性和方法,實現(xiàn)類實現(xiàn)具體的事物屬性和方法。在復雜的項目中可能會帶來代碼閱讀的難度。