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

在批判之前,先了解一下依赖倒置
依赖倒置(Dependence Inversion Principle)原则讲的是:要依赖于抽象,不要依赖于具体。
简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:
抽象不应当依赖于细节;细节应当依赖于抽象;
要针对接口编程,不针对实现编程。
反面例子:
 
缺点:耦合太紧密,Light发生变化将影响ToggleSwitch。
解决办法一:
将Light作成Abstract,然后具体类继承自Light。
依赖倒置原则(DIP)批判 -- 称之为本末倒置原则更贴切_第1张图片 
优点:ToggleSwitch依赖于抽象类Light,具有更高的稳定性,而BulbLight与TubeLight继承自Light,可以根据"开放-封闭"原则进行扩展。只要Light不发生变化,BulbLight与TubeLight的变化就不会波及ToggleSwitch。
缺点:如果用ToggleSwitch控制一台电视就很困难了。总不能让TV继承自Light吧。
解决方法二:

依赖倒置原则(DIP)批判 -- 称之为本末倒置原则更贴切_第2张图片 
优点:更为通用、更为稳定。
结论:
使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。

依赖倒置(Dependence Inversion Principle)原则讲的是:要依赖于抽象,不要依赖于具体。
而我要说的是:要依赖于具体,不要依赖于抽象。
当然我并不是要批判依赖倒置原则本身,因为这个原则是正确的,但仅限于业务抽象分析领域,如果我们将抽象概念直接映射成代码则是不伦不类,只会阻碍生产力的提升并导致开发成本居高不下。我的意见是,业务抽象分析就留给业务专家们玩去吧,就算他们一眼就能发现所有人都能发现的light这一抽象概念,我们也不应该愚蠢到去写出class light或者interface light这样的东西。
不知道大家有没有看过robbin转载的《量子物理史话》,如果看过的话,就可以了解量子学说和相对论学说是如何颠覆经典物理学的。经典物理学虽然被颠覆,但并不是说经典物理学是错误的,它只是被请下了神坛,安分守纪的在自己的位置干好自己的事情,不复当年千秋万载一统江湖的风光日子。
如果我们学过化学,就应该了解H2O是什么东西,两个氢原子加一个氧原子,这是什么?分子,两种原子按照某种规律组合在一起而形成的分子,我们将之命名为“水”分子。“水”只是一个抽象名词,所以在我们的系统中,class water是不应该存在的,如果你非要表达这一个概念那么你应该这样写: Object o = new Object;  o.Name="water"; why?为什么不应该写出class water这种东西?接下来我们要说一说量子学。
先举一个例子吧:我们的客户想要一个简单的订单处理系统,其中有一项功能需求是“订单录入”,我们将会这样描述这个功能:订单数据由a,b,c组成,我们需要一个录入界面可以录入a,b,c,并且有一个录入按钮,当用户按下该按钮的时候订单数据应该保存到数据库里面。
好了,这样一个需求对各位来说简直就是小菜一碟,但是我并不希望各位为这种琐碎的需求去写无聊代码,我们的挑战是:你应该写一个系统,这个系统直接读入上面的功能描述,并产生执行代码或者直接解释功能描述来运行。你可以将上述功能描述生转换成为你所定义的形式化文件,以便于你的系统进行解释和分析。如果你对自己的系统很有自信,也可以直接写代码,但是记住代码量应该尽可能逼近我们的需求描述。
代码示例:
Data order = new Data();
order.Add("a");
order.Add("b");
order.Add("c");

Form form = new Form();
form.default_control = "TextBox";
form.controls.Add("a");
form.controls.Add("b");
form.controls.Add("c");

Entity entity = new Entity();
entity.table_name = "order";
entity.AddColumn("a", "varchar");
entity.AddColumn("b", "varchar");
entity.AddColumn("c", "varchar");

Action action = new Action();
action.name = "录入";
action.data_access_type = "insert";
action.data = order;
action.entity = entity;

form.actions.Add(action);
form.controls.Add("录入", "Button");
form.show();
在上面的例子中,我们的系统完全不关心自己在处理什么业务,业务概念对系统来说是毫无意义的,任何一个业务对象最终都会分解为系统对象,任何一个业务过程最终都会分解成为系统过程,对系统来说,系统元素的排列组合构成了世界的全部。H2O,两个氢原子加一个氧原子,水。物理学的发展史为我们揭示了现实世界精妙绝伦的结构,物理学的研究是收敛的,研究的越深,就会越来越逼近事实的真相和本质,而计算机科学研究则是发散的,每一个专家学者都可以异想天开创造出一个又一个的抽象体系,对软件人而言,到底是幸福还是不幸呢?

我要说的东西很杂,很多,也很乱,目前还无法成体系。
gigix你不如先说一说你所关心的业务逻辑问题,业务逻辑确实比较复杂,要把业务逻辑分解成有限的对象不是一件轻而易举的事。
这样吧,你来提业务逻辑需求,我来写代码。
我上面写的代码很重要,没有这些代码的支持是无法实现业务逻辑自动化处理的。

那么就先简单讲一下业务逻辑这种东西吧。
为了避免犯错误,把“业务逻辑”的概念弄错,google了一把“业务逻辑”,找不到关于“业务逻辑”的名词解释,“业务逻辑层”倒是出现了不少,同时出现的就是滥的不能再滥的“三层结构”,软件结构什么时候变得这么简单,只剩“三层”了。
最后还是找到一个解释:
引用

问:
看了很多资料,发现“业务逻辑”和“应用逻辑”出现的频率较高,但是两者往往被混用,弄得读资料的时候有些糊涂。按照我现在的理解,“应用逻辑”应该是和特定的应用有关,例如是“报帐”系统还是“图书管理”系统。那么“业务逻辑”又是指什么呢?是指“工作流”吗?还有“领域逻辑”,它是否就是指静态的“领域实体”?
我对这些概念的理解总是有点“似是而非”,没有掌握其本质的含义和相互的区别。希望版主或是哪位大峡能指点指点。小弟才疏学浅,希望能举点例子来说明。我感激不尽。
答:
业务逻辑是从业务来看,指的是某个具体的业务的流程; 应用逻辑是从实现业务的程序来看,指的是实现某业务的应用程序的处理逻辑。如果应用逻辑和业务逻辑完全吻合,那么你的程序在满足业务需求上,就是完美的了,但是一般来说,这只是理想情况。
领域逻辑应该指适应于某个领域的通用的业务逻辑。
个人理解

既然没人知道业务逻辑究竟是什么东西,那么接着继续说我们的例子。
上面我们已经实现了“订单录入”的功能,只要客户一按“录入”按钮,订单就会自动生成并保存。但是我们的客户并不满足,因为业务订单并不是可以随便乱填的,必须满足一定的条件才能建立,而这一个条件就是:a+b>c 以及 a-b修改我们的代码,记得我们的action吗,只需要增加一行代码
Action action = new Action();
action.name = "录入";
action.data_access_type = "insert";
action.data = order;
action.entity = entity;
// 增加
action.restriction = "((a+b>c) and (a-b)action 和 restriction 是最难设计的,因为必须要考虑到分支处理等执行序列的问题,如果太复杂的话就会成为另一个设计语言,所以只能按照概率进行有限处理,仅仅捕捉在项目中经常出现的逻辑处理模式,对于特殊的处理则建议重载action及restriction手工写逻辑处理代码
当然这里出现的action和restriction只是一个概念示例,事实上它们是被各自分解为许多独立对象。
在上面的代码中我们可以看到 "((a+b>c) and (a-b)c) and (a-b)另外在 entity 中我们将a,b,c都声明为varchar,所以条件"((a+b>c) and (a-b)<c) or b=c"是无法验证的,编译器也无法检测出这种错误,所以代码审查及全面的黑盒测试是必不可少的。

看不懂没关系,正好证明你是一个不错的面向对象设计专家,这篇文章不会谈论如何使用设计对象原则、框架或者设计模式之类你所熟悉的东西。我要说的东西如果不是在对立面,也会是在另外一条岔道上。
先说一说终极目标吧
典型软件开发过程生命周期模型:
需求分析、设计(概要设计和详细设计)、编码实现、测试
终极软件开发过程生命周期模型:
需求分析、需求形式化、运行测试
如果终极系统拥有相当于优秀开发工程师的智慧和知识的话,需求形式化的工作也应该可以一并省略。

接着继续说我们的量子学,有些人或许会觉得奇怪,软件开发跟物理学有什么关系?相信大多数人都看过《matrix》,我们就姑且作一个大胆的假设,我们所处的世界正是一个matrix,但此matrix非彼matrix,这是由上帝设计的系统,这个系统非常庞大、非常复杂,人类所了解的知识不过是沧海一粟,我们将要设计的任何系统在这个系统面前根本就不值一提。什么叫简单设计?什么叫复杂系统?我们或许可以向上帝寻求答案。
与其他学科相比,物理学是最接近上帝的(请注意,此上帝非彼上帝,我们的上帝是爱因斯坦的上帝)。数百年来,无数的物理科学家孜孜不倦的做出各种尝试去探索世界的本质,归功于他们的不懈努力,我们才得以从量子学中窥探出上帝设计模式的一斑。
在人类眼中,这个世界总是斑斓多彩的,无数新奇事物等待着人们去发掘,去抽象,去给它们命名,去构造X工厂为它们分门别类。抽象,是人类的伟大发明,只要运用恰当,就可以将现象抽象为本质,并且可以将其命名为X模式。但是在上帝的眼里,世界要复杂的多,表面上毫不相干的事物,事实上有着某种直接或间接的联系,上帝制定了人类无法直接感知的规则控制着所有的一切,量子学则为我们抽丝驳茧的揭示了这些联系以及背后的规则。
软件复杂度的问题是结构复杂度的问题,上帝的matrix也面临着同样的问题,不过反过来说更为恰当,上帝的matrix面临的问题也是软件系统面临的问题,我们开发的软件是另外一个微型的平行matrix,之所以说是平行的,是因为我们的软件系统是对现实世界中的一小部分作出映射。
暂时先到这里,有闲情稚趣的人可以当科幻小说一样看看。

--------------------------------------------

gigix :

我也渐渐有点看明白了。也就是说,我们设计对象接口时就是在规定业务逻辑。但就像Martin Fowler说的,所谓“业务逻辑”就是业务中不讲逻辑的那些东西,所以我们的对象接口老是跟不上业务逻辑的变化。或者说,我们老是猜不到合适的接口。这个问题呢,TrustNo1也提到过。先听age0继续讲下去吧。

firebody: 

我也明白一点了,
不过业务对象建模过程本身就是从具体--->抽象--->具体实现 过程,这个捕捉业务逻辑还是相对准确的。
难道,建模过程是先定好接口再做具体实现的???
我个人认为:
No! No! No!
首先是详细了解业务逻辑(详细用例分析),然后针对用例做这些分析,搭建对象框架,其实这个过程是一个很抽象的过程,也是最难把握的过程。按照我的经验和理解,我个人认为,对于较复杂的业务逻辑,我会针对它做一个草图设计,有一个画一个,画一个又一个主干用例的过程本身是一个迭代过程,感觉就是将具体用例过程 先做具体对象实现过程,然后再“综合”抽象这些具体对象实现到一个抽象层, 这就是我们的顶层类框架草图
双引号 框上“综合”,这个词份量很重,因为在分析单独一个用例的时候,你是不知道哪些部分要做一个抽象或者设计,等到第二或者第三个用例分析,还发现同样的业务逻辑部分,你就会综合抽取这些相同的逻辑出来做一个抽象设计。

xiaoyu:

这点我很同意,不可能一开始就设计接口吧(我相信会有这种牛人,对所有的事都很清楚--god).
通过现象看本质.
---------------------------------------------

我觉得开始就接口不错啊.
遇到需求, 先写接口, 先写客户代码, 弄清楚自己想要什么, 比上来就实现强多了.
就算以后发现需求理解得不好, 需要改动, 用接口也不比直接实现麻烦.
关键是: 谁说你要对什么都清楚了才开始写接口?
接口就是类似一个描述需求的伪码而已. 有什么了不起的?

因为现在比较忙,写科幻小说也不是一件容易的事,所以连载的间隔时间可能会长一点,请大家见谅。但是主轴应该还是物理学,在恰当的时候也会稍微谈及文学、戏剧及电影,艺术实际上也是一门科学,因为大家都同处于上帝的matrix当中,直接或间接的联系是必然的。
但是在继续下去之前,先问一个问题,大家对于“接口”这个概念是不是有一个一致的共识,就具体而言,“接口”在各位的平行matrix当中指的是class?interface?还是别的东西?希望有一个比较一致的认识,否则谈到具体问题的时候又会演变成空对空的局面。
(注:平行matrix是一个很有趣的说法,平行是弦论的概念,弦论推论出平行宇宙的可能性,记得李连杰的《The One》吗,matrix则是《matrix》中对宇宙的另外一个更有趣的假设,更符合软件人的观点)

----------------------------------------------

Trustno1:

其实,这是一个非常简单的问题.没有那么复杂,也没有那么多神神叨叨的。
所谓的抽象,只不过是一种归纳法。归纳法只会对已经知道的事情起作用。
我们不可能说,我看到了一千只乌鸦是黑的,就断言第一千零一个乌鸦一定也是黑的。从我们经历过的事例推出我们没有经历过的其他事例,本来就是荒谬不羁,不合逻辑的.
所谓的需求变更,就是那些我们从未经历过的事情。如何对待这种东西?人类唯一的方法就是Guess&Gambling。Science is just Guess抽象或者归纳法在这些东西面前是毫无用处的。对于需求来说,更为困难的是:大部分需求都是无法在人和人当中传递的,无法去确证的。就如我一直举的那个例子:我认为这朵花很美。对你来说,你不可能知道我这朵花美在那里,是颜色?气味?形状?或者是一种综合的体验?即使你知道,你也无法去证实。
我们很多人都是从理工科毕业的,所以特别相信。我们是可以认识这个世界的,我们是可以对这个世界进行形式化预测的。有些东西可以,有些东西却不可以。需求就是属于不能进行预测的一类。对于大多数的软件工程师来说,他们喜欢用好的结构去应付需求变化。这其中本身就犯了两个错抽象,模式这些东西属于归纳法,刚才说了归纳法与预测需求本身就是牛头不对马嘴搭不上边的。其次,需求是否可以用一种形式化的东西去预测呢?我认为不能。我们最多能做的是Guess&Gambling。需求无法进行形式化的预测-----这不是需求的问题,也不是软件方法的问题。而是人类自身语言上的缺陷。如果你希望了解需求像演算物理方程式那样唯一确定,那么这将是一个可怕的世界——1984 forever。
PS:物理学从来不揭示这个世界的本质。物理学所揭示的只不过是这个世界上某些现象所呈现出来的数据关系而已。量子力学就是最典型的例证。量子力学从来没有揭示过微观世界的本质,他不知道他们观测到的到底是十么。量子力学只是说,他观测到的数据是十么,这些数据之间有十么关系。所以那些波动说,粒子说其实统统的都是胡说八道。微观世界到底是十么,没有人知道。以爱因斯坦从来不相信这套,因为他是一个确定论者,更加是一个本质论者。
从我的观点看,物理学所能解决的是How的问题,why的问题只能由上帝来回答。

----------------------------------------------

事实上并不仅限于物理学,人类所研究的任何一个学科都只是揭示这个世界上某些领域的某些层次中的某些现象所呈现出来的数据关系而已。每一项科学理论都必然是从现实世界中一系列具体现象所呈现的数据关系归纳演绎出来的,那么我们是不是可以说科学研究揭示的只是现象,而不是本质?
“微观世界到底是什么,没有人知道”,这句话很有趣,由此可以推导出并不仅仅是微观世界,无论是宏观世界还是什么观世界都没有人知道是什么,即使你看见的东西你实际上也不知道是什么,因为你所“看见”的影像只是你的视觉神经对物体反射光产生的脉冲信号而已,你所了解的仅仅是物体所呈现出来的光属性,你凭什么说你了解这个世界?仅仅是因为别人看到的东西与你相同?
为了避免无谓的争执,先学习一下科学本质
引用

科學的本質
魏明通 教授
國立台灣師範大學化學系
趙金祁對科學的本質及其成分,在其著作《自然科學原理在科學教育上的意義》有詳盡的介紹:
一、事物發生中,時空物質的侷限性
人類知識固然誰時代的進步而突飛猛進,一日千里,但人類對時空物質,這類實質的了解,到今日仍有限。甚至包括生命現象在內,都無從窺其全貌。因此科學家必須承認,知識的程度僅及於經驗證據所涉範圍之內,強力摒棄不知為知的意念。科學家對於臆測、假說、假設、模型、假說真理、思維真理等界限分明,即表明白對各別問題程度的不同,不容混淆。
同時,在求真過程中,科學家始終權宜運用逐步逼近的法則,以求由近及遠,由小至大,漸進了解,趨近自然的終極真理。/r
二、自然律的一致性
科學家一致承認,大自然間的千變萬化,必定由一個一致的、有序的,和統一的自然律所支配,即所謂的再現性。因此在相同的情境下必產生相同的現象。此種由自然律支配自然現象的特性,正是科學家與迷信的重要區別關鍵所在。科學知識由反覆出現中,獲得實驗數據,以量化證據說服大眾;迷信卻只屬於少數人的感受,既無再現性的可能,更無法提供證據取信於人。
三、因果關係性
本質上,科學家認定現有事物,必在功能上與過去事物相互關聯,即在特定因素上,有某種程度的因果關係。因此,科學家除描述與說明現有事物外,亦能憑藉對事物所以形成各種因素之了解,預測可能發生的新事物。
四、事物的可理解性
科學家堅信宇宙的一切事物,可由人的知覺感受、意識運作、設備器材、與剖析能力,加以理解。進一步,還可經由科學方法,獲致預測一切未知事物的寶貴知識。科學家深信過去的科學既能提供人類解決生存問題的條件,將來勢必亦能帶給人類無比力量,求取自身在物質世界中的生存機會。/r
五、生存環境的長遠價值觀
科學是人類文化的一部分,基本上應在人生理想與社會規範的要求上,求取發展與成長。不過,科學之進步,往往衍生人類生存環境的改變,造成環境污染與資源貧瘠等問題。因此,科學家既認定宇宙是有秩序而和諧的,自當維護人類與物質間,個人與自然間,個人與他人間的有秩序特徵與和諧關係。也就是說,科學工作應以維護生存環境的完美為重,力避任意破壞生存條件而招致人類的噩運。/
六、探究事物的傳統性
科學研究的問題與工作,具傳統性。自古以來師徒間研究題目及成果的相應承襲上,時常見到。科學研究的方法,譬如,歸納與演譯、直觀與分析、假設與求證等,都行之有年,歷久彌堅,代代相傳。
七、知識本體的不完整性
人類不斷創立各種理論,以描述、說明與預測自然界所發生的各個現象。不過,因為科學只能在自然間,擷取片斷的資料,呈現自然真理。因此,到目前已建立的理論中,不僅甚多假設性或臨時性的理論,而且彼此間,還存在不少無法彌補的空隙,暫時由假設、形成模型等加以墊補,以保未來的求證,修改模型,取捨假設,進而推出更為完整新理論。因此,科學家只能經由不完整知識的過程,不斷發掘問題,解決問題,以達更趨完整的目標。
八、事物表象的存疑性
根據科學典範咸由某種立足點出發的道理,盛行一時的任何一個典範,必有其範圍與極限。超出典範的界限,必引起爭論,導致新典範的產生。因此不能斷定,科學發展的主導因素是,無窮的質疑與不斷的探討。科學家在存疑的基礎上,推動科學的發展。準此,科學家所崇尚的大膽假設、小心求證,以獲得新知,所必要的前提,即在於存疑與適當提出問題上。
九、認識事物的客觀性
客觀是指存在於心意之外,具有實在與實證的理性意義。這就是說,科學的所以成為科學,係因其具有獨立嚴謹的客觀性,與個人的情緒、愛好、希望、價值、需求等無關。
十、理論上的節儉性
大多數科學家都深信,自然界的基本原理、原則必定極為簡單,認定大自然中各式各樣的個別現象,可由簡單的敘述或數學公式,加以貫穿、詮釋與說明。卜帕 (K.R.Popper)從反面指出,容易為科學接受的簡單原理、原則,必屬可適應更多經驗實證的學說。當然,這樣簡單的原理、原則,可能遭遇反證機會增加,因此,原理、原則的節儉程度直接與反證次數成正比,越節儉的,必涵蓋越形龐雜的範圍,而在科學界的邏輯推理標準上,佔最強勢的地位。
-----------------------------------------------
Trustno1:
基本没有太大的问题。只是标准太多了一些,
我看只要留下 自然律的一致,因果关系,事物的可理解 三个修饰。
再加上一个定义:科学是一种说话方式,就足够了。
从新整理一下就是: 科学是一种说话方式,这种说话方式满足自然规律一致性(主体无关性),满足因果律性(或者概率),事物的可理解(事物指称性)。
-----------------------------------------------
我们还是先关注主题,围绕DIP原则来进行讨论吧。
DIP原则讲的是“要依赖于抽象,不要依赖于具体”,强调“要针对接口编程,不针对实现编程”。
现在来看看我的示例代码,代码中有三个对象:Data、Entity及Action,这三个对象组合在一起实现Insert动作,也就是说它们之间的协作关系完成了对Insert的抽象,这是最高层次的抽象,在关系数据库消失之前它们都不用作任何改动。
再回头看看传统设计,我们有一张数据表用来保存用户资料,你猜人们会如何设计呢?根据他们对面向对象的深刻理解,用户这个“对象”是必不可少的,所以他们的设计八九不离十会是这样:
Java代码  
class User
{
  int ID;
  string Name;
  setID();
  setName();
  bool Insert();
  {
    string sql = string.Format(" insert user_table values({0},'{1}'); ", ID, Name);
    return DBAccess.Insert(sql);
  }
}
如果用户换成雇员的话,class User会换成class Employee,以上的无聊代码同样会反复出现。
讨论到这里,好象跟DIP还是扯不上任何关系,为了展示OO大师的风范,我们还是DIP一下吧。用户和雇员到底有什么关系呢?想来想去好象都是Human,那么DIP终于可以大显身手了。  
Java代码
interface Human
{
  string Name;
  virtual bool Insert();;
}
class User : Human;
class User : Empolyee;
上面的代码看起来是不是觉得很傻,有些人之所以会觉得coding毫无乐趣可言,是否是因为这样的缘故呢?
DIP所追求的方向是正确的,但其方式如果不是无用的,也是不切实际的。
我批判DIP原则,目的主要是指出它的 应用范围实在是小的可怜,也就是其环境适应能力实在是差的不能再差,精心构造DIP的应用环境比DIP应用本身更困难、更有实际性的意义,DIP应用与之相比可以说仅仅是最后的装饰品而已,但奇怪的是DIP这种东西却可以成为指导性的原则,更糟糕的是我们经常会看到玩具级别的例子来展示DIP应用。
举一个例子,我们有一个窗口,上面有两个button,一个负责关闭窗口,一个负责将数据Insert到数据库。两个button的实现的功能完全不同,它们之间可以说完全搭不上任何关系,但是依然可以运用DIP原则,从中可以抽象出Action概念。
class Action
{
  virtual public void OnAction();
}
class CloseForm : Action
{
  Form form;
  public void setForm();
  override public void OnAction();
  {
   form.close;  
  }
}
class Insert : Action
{
  string ID;
  string Passwd;
 
  public void setID();
  public void setPasswd();
  override public void OnAction();
  {
    string sql = string.Format(" inset user_table values('{0}','{1}'); ", ID, Passwd);
    DBAccess.Insert(sql);
 }
}
这是一个典型的DIP应用,绝对符合“高层模块不应该依赖于低层模块,二者都应该依赖抽象,抽象不应该依赖于细节,细节应该依赖于抽象 ”的定义。但是你认为这样的设计能够实现解藕的目的吗? 解藕有很多方式,所谓的高层模块、低层模块、接口类、实现类不过是建筑在oo概念之上的条条框框而已,跳不出这些束缚的话coding只是自虐而已。
举个容易理解的例子。哺乳动物基本上都会发声,猫的叫声是“喵~~”,狗的叫声是“汪~~”,那么看看我们可以如何组织Animal,Cat和Dog之间的关系。
标准的DIP方式:
class Animal
{
  virtual public void Bark();
}
class Cat : Animal
{
  override public void Bark();
  {
    print("喵~~");
  }
}
class Dog : Animal
{
  override public void Bark();
  {
    print("汪~~");
  }
}
client:
Animal cat = New Cat();
Animal dog = New Dog();
cat.Bark();
dog.Bark();
非DIP方式:

class Animal  
{  
    string voice = "";  
    public void setVoice(string v);
    public void Bark();  
    {  
        print(voice);  
    }  
}  
class Animals  
{  
    static public Animal Cat();  
    {  
        Animal cat = new Animal();;  
        cat.setVoice("喵~~");;  
        return cat;  
    }  
    static public Animal Dog();  
    {  
        Animal dog = new Dog();  
        dog.setVoice("汪~~"); 
        return dog;  
    }  
}  
client:  
Animal cat = Animals.cat;  
Animal dog = Animals.dog;  
cat.Bark(); 
dog.Bark();

--------------------------------------------
wfeng007:
搂住的意思比较杂
好像是说 不同抽象层次的东西 应该由不同认识层次(或者不同职能层次)的人来完成。 而 业务的抽象,不是设计的部分,因为抽象可以是无止境的,发散下去。dip虽然可以解决一定的问题,但其本身在代码实现过程中,会带来更多的需要抽象分析的东西。所以,dip不应该在特定的业务中去刻意追求,而应该由大量具体经验的人,在对抽象的业务(事物)进行归纳总结。 一般的人,只要注重使用抽象了的工具就可以了。
不知道是否是这个意思。。。。。
不过,感觉用哲学层次的表达没有必要。

---------------------------------------------
基本上就是这样,不过最近我也修正了自己的观点,DIP本身是一种方法工具,工具本身并没有任何错误,运用工具的人才可能会犯错DIP在系统设计层面非常适用,因为系统层面的抽象适用范围广、持续时间长,一个好的系统抽象将会长久的运用下去,但是在短促多变的业务层面则不大适用,高层次的业务抽象没有实际意义,低层次的业务抽象又无法灵活应变

DIP与其说是设计原则,倒不如说是设计目标来得更加贴切。
DIP所追求的高层次泛化抽象模型只能是在广泛性的探索和研究中归纳总结出来,在一般性的个别开发过程所得到的信息并不足以归纳出足够泛用的抽象模型。而OO也仅是一种方法工具,并没有强制约束应该以何种方式进行归纳或演绎,OO的功劳只是能够以自然幽雅的方式表达及展现DIP抽象模型而已
所谓“OO提供的是一个不断特化的过程,要求我们一开始就给出最一般最抽象的概念,然后不断的特化以求描述客观”应该算是对OO的误解,OO建议好的系统应该建构在合理的抽象体系结构之上,但是并没有强制要求一开始就建立优秀的抽象设计,任何人都知道这是不可能的,任何好的抽象都必然是建立在归纳的基础之上

你可能感兴趣的:(软件技术)