抓蟲系列(五) 淺談依賴注入與控制反轉

前篇回顧:前篇蟲子介紹了3個"池"中線程池的相關問題,不過謬論的可能性比較大 僅代表蟲子的個人觀點了 - -

本章結合實例給大家闡述下依賴注入與控制反轉可以給自己的項目帶來哪些優缺點。

先回顧下OO的一些設計原則:

開放封閉原則  軟件實體(類、模塊、函數等)應該是可以開展的,但是不可修改。

依賴倒置原則 抽象不應該依賴於細節。細節應該依賴於抽象。

接口隔離原則 不應該強迫客戶依賴於它們不用的方法。接口屬於客戶,不屬於它所在的類層次結構。

單一職責原則 就一個類而言,應該僅有一個引起它變化的原因。

......

隨着面向對象分析與設計的發展,一個良好的設計,核心原則之一就是將變化隔離,使得變化部分發生變化時,不變部分不受影響(這也是OCP的目的)。爲了做到這一點,要利用面向對象中的多態性,使用多態性後,客戶類不再直接依賴服務類,而是依賴於一個抽象的接口,這樣,客戶類就不能在內部直接實例化具體的服務類。
但是,客戶類在運作中又客觀需要具體的服務類提供服務,因爲接口是不能實例化去提供服務的。就產生了“客戶類不準實例化具體服務類”和“客戶類需要具體服務類”這樣一對矛盾。
依賴注入(Dependency Injection),是這樣一個過程:由於某客戶類只依賴於服務類的一個接口,而不依賴於具體服務類,所以客戶類只定義一個注入點。在程序運行過程中, 客戶類不直接實例化具體服務類實例,而是客戶類的運行上下文環境或專門組件負責實例化服務類,然後將其注入到客戶類中,保證客戶類的正常運行。
OK,概念性的東西已經佔了不少篇幅了,下面蟲子結合一個低侵入性、通過配置文件實現注入的實例 來看看實際的效果如何。

 BaseClass.cs中提供基本的功能類和接口定義

public interface IocObj
{
      TestObj GetTestObj(string QQName);
}
public class TestObj
{
      public string QQ { get; set; }
}

 Content01.cs中實現一種功能

 public class Con1 : IocObj
    {
        public TestObj GetTestObj(string QQName)
        {
            return new TestObj { QQ = QQName+" 這是con1" };
        }
    }

  Content02.cs中實現另一種功能

public class Con2 : IocObj
    {
        public TestObj GetTestObj(string QQName)
        {
            return new TestObj { QQ = QQName + " 這是con2" };
        }
    }

下面我們就看看如何進行依賴注入,關於分析xml以及反射等細節處理本篇先暫不介紹,主要介紹下依賴注入帶來的影響與效果

控制檯程序

static void Main(string[] args)
        {
            var IOCService = ServiceLocator.GetService<IocObj>();
            var TestObj = IOCService.GetTestObj("1326194996");
            Console.WriteLine("當前用戶的qq爲" + TestObj.QQ);
            Console.ReadLine();
        }

配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="ChongZi" type="ChongZi.Config.ConfigSectionHandler, ChongZi.IOC" />
  </configSections>
  <ChongZi>
    <objects>     
      <add name="Content01" type="BaseClass.IocObj, BaseClass" mapTo="Content01.Con1, Content01" />
    </objects>
  </ChongZi>
</configuration>

看結果

 修改下配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="ChongZi" type="ChongZi.Config.ConfigSectionHandler, ChongZi.IOC" />
  </configSections>
  <ChongZi>
    <objects>      
      <add name="UserServiceLocal" type="BaseClass.IocObj, BaseClass" mapTo="Content02.Con2, Content02" />
    </objects>
  </ChongZi>
</configuration>

再看結果

結果一目瞭然,實例也很簡單。但是依賴注入給項目帶來的意義還是很大的。而且通過一些RMI組件我們還可以注入遠程對象、服務。對於分佈式開發也提供了積極的解決方案。不過既然是抓蟲系列,當然也要談談這種模式的缺點,首先對象生成的步驟變複雜,其次,涉及反射對性能上也是個損耗。至於大家的項目中是否需要依賴注入和控制反轉,取決於項目對可維護性以及可擴展性的需求。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章