按需分配,共創和諧社會的鑰匙:依賴注入


  滾滾長江東逝水,浪花淘盡英雄。一代代的先輩的努力才造就我們的今天,細數歷史的進步會讓人深感受益良多。

  本系列文將着重比對歷史的發展和控制反轉產生的關系,此文為引導文,主要介紹依賴注入,之后會有一系列文章來分析各種實現方式,希望大家拍磚。

 

  

  

[小九的學堂,致力於以平凡的語言描述不平凡的技術。如要轉載,請注明來源:小九的學堂。cnblogs.com/xfuture]

 

  歷史的發展

  遠古母系氏族,每個人都是一個獨立的個體,需要什么工具就需要自己去打磨一件工具,自己需要了解所有的流程才能生存。比如打獵,從前期准備繩索,尖木,到中期做陷阱,后期收成,都需要了解的非常透徹。對應編程中便是new 繩索()new 尖木()new 陷阱()new X()。實例化所有需要的資源,然后再進行邏輯流程。

  人類逐漸在進步,工業革命的來襲,改變了整個社會的結構。人再不需要了解所有的流程,只需要去一個工廠或者采購平台,輸入自己想要的東西,便能得到。對應編程中便是工廠模式,需要一個靜態工廠類,一個抽象產品類型的類,一個你想拿到的可以具象化的產品類,從此便進入了全民淘寶年代,需要什么購買什么。

  當你為了修一個頂樓的燈泡購買了梯子,但當修好后,如何處理這個梯子便成了難題,扔掉不舍,不扔去賣二手又很麻煩。這時候就需要我們的主角:和諧社會登場了!主張不鋪張不浪費,這便是一種回收機制,你需要它只需要說一聲,秒秒鍾就到你手里,你也不需要知道他來自哪里。不需要了你也不用管,我直接秒秒鍾再變走。是不是有一種魔術的感覺?這便是依賴注入!依賴注入解除了對象和對象的依賴關系,需要其他對象時候,會有外部直接注入給你,而你不需要。對象符合OCP原則(對外擴展開放,對修改關閉), 容器負責所有關系匹配。在此層,容器便是這個社會的規則,而對象只需要關心自己所完成的一部分就好。輕松愜意!

 

  依賴注入:Dependency Injection

  從起始的new,new,new到后來的多態,面向接口編程,匹配協議規定的規則,直到按需分配,外部注入的控制反轉依賴注入。實際上就和人類進步的邏輯是一樣的,目的就是為了讓工作分配的更明確,更效率,彼此依賴越來越少。依賴注入隔離了變化,讓之不會影響不變的對象部分。依賴注入實際上是很多原則的合體。多態使類不再依賴其他服務類,只需要接口,實現了OCP(對外擴展開放,對修改關閉)。為了不需要實例具體的服務類,就需要定義注入點(接口),容器來進行服務,實現注入。

 

  

  注入容器:Container

  依賴注入需要一個容器來儲存所有的資源,根據你的需要按需分配,進行注入。依賴注入還有個名字叫控制反轉,就是大家經常說的IOC。

  輕量級的有Unity Container, Autofac, Spring等,重量級有EJB, 還有游離在輕重之間的是JBoss等。之后系列文會詳細介紹幾種常用的,比如container,autofac,ejb。

  由於本人經常使用prism,orchard,故而會更詳細介紹container和autofac,也會把使用心得更多分享給大家。

 

  基本技術:反射

  

  IOC是工廠模式的升華,最基本的技術是“反射”。根據一個注入的匹配表或者規則,來進行靈活的注入。

 

  注入規則:

  

    1. xml來進行配置。

    Spring使用xml文件來進行beans的匹配。好處在於完全抽離了代碼層次,在xml進行配置,用字符串來進行反射注入。但壞處就是xml的維護,需要一個很好的IDE

  2.Assembly注入,class,interface匹配。在.NET里個人比較喜歡這種。

    var builder = new ContainerBuilder();
      builder.RegisterGeneric(typeof(Dal<>)).As(typeof(Idal<>)).InstancePerDependency();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency();
builder.Register(c=>new PersionBll((IRepository<Persion>).Resolve(typeof(IRepository<Persion>))));
builder.Register(c => new CustomBll((IRepository<Custom>)
    c.Resolve(typeof(IRepository<Custom>))));
    var container = builder.Build()
    

這里只大概列出一些例子。具體會有詳細介紹在系列篇后篇。

  注入方法:

  1.接口注入,2.構造函數注入,3.屬性注入

 

 

  開碟小菜(不使用容器,僅使用接口和實現類來展現依賴注入的基本邏輯)

  場景:家里很多電視,有時候這個可以用,有時候那個可以用。希望能在替換的時候,個人這邊是不需要更改什么的,依然是拿起遙控器就能看電視,不管是哪個。

  解決方案:(接口注入)

// 創建實現看電視功能的接口
public interface ITvProvider
{
        void WatchTv();
}

// 創建一個TV的實體類,繼承ITvProvider,實現其WatchTv方法。
public class KonkaTv:ITvProvider
{
         public void WatchTv()
         {
                 // 實現看康佳電視功能的邏輯代碼
         }
}

// 創建一個注入用的接口,實現類似容器/XML鏈接對象匹配的功能
public interface ITvInjecter
{
        void InjectTv(ITvProvider tvProvider);
}

// 創建一個看電視的控件,繼承ITvInjecter(容器時則是繼承類似IDepency這種可以拿到容器, 這里是不使用容器的方法)
public Control WatchTvControl:ITvInjecter
{
        private ITvProvider _tvProvider;

        // 若使用容器,則在構造函數里既可以實現注入,不用手工來寫注入方法。
        public void InjectTv(ITvProvider tvProvider)
        {
              _tvProvider = tvProvider
        }

        public WatchTvControl()
        {
             // 注入完成后便可以使用其watchtv方法
              _tvProvider.WatchTv();
        }
}

// 主程序,代碼層次實現注入並調用
public partial class App
{
     private void Application_Startup(object sender, StartupEventArgs e)  
        {
               ITvProvider tvProvider = new KonkaTv();
               WatchTvControl watchTvControl = new WatchTvControl();
               watchTvControl.InjectTv(tvProvider);
        }  
}
 
       

通過這樣的調用,就可是實現解耦和。當你想要更換Tv的時候只需要在主程序中更換就好,其余功能模塊則完全不需要更改。(容器則是注入其他Tv實體類就好) 

希望大家點贊關注和拍磚。個人是在做.net,比較擅長使用prism和orchard(非常宏大的設計模式集合的CMS框架,分布式網絡的福音),對依賴注入的好處感受也比較深刻一些.總之希望大家持續關注。我也會努力提升自己來寫出更好文章豐富這個小學堂的,希望每項技術都能映射到現實的例子,其實編程就是人生啊!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM