按需分配,共创和谐社会的钥匙:依赖注入

  滚滚长江东逝水,浪花淘尽英雄。一代代的先辈的努力才造就我们的今天,细数历史的进步会让人深感受益良多。

  本系列文将着重比对历史的发展和控制反转产生的关系,此文为引导文,主要介绍依赖注入,之后会有一系列文章来分析各种实现方式,希望大家拍砖。

 

  

  

[小九的学堂,致力于以平凡的语言描述不平凡的技术。如要转载,请注明来源:小九的学堂。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框架,分布式网络的福音),对依赖注入的好处感受也比较深刻一些.总之希望大家持续关注。我也会努力提升自己来写出更好文章丰富这个小学堂的,希望每项技术都能映射到现实的例子,其实编程就是人生啊!

 

 

posted @ 2014-04-23 13:13  techlead_krischang  阅读(2436)  评论(9编辑  收藏  举报