物件建立的依賴

2021-08-26 02:00:04 字數 3270 閱讀 2540

關於依賴的哲學,最典型的違反莫過於物件建立的依賴。自物件導向的大旗樹立以來,對於物件建立話題的討論就從未停止。不管是工廠模式還是依賴注入,其核心的思想就只有乙個:如何更好地解耦物件建立的依賴關係。所以,在這一部分,我們就以物件建立為主線,來認識對於依賴關係的設計軌跡,分別論述一般的物件建立、工廠方式建立和依賴注入建立三種方式的實現、特點和區別。

1.典型的違反

一般而言,以new關鍵字進行物件建立,在.net世界裡是天經地義的事情。在本書7.1節「把new說透」中,就比較透徹地分析了new在物件建立時的作用和底層機制。對.net程式設計師而言,以new進行物件建立已經是習以為常的事情,大部分情況下這種方式並沒有任何問題。例如:

publicabstractclassanimal

publicabstractvoidshow();

publicclassdog:animal

publicoverridevoidshow()

console.writeline("thisisdog.");

publicclasscat:animal

publicoverridevoidshow()

console.writeline("thisiscat.");

publicclassnormalcreation

publicstaticvoidmain2()

animalanimal=newdog();

對animal物件而言,大部分情況下具體的dog類是相對穩定的,所以這種依賴很多時候是無害的。這也是我們習以為常的原因之一。

然而,誠如在本文開始對抽象和具體的概念進行分析的結論一樣,依賴於具體很多時候並不能有效地保證其穩定性的狀態。以本例而言,如果有新的bird、horse加入到動物園中來,管理員基於現有體系的管理勢必不能適應形式,因為所有建立而來的例項都是依賴於dog的。所以,普遍的物件建立方式,實際上是對dip原則的典型違反,高層animal的建立依賴於低層的dog,和普世的dip基本原則是違背的。

因此,dip並不是時時被oo所遵守,開發者要做的只是適度的把握。為了解決new方式建立物件的依賴違反問題,典型的解決思路是將建立的依賴由具體轉移為抽象,通常情況下有兩種方式來應對:工廠模式和依賴注入。

2.工廠模式

本文將視角拉回到wcf的ichannelfactory和各種channel的建立上,以此借用wcf架構中channel layer的設計思路,應用工廠模式進行物件建立的設計和擴充套件,來了解應用工廠模式進行物件建立依賴關係解除的實質和實現。注意

對於wcf中channel的概念可以參考相關的資料,在此你只需將其看成乙個簡單型別即可。

首先來了解一下channel的建立過程:

在示例中,irequestchannel例項通過ichannelfactory工廠來建立,因此關注工廠方式的建立焦點就著眼於ichannelfactory和irequestchannel上。實質上,在wcf channel layer中,channelfactory是建立和管理channel的工廠封裝,通過乙個個的channel factory來建立乙個個對應的channel例項,所有的channel factory必須繼承自ichannelfactory,其定義為:

publicinte***ceichannelfactory:ichannelfactory,icommunicationobject

tchannelcreatechannel(endpointaddressto);

tchannelcreatechannel(endpointaddressto,urivia);

通過型別引數tchannel來註冊建立例項的型別資訊,進而根據endpointaddress資訊來建立相應的物件例項。當然,wcf中的工廠模式應用,還有很多內容值得斟酌和學習。現有篇幅不可能實現完全類似的設計結構,借鑑於wcf的設計思路,對animal例項的建立進行一點改造,實現基於泛型的工廠模式建立設計,首先定義乙個物件建立的模板:

publicinte***ceianimalfacotry

tanimalcreate();

然後實現該模板的泛型工廠方法:

publicclassanimalfacotry:ianimalfacotrywheretanimal:tanimalbase,new()

publictanimalbasecreate()

returnnewtanimal();

其中型別引數tanimalbase代表了高層型別,而tanimal則代表了底層型別,其約定關係在where約束中有明確的定義,然後是乙個基於對工廠方法的封裝:

publicclassfacotrybuilder

publicstaticianimalfacotrybuild(stringtype)

if(type=="dog")

returnnewanimalfacotry();

elseif(type=="cat")

returnnewanimalfacotry();

returnnull;

最後,可以欣賞一下基於工廠方式的物件建立實現:

classprogram

staticvoidmain(stringargs)

ianimalfacotryfactory=facotrybuilder.build("cat");

animaldog=factory.create();

dog.show();

你看,物件建立的依賴關係已經由new式的具體依賴轉換為對於抽象和高層的依賴。在本例中,完全可以通過反射方式來消除if/else的執行時型別判定,從而徹底將這種依賴解除為可配置的靈活定製。這正是抽象工廠方式的偉大意義,其實在本例中完全可以將ianimalfacotry擴充套件為ianyfactory形式的靈活工廠,可以在型別引數中註冊任何型別的t***base和t***,從而實現功能更加強大的物件生成器,只不過需要更多的**和擴充套件,讀者可以就此進行自己的思考。

本文節選自《你必須知道的.net(第2版)》一書

圖書詳細資訊:

物件建立的依賴

物件建立的依賴 關於依賴的哲學,最典型的違反莫過於物件建立的依賴。自物件導向的大旗樹立以來,對於物件建立話題的討論就從未停止。不管是工廠模式還是依賴注入,其核心的思想就只有乙個 如何更好地解耦物件建立的依賴關係。所以,在這一部分,我們就以物件建立為主線,來認識對於依賴關係的設計軌跡,分別論述一般的物...

注入依賴物件

兩種註解注入依賴物件 autowired resource autowired 預設按型別裝配。resource預設按名稱裝配,當找不到與名稱匹配的bean才會按型別裝配。autowired private persondao persondao 用於欄位上 autowired public voi...

物件變數的依賴注入

訪問 b 通過例項化請求類來使用請求變數 request instance 返回乙個請求物件 完成了請求類的匯入並且獲取到了請求變數 c 依賴注入 將請求物件以方法引數的方式直接注入到當前操作中,將引數宣告為request型別,當我們使用該引數的時候會自動觸發例項化過程,建立request物件 這樣...