论坛首页 Java企业应用论坛

依赖倒置原则(DIP)批判 -- 称之为本末倒置原则更贴切

浏览 46593 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-11-01  
我觉得写个接口更好一些,偷懒了没写

用户Client就用
Animal cat = new Cat();;
cat.bark();;

就可以了
0 请登录后投票
   发表时间:2004-11-01  
swing 写道
还是前面关于XML解析器的实现,
我们来深入一步好了,
假设你现在准备用一个实现乐org.w3c.dom 包的DOM实现,比如xerces,
这个时候你会去直接使用xerces中的Document接口实现类,还是说你通过org.w3c.dom提供的Document接口?我想是没有人关心xerces中是怎么实现Document接口的,甚至都不需要去关心到底那个实现类类名叫什么,你只要都依赖org.w3c.dom提供的接口,那么将来你就可以替换一个实现,比如出现了一个新的实现,它的效率是xerces的100000000倍,呵呵这个效率实在是难以抵抗的诱惑,你想替换,这个时候,如果你的代码(这里就是高层乐,高层是相对低层而言的)总是通过org.w3c.dom包的接口(这个包就是上面你所引用的一句话中的“抽象”乐)引用的,那么你只管替换实现包(这个就是低层实现乐)好了,你的代码不需要做任何改动,
但是你如果在你的代码中使用乐xerces实现中所独有的类,比如DocumentImp之类(注,我忘了那个实现类类名乐,差不多是这样大概,这里就不用较真乐我想),你就需要改你的代码乐。
到底是不是解耦乐,两个字:
显然


你不觉的自己的例子很无聊吗?你假设别人实现了某些功能,却发觉其有不足之处,但由于没有办法修改源代码,所以只好去继承原有类来实现新特性,按照你的说法,DIP的唯一用处就是亡羊补牢,不见的吧。
0 请登录后投票
   发表时间:2004-11-01  
mikecool 写道
我觉得写个接口更好一些,偷懒了没写

用户Client就用
Animal cat = new Cat();;
cat.bark();;

就可以了


老兄,仔细看看你的代码,和我的例子有本质区别吗,客户端的调用代码都是一模一样的,解藕的目的就是让客户端解除对具体类的依赖,管你抽象类和具体类自己内部怎么玩。
0 请登录后投票
   发表时间:2004-11-01  
引用
你不觉的自己的例子很无聊吗?你假设别人实现了某些功能,却发觉其有不足之处,但由于没有办法修改源代码,所以只好去继承原有类来实现新特性,按照你的说法,DIP的唯一用处就是亡羊补牢,不见的吧。


晕哦,这里你又理解反乐,org.w3c.dom 包是我的高层接口,
我并不假设有人实现乐某些功能,
最关键的是,我不需要关心低层实现,这就是解耦。将来无论是我使用别人的代码,还是自己做一个实现,都不需要关心我到底拿这些实现做了什么,
你可以把这个抽象看成是高层和低层的约定,请注意这是代码级强制约定,所以对解耦非常有效。

本来想,XML的解析器应该是大家都比较熟悉的内容,所以才搬出来说,其实它本身是遵循有其它一些原则,单独讨论dip有些混乱。
另外:
引用
按照你的说法,DIP的唯一用处就是亡羊补牢

你这么说明显强词夺理,不知道该如何同你讨论乐,怎么说你也应该花时间精力真正理解我的话才好同我讨论,我不和你接着讨论乐,因为我不是来和你争的。

有一点奇怪,作者 正文
age0 你居然明白mikecool 的例子和你的没有本质区别,那为什么你还执着着你的例子?!!
0 请登录后投票
   发表时间:2004-11-02  
只能说他根本不懂什么叫抽象什么叫DIP,哎无知者无罪

无语

我的例子好像和Age0的还是不一样的吧。。。。竟然被看作一样的,我拿块豆腐撞死算了
0 请登录后投票
   发表时间:2004-11-02  
^_^


原因很简单啊,
首先是你要给出高层接口,在你的例子里面,我想
你会把Animal作为高层接口,
但是,当你写下:
Animal cat = new Cat();
时,你说你不依赖Cat的代码,当然不可能乐。这样的话,你还不是把低层实现给参和进来乐?!
其实你只要考虑,为什么当你使用xerces的XML解析器实现时不需要关心里面的实现细节就知道怎么回事乐。
这里有2种显而易见的实现方式:
1、工厂,这是使用很普遍的方式
2、注入,这里说注入我想我只是借用乐一下词汇,感觉很形象,不一定是需要ioc的,比如:
MyClass(Animal animal) {
}
这样的构造器,还有普通的get/set方法等等。

经典的设计模式中大多数都是遵循dip原则的,当然,它们还有遵循其它原则。
0 请登录后投票
   发表时间:2004-11-02  
我倒,这肯定是DIP几种标准不需知道细节的用法,我偷懒了,哎,只想用个简单例子写写好了
其实到头来都是还是:Animal a = new subclass of animal b();,
难道我在使用a的时候关心过b里面的细节么?我才不关心呢,我用的时候抽象出来的东西,子类爱怎么叫怎么叫啊:D

不论注入还是Factory都逃不过这一点,而且后来也还是用超类的一些方法来调用嘛,DocumentBuilderFactory也就这么做的。大可不必言必Factory IoC,毕竟这才是调用的本质嘛

继续拿头撞豆腐,呵呵玩笑
0 请登录后投票
   发表时间:2004-11-02  
mikecool 写道
只能说他根本不懂什么叫抽象什么叫DIP,哎无知者无罪

无语

我的例子好像和Age0的还是不一样的吧。。。。竟然被看作一样的,我拿块豆腐撞死算了


谁规定了只有把类声明为abstract才叫抽象?abstract关键字发明前的oo都跟抽象搭不上关系?DIP原则和abstract关键字有什么必然的关系吗?
0 请登录后投票
   发表时间:2004-11-02  
swing 写道
^_^


原因很简单啊,
首先是你要给出高层接口,在你的例子里面,我想
你会把Animal作为高层接口,
但是,当你写下:
Animal cat = new Cat();
时,你说你不依赖Cat的代码,当然不可能乐。这样的话,你还不是把低层实现给参和进来乐?!
其实你只要考虑,为什么当你使用xerces的XML解析器实现时不需要关心里面的实现细节就知道怎么回事乐。
这里有2种显而易见的实现方式:
1、工厂,这是使用很普遍的方式
2、注入,这里说注入我想我只是借用乐一下词汇,感觉很形象,不一定是需要ioc的,比如:
MyClass(Animal animal) {
}
这样的构造器,还有普通的get/set方法等等。

经典的设计模式中大多数都是遵循dip原则的,当然,它们还有遵循其它原则。



我一定要把cat的创建代码放到客户端里面,难道就不叫DIP了吗?


class AnimalClient
{
	Animal animal = null;
	
	public AnimalClient(string name);
	{
		switch(name);
		{
			case "猫":
				animal = new Cat();;
				break;
				
			case "狗":
				animal = new Dog();;
				
			default:
				animal = UnknownAnimal();;
		}
	}
	
	public void DoSometing();
	{
		animal.Bark();;
	}
}

0 请登录后投票
   发表时间:2004-11-18  
摇摇头,楼主举的例子只是为DIP而DIP,根本没有考虑使用DIP的Context,所以不具有任何批判性。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics