• 深入理解DIP、IoC、DI以及IoC容器(转载)


     《转载的这个up的其他的文章也很nice》

    这几个词第一眼看,懵逼,第二眼看,更特么懵逼、、、、、

    面向对象设计(OOD)有助于我们开发出高性能、易扩展以及易复用的程序。

    其中,OOD有一个重要的思想那就是依赖倒置原则(DIP)(啥特么意思,倒置?瓶子倒置的意思吗),并由此引申出IoC、DI以及Ioc容器等概念。

    通过本文我们将一起学习这些概念,并理清他们之间微妙的关系。

    依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)。

    控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)。

    依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)。

    IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)

    依赖倒置原则(DIP)(我特么读着都瘪嘴)

    相信大部分取过钱的朋友都深有感触,只要有一张卡,随便到哪一家银行的ATM都能取钱。

    在这个场景中,ATM相当于高层模块,而银行卡相当于低层模块。ATM定义了一个插口(接口),供所有的银行卡插入使用。

    也就是说,ATM不依赖于具体的哪种银行卡。它只需定义好银行卡的规格参数(接口),所有实现了这种规格参数的银行卡都能在ATM上使用。现实生活如此,软件开发更是如此。

    依赖倒置原则,它转换了依赖,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口

    通俗的讲,就是高层模块定义接口,低层模块负责实现。

    其实再通俗的说就是:想到依赖倒置:就想到高层与底层(高层是接口,底层是实现接口;接口才不管谁实现了它,底层只要满足高层的参数需要就能实现高层的方法。)

    感觉总而言之:依赖倒置就是高层是接口,底层是继承接口的各种方法;好处也就是接口的好处.

    控制反转(IoC)

    IoC则是一种 软件设计模式,它告诉你应该如何做,来解除相互依赖模块的耦合

    控制反转(IoC),它为相互依赖的组件提供抽象(握草,提供抽象,抽象???)

    将依赖(低层模块)对象的获得交给第三方(系统)来控制即依赖对象不在被依赖模块的类中直接通过new来获取。//是不是就是说,"底层"的类,不直接继承接口,而是底层-->第三方-->高层接口

    在图1的例子我们可以看到,ATM它自身并没有插入具体的银行卡(工行卡、农行卡等等),而是将插卡工作交给人来控制(人就是第三方啦),即我们来决定将插入什么样的银行卡来取钱。

    同样我们也通过软件开发过程中场景来加深理解。

    做过电商网站的朋友都会面临这样一个问题:订单入库。假设系统设计初期,用的是SQL Server数据库。通常我们会定义一个SqlServerDal类,用于数据库的读写。

    public class SqlServerDal
    {
         public void Add()
        {
            Console.WriteLine("在数据库中添加一条订单!");
        }
    }
    

      然后我们定义一个Order类,负责订单的逻辑处理。由于订单要入库,需要依赖于数据库的操作。因此在Order类中,我们需要定义SqlServerDal类的变量并初始化。

    public class Order
    {
            private readonly SqlServerDal dal = new SqlServerDal();//添加一个私有变量保存数据库操作的对象
     
             public void Add()
           {
               dal.Add();
           }
    }
    

      写个控制台来实现一下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace DIPTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Order order = new Order();
                order.Add();
     
                Console.Read();
            }
        }
    }
    

      

    OK,结果看起来挺不错的!正当你沾沾自喜的时候,这时BOSS过来了。“小刘啊,刚客户那边打电话过来说数据库要改成Access”,“对你来说,应当小CASE啦!”BOSS又补充道。带着自豪而又纠结的情绪,我们思考着修改代码的思路。

     由于换成了Access数据库,SqlServerDal类肯定用不了了。因此,我们需要新定义一个AccessDal类,负责Access数据库的操作。

    public class AccessDal
    {
        public void Add()
       {
           Console.WriteLine("在ACCESS数据库中添加一条记录!");
       }
    }
    

      然后,再看Order类中的代码。由于,Order类中直接引用了SqlServerDal类的对象。所以还需要修改引用,换成AccessDal对象。

    显然,这不是一个良好的设计,组件之间高度耦合,可扩展性较差,它违背了DIP原则。

    高层模块Order类不应该依赖于低层模块SqlServerDal,AccessDal,两者应该依赖于抽象。

    那么我们是否可以通过IoC来优化代码呢?答案是肯定的。IoC有2种常见的实现方式:依赖注入和服务定位。

    其中,依赖注入使用最为广泛。下面我们将深入理解依赖注入(DI),并学会使用。

    依赖注入(DI)

    先copy到这吧。。。

  • 相关阅读:
    [BZOJ1578] [Usaco2009 Feb]Stock Market 股票市场(DP)
    [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))
    [BZOJ1575] [Usaco2009 Jan]气象牛Baric(DP)
    [BZOJ1574] [Usaco2009 Jan]地震损坏Damage(贪心 + dfs)
    [BZOJ1572] [Usaco2009 Open]工作安排Job(贪心 + 堆)
    [luoguP2862] [USACO06JAN]把牛Corral the Cows(二分 + 乱搞)
    [luoguP3668] [USACO17OPEN]Modern Art 2 现代艺术2(栈)
    [luoguP3608] [USACO17JAN]Balanced Photo平衡的照片(树状数组 + 离散化)
    [luoguP3110] [USACO14DEC]驮运Piggy Back(SPFA || BFS)
    [BZOJ2342] [Shoi2011]双倍回文(manacher)
  • 原文地址:https://www.cnblogs.com/ZkbFighting/p/9518321.html
Copyright © 2020-2023  润新知