别了,DIP、IoC

[本文已经作为垃圾,请参考什么是好莱坞原则]

如果网上搜索依赖倒置原理/DIP、控制反转(IoC)容器等,会得到一大堆的信息,其中可能还包括yqj2065在本博客中发布的The Dependency Inversion Principle(翻译)(2005-01-28 00:22)的转载版(原文我也移到了垃圾桶)。

最近,在我系统地回顾设计模式时,感到应该与DIP、IoC说ByeBye了。

1、“依赖倒置”(1)这个名字令人不舒服,(2)当用“好莱坞法则”解释它时,显得不伦不类。(3)逻辑混乱,被我抛弃。

2、IoC,被玩坏了。

1.回调机制和好莱坞法则

  • 回调(call back,一个动词词组)机制,是一门编程语言,使得下层模块/库可以调用或执行上层模块定义的代码的机制。上层模块所定义的、被(下层模块)调用或动态绑定的代码,则被称为回调函数 (简称回调、callback,一个名词)。
  • 回调机制用于框架设计和通知机制。

通知机制中,如图9-11所示,上层模块Client调用了下层Server的copy()方法。假设上层需要更新进度条——显示复制任务完成的进度,显然上层并不清楚复制的进度而只有下层的Server才知道。这时下层模块如何将进度数据传递给上层的Client呢?
一种简单的方式:Server将进度数据保存在一个成员变量x中,并提供getX()。这样就需要Client时时刻刻地查询该数据。如同现实生活中打的士到某地,从上车的第一秒开始,时刻或每隔5秒问司机到了地方没有,也太烦人了。
另一种方式则是通知或使用回调。

2. 好莱坞法则:多个Client的对象或多个IXxx的其他实现类对下层Server2对象的某种状态变化感兴趣。以现实生活中的场景为例:一些男女演员们(Client)都对某导演(Server2)是否拍新片子感兴趣。导演肯定和的士司机一样,不喜欢演员们天天打电话询问。于是导演提供了一个让感兴趣的演员们留下电话号码的接口register(IXxx listener)。一旦导演准备拍摄一部新片子(sthHappened())就通知所有已登记的演员。而对于那些随时打电话询问是否有戏的演员,导演告诉他们一条好莱坞法则:"Don't call me; I'll call you."。

2.两个结构

这是OCP/抽象依赖原则的类图。

图1 抽象依赖原则

这是回调/好莱坞/观察者模式的类图:

图2 回调/好莱坞法则

 

两个结构完全相同的图,却有完全不同的含义/语义。

  • DIP的类图中,Client可以随时随地地调用Server,但是地主应该依赖于“I丫鬟”;
  • 回调/好莱坞/观察者模式的类图中,绝对不允许S依赖C。

用好莱坞法则、钩子解释OCP、DIP、模板方法显得异常地别致。

3.控制反转(IoC)

DIP的描述除了有点含糊,名字不好之外,可以作为OCP的操作性的注解。而控制反转(IoC)则是DIP缺点的继承者。

  • 对于图1,我不能够理解IoC的含义,地主依赖一个丫鬟,变成地主依赖一个I丫鬟,这时地主在编译时不依赖具体的丫鬟,但是地主还是依赖丫鬟。(注:有人用层次结构说明DIP的意义,有所谓真假DIP,等下在说。)

《设计模式》、和[3P•11DIP]中,出现了别致到别扭的好莱坞法则的解读。地主要I丫鬟上茶(),

I丫鬟 yh = new 丫鬟();  // I丫鬟 yh =(I丫鬟)getObject();

yh.上茶();

按照我们正常人的说法:yh按照引用的实际类型,动态绑定方法体。

看看别致的说法:地主要I丫鬟上茶,I丫鬟调用子类型丫鬟的上茶()。本来子类依赖于父类,这里父类可以调用子类型的方法,所以……父类依赖于子类??我不知道这里在说什么。

  • 《设计模式》:“模板方法导致一种反向的控制结构,这种结构有时被称为“好莱坞法则” ,即“别找我们,我们找你”[ S w e 8 5 ]。这指的是一个父类调用一个子类的操作,而不是相反。”
  • [3P•11DIP]:“This is sometimes known as the Hollywood principle..... The lower-level modules privide the implementation for interfaces that are declared within,andcalled by,the upper-level modules”

“反转”总不会是说父类依赖于子类吧?

  • 对于图2,也不知道哪里反转了。再说了,有回调或者观察者模式,这个含含糊糊的控制反转(IoC)纯属多余。

总之,IoC要么别扭,要么多余。

4.抽象依赖原则

 

一、在类设计层面,OCP、针对接口编程,或者我喜欢使用的“抽象依赖原则”(或许包括DIP)是同义词。OCP是目的/目标性的,针对接口编程,“抽象依赖原则”,DIP是操作性的。

但是DIP要改:

第一条: 地主 should not depend upon 丫鬟, both should depend upon I丫鬟。

第二条:不知道在类设计层面,这个Abstractions的意思。如果是指I丫鬟,这就是废话;如果是指Client?这就是梦话。ok,在类设计层面,这一条不要。

二、在架构设计或分层设计中,

上下层中添加一个服务层(接口层),可以看成DIP的应用,也是SOA的常用模式,【与《企业应用架构模式》中的Service Layer模式有些不同】。所以DIP-1挺好的。但是“倒置”,我随时不适应。依赖接口层的目的是封装变化,至于接口层与上层打包(所谓真DIP),还是与下层打包,有真正的价值和实用意义吗?

总之,DIP除了“倒置”和需要修改外,还是好的。在有OCP、针对接口编程,“抽象依赖原则”时,就显得多余。特别是在类设计层面,完全辞不达意。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值