依赖注入那些事儿【2】 之 探究依赖注入

2.1 故事的启迪

我们现在静下心来,再回味一下刚才的故事。因为,这个故事里面隐藏着依赖注入的出现原因。我说过不只一次,想真正认清一个事物,不能只看“它是什么?什么样子?”,而应该先弄清楚“它是怎么来的?是什么样的需求和背景促使了它的诞生?它被创造出来是做什么用的?”。

回想上面的故事。刚开始,主要需求是一个打怪的功能。小李做了一个初步面向对象的设计:抽取领域场景中的实体(怪物、角色等),封装成类,并为各个类赋予属性与方法,最后通过类的交互完成打怪功能,这应该算是面向对象设计的初级阶段。

在小李的设计基础上,架构师小于指出了几点不足,如不符合OCP,职责划分不明确等等,并根据情况引入策略模式。这是更高层次的面向对象设计。其实就核心来说,小于只做了一件事:利用多态性,隔离变化。它清楚认识到,这个打怪功能中,有些业务逻辑是不变的,如角色攻击怪物,怪物减少HP,减到0怪物就会死;而变化的仅仅是不同的角色持有不同武器时,每次攻击的效用不一样。于是他的架构,本质就是把变化的部分和不变的部分隔离开,使得变化部分发生变化时,不变部分不受影响。

我们再仔细看看小于的设计图,这样设计后,有个基本的问题需要解决:现在Role不依赖具体武器,而仅仅依赖一个IAttackStrategy接口,接口是不能实例化的,虽然Role的Weapon成员类型定义为IAttackStrategy,但最终还是会被赋予一个实现了IAttackStrategy接口的具体武器,并且随着程序进展,一个角色会装备不同的武器,从而产生不同的效用。赋予武器的职责,在Demo中是放在了测试代码里。

这里,测试代码实例化一个具体的武器,并赋给Role的Weapon成员的过程,就是依赖注入!这里要清楚,依赖注入其实是一个过程的称谓!

2.2 正式定义依赖注入

下面,用稍微正式一点的语言,定义依赖注入产生的背景缘由和依赖注入的含义。在读的过程中,读者可以结合上面的例子进行理解。

依赖注入产生的背景:

随着面向对象分析与设计的发展,一个良好的设计,核心原则之一就是将变化隔离,使得变化部分发生变化时,不变部分不受影响(这也是OCP的目的)。为了做到这一点,要利用面向对象中的多态性,使用多态性后,客户类不再直接依赖服务类,而是依赖于一个抽象的接口,这样,客户类就不能在内部直接实例化具体的服务类。但是,客户类在运作中又客观需要具体的服务类提供服务,因为接口是不能实例化去提供服务的。就产生了“客户类不准实例化具体服务类”和“客户类需要具体服务类”这样一对矛盾。为了解决这个矛盾,开发人员提出了一种模式:客户类(如上例中的Role)定义一个注入点(Public成员Weapon),用于服务类(实现IAttackStrategy的具体类,如WoodSword、IronSword和MagicSword,也包括以后加进来的所有实现IAttackStrategy的新类)的注入,而客户类的客户类(Program,即测试代码)负责根据情况,实例化服务类,注入到客户类中,从而解决了这个矛盾。

依赖注入的正式定义:

依赖注入(Dependency Injection),是这样一个过程:由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。

Creative Commons License

本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名张洋(包含链接),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值