前篇回顧:前篇蟲子介紹了3個"池"中線程池的相關問題,不過謬論的可能性比較大 僅代表蟲子的個人觀點了 - -
本章結合執行個體給大家闡述下依賴注入與控制反轉可以給自己的項目帶來哪些優缺點。
先回顧下OO的一些設計原則:
開放封閉原則 軟體實體(類、子產品、函數等)應該是可以開展的,但是不可修改。
依賴倒置原則 抽象不應該依賴于細節。細節應該依賴于抽象。
接口隔離原則 不應該強迫客戶依賴于它們不用的方法。接口屬于客戶,不屬于它所在的類層次結構。
單一職責原則 就一個類而言,應該僅有一個引起它變化的原因。
......
随着面向對象分析與設計的發展,一個良好的設計,核心原則之一就是将變化隔離,使得變化部分發生變化時,不變部分不受影響(這也是OCP的目的)。為了做到這一點,要利用面向對象中的多态性,使用多态性後,客戶類不再直接依賴服務類,而是依賴于一個抽象的接口,這樣,客戶類就不能在内部直接執行個體化具體的服務類。
但是,客戶類在運作中又客觀需要具體的服務類提供服務,因為接口是不能執行個體化去提供服務的。就産生了“客戶類不準執行個體化具體服務類”和“客戶類需要具體服務類”這樣一對沖突。
依賴注入(Dependency Injection),是這樣一個過程:由于某客戶類隻依賴于服務類的一個接口,而不依賴于具體服務類,是以客戶類隻定義一個注入點。在程式運作過程中, 客戶類不直接執行個體化具體服務類執行個體,而是客戶類的運作上下文環境或專門元件負責執行個體化服務類,然後将其注入到客戶類中,保證客戶類的正常運作。
OK,概念性的東西已經占了不少篇幅了,下面蟲子結合一個低侵入性、通過配置檔案實作注入的執行個體 來看看實際的效果如何。
BaseClass.cs中提供基本的功能類和接口定義
<a href="http://blog.51cto.com/dubing/712453#">?</a>
1
2
3
4
5
6
7
8
<code>public</code> <code>interface</code> <code>IocObj</code>
<code>{</code>
<code> </code><code>TestObj GetTestObj(</code><code>string</code> <code>QQName);</code>
<code>}</code>
<code>public</code> <code>class</code> <code>TestObj</code>
<code> </code><code>public</code> <code>string</code> <code>QQ { </code><code>get</code><code>; </code><code>set</code><code>; }</code>
Content01.cs中實作一種功能
<code>public</code> <code>class</code> <code>Con1 : IocObj</code>
<code> </code><code>{</code>
<code> </code><code>public</code> <code>TestObj GetTestObj(</code><code>string</code> <code>QQName)</code>
<code> </code><code>{</code>
<code> </code><code>return</code> <code>new</code> <code>TestObj { QQ = QQName+</code><code>" 這是con1"</code> <code>};</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
Content02.cs中實作另一種功能
<code>public</code> <code>class</code> <code>Con2 : IocObj</code>
<code> </code><code>{</code>
<code> </code><code>public</code> <code>TestObj GetTestObj(</code><code>string</code> <code>QQName)</code>
<code> </code><code>{</code>
<code> </code><code>return</code> <code>new</code> <code>TestObj { QQ = QQName + </code><code>" 這是con2"</code> <code>};</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
下面我們就看看如何進行依賴注入,關于分析xml以及反射等細節處理本篇先暫不介紹,主要介紹下依賴注入帶來的影響與效果
控制台程式
<code>static</code> <code>void</code> <code>Main(</code><code>string</code><code>[] args)</code>
<code> </code><code>var</code> <code>IOCService = ServiceLocator.GetService<IocObj>();</code>
<code> </code><code>var</code> <code>TestObj = IOCService.GetTestObj(</code><code>"1326194996"</code><code>);</code>
<code> </code><code>Console.WriteLine(</code><code>"目前使用者的qq為"</code> <code>+ TestObj.QQ);</code>
<code> </code><code>Console.ReadLine();</code>
配置檔案
9
10
11
<code><?xml version=</code><code>"1.0"</code> <code>encoding=</code><code>"utf-8"</code> <code>?></code>
<code><configuration></code>
<code> </code><code><configSections></code>
<code> </code><code><section name=</code><code>"ChongZi"</code> <code>type=</code><code>"ChongZi.Config.ConfigSectionHandler, ChongZi.IOC"</code> <code>/></code>
<code> </code><code></configSections></code>
<code> </code><code><ChongZi></code>
<code> </code><code><objects> </code>
<code> </code><code><add name=</code><code>"Content01"</code> <code>type=</code><code>"BaseClass.IocObj, BaseClass"</code> <code>mapTo=</code><code>"Content01.Con1, Content01"</code> <code>/></code>
<code> </code><code></objects></code>
<code> </code><code></ChongZi></code>
<code></configuration></code>
看結果
修改下配置檔案
<code> </code><code><objects> </code>
<code> </code><code><add name=</code><code>"UserServiceLocal"</code> <code>type=</code><code>"BaseClass.IocObj, BaseClass"</code> <code>mapTo=</code><code>"Content02.Con2, Content02"</code> <code>/></code>
再看結果
結果一目了然,執行個體也很簡單。但是依賴注入給項目帶來的意義還是很大的。而且通過一些RMI元件我們還可以注入遠端對象、服務。對于分布式開發也提供了積極的解決方案。不過既然是抓蟲系列,當然也要談談這種模式的缺點,首先對象生成的步驟變複雜,其次,涉及反射對性能上也是個損耗。至于大家的項目中是否需要依賴注入和控制反轉,取決于項目對可維護性以及可擴充性的需求。
本文轉自 熬夜的蟲子 51CTO部落格,原文連結:http://blog.51cto.com/dubing/712453