美文网首页
关于依赖注入

关于依赖注入

作者: 貘鸣 | 来源:发表于2018-01-22 21:31 被阅读58次

    摘自 Spring In Action 一书,第一章第一节。

    DI (dependency injection)并非什么高深莫测的词,下面通过一些简单的例子,来看看到底 DI 是什么,以及它是如何在开发中起到关键作用的。

    1 DI 的实现原理

    现代的面相对象方法开发的程序,肯定都是由若干个类集合到一起构成的。这些类相互之间进行配合,从而实现预定的业务逻辑。

    在传统的开发观点下,每个类都是由自己来获得这些和自己一起协作的类的实例(也就是类自己创建或通过某种方式主动获取到它自己的依赖),但这样的代码存在的问题是高耦合,难测试。

    比如下面这段代码:

        internal interface IKnight
        {
            void embarkOnQuest();
        }
    
        internal class DamselRescuingKnight : IKnight
        {
            private RescueDamselQuest quest;
            DamselRescuingKnight()
            {
                this.quest = new RescueDamselQuest();
            }
    
            public void embarkOnQuest()
            {
                quest.embark();
            }
        }
    

    上面的这段代码中,DamselRescuingKnightRescueDamselQuest 就是紧耦合在一起的,同时这段代码也非常难于维护和测试。特别是当测试 embarkOnQuest 方法的时候,还需要同时去测试 embark 方法。

    简单来讲,就是这样的依赖生成和使用方式都是错误的。

    所以需要寻找一种手段,让代码低耦合,而 DI 就是这样的一种方式。

    在使用 DI 的情况下,可以将对象的依赖在该对象初始化的时候由第三方提供,而非由对象自己主动创建。

    下面就来看一个例子:

       internal class BraveKnight : IKnight
        {
            private IQuest quest;
    
            internal BraveKnight(IQuest quest)
            {
                this.quest = quest;
            }
    
            public void embarkOnQuest()
            {
                quest.embark();
            }
        }
    

    上述代码中,依赖是通过构造时注入的,此时注入的对象以接口类型来表示,从而形成模块边界,当前的 BraveKnight 不再依赖任何的实现,而是依赖于接口抽象,从而实现低耦合。

    这样的代码在单元测试的时候也非常方便,由于依赖于接口,从而可以对实现进行灵活替换。

    下面为了注入 IQuest 对象,首先来提供一个 IQuest 的实现类 SlayDragonQuest:

        internal class SlayDragonQuest : IQuest
        {
            public void embark()
            {
                Console.WriteLine("Embarking on quest to slay the dragon!");
            }
        }
    

    那如何将这个 IQuest 实现类注入到 BraveKnight 中呢?

    这里就需要一个概念,即 wiring 了。在 Spring 中通过 XML 配置的方式将依赖实现方和依赖需求方进行绑定,而在其他地方没有这样的配置机制的情况下,就需要其他的措施来对依赖自动进行注入了。这里需要去寻找一些依赖注入的手段。

    在没有依赖注入工具帮助的前提下,可以手动在需要建立对象的时候指定依赖,而依赖的创建就是第三方完成的。

    在日常编程的时候,首先第一个习惯就是把依赖由依赖具体实现变为依赖接口。SOLID:单一职责,开放封闭,里式替换,依赖倒置,迪米特。其中的依赖倒置就是说的依赖抽象,而非依赖具体实现,而依赖倒置的一种实现方式就是采用依赖注入的手段。

    最后,现在写代码的目标就是先达到 SOLID,然后往整洁流派迈进,慢慢地提高在架构上的功力,最后再求融会贯通!

    相关文章

      网友评论

          本文标题:关于依赖注入

          本文链接:https://www.haomeiwen.com/subject/ezuraxtx.html