论坛首页 Java企业应用论坛

对于OCP原则的困惑

浏览 44436 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-09-22  
to:yhc0125

他们前面也给了你不少方法了,你比较一下,哪一种方法的代码编写量最小?

我看啊,还是:

A temp = new B();;
  |
  v
A temp = new C();;


这样最省事,只用改一个字母。:P

gigix 写道
在一个reasonable的架构下,没有任何client代码会直接去new一个对象。


这样绝对的话,我是不说的。
0 请登录后投票
   发表时间:2004-09-22  
yhc0125 写道

比如说我定义了一个接口Interface A,他的一个实现class B,我在调用B来完成功能时这样做A temp = new B();

这样的话当我给他另外一个实现class C时,我的客户段代码还是要改变的:
A temp = new C();

完全不变是不可能的,但变化所影响的范围可以得到限制,或者从代码中分离出来。
想想你用过的jdbc,你的驱动改变的时候,客户端代码需要改变吗?
你可以了解一下bridge pattern 是如何把抽象与实现相分离的。
当然还有适度问题,像庄所说的,不必做无用功,如果不需要实行这种抽象与实现的分离或意义不大,完全不必去费力气实现。
0 请登录后投票
   发表时间:2004-09-22  
没有什么纯粹的架构合理这样的指标。

一个架构是否合理,只能是相对于需求,以及需求的变动而言的。

面对N个需求,以及随后的M种需求变更,你的代码是不是最节省的?这就是判断标准。

不要用一个系统中interface的数量来判断设计的好坏。
也不要用一个系统中工厂的数量来判断设计的好坏。
也不要用一个系统中XML配置文件的数量来判断设计的好坏。
也不要用一个系统中IOC的次数来判断设计的好坏。
也不要用一个系统中AOP的次数来判断设计的好坏。

这些都是静态的,而不是动态的指标。
0 请登录后投票
   发表时间:2004-09-22  
只要使用了继承,出现了派生类,OCP原则都会被打破,无论你如何部署代码,显式创建派生类的代码都是无可避免的。

如果你一定要坚持OCP原则,首先必须坚持CARP原则,只有CARP原则成立的情况下才能达到OCP的效果。
0 请登录后投票
   发表时间:2004-09-22  
OCP作为OO最基本的原理,是有它存在的意义的。
当你在你的构架的核心代码B里写下:
A a=new A();
这样一行代码时,你就应该百倍小心,甚至觉得写下这一句代码很“不可思议”,
如果B 和 A 在不同的包中,那么你更应该值得重新审视你的设计。
a对你所见的是一个具体类,而不是一个抽象类。
比如说本来:
public class A implements AI
接口AI仅仅提供了稳定的method:doA();
然而在B里,你不仅仅看到了doA();你还看到了A所公开的其自身独有的一些public 方法。等于把这种易变的因素公开给了A的使用者。那么,这一句代码意味着A的变化将是B变化的直接因素。变化波及的范围越大,说明你的设计越是丑陋。
隔离这种具体类之间的关联设计模式都有过相关讨论:
1)工厂隔离
2)配置隔离
我更喜欢第2)种,其实把它提高一点,就是容器隔离的概念。
用容器组装核心类,核心类的配置可以通过更改配置文件来修改。
当然,这些都离不开诸如Constructor这些反射机制。
0 请登录后投票
   发表时间:2004-09-22  
为什么要隔离?
设计为什么就是“丑陋”的?

隔离、美丽,都要付出代价的,这些代价,究竟该不该付出,是需要考虑的。
0 请登录后投票
   发表时间:2004-09-22  
多谢大家对我这个简单问题的关注。

我觉得应该明确的一点是ocp原则是非常重要的,可以给我们的开发带来很大帮助,但根据问题的具体情况来分类处理:

1、简单不变的应用,我可能不会使用ocp原则,而是采取直接实现的方式,就像Bob大叔说的:不要对任何事物都进行抽象

2、一般的应用,使用ocp原则,变化的时候在客户端调用时简单修改一下就好了

3、使用工厂或容器,用他们为客户端创建对象

在Spring里面同样是由一个工厂来生成和管理所有bean的,按照Ioc原则,就是说一次把对象都创建好,用那一个都可以,而不用客户端去创建了,这样是不是客户端只要有一个接口引用就行了?
0 请登录后投票
   发表时间:2004-09-22  
庄表伟 写道
为什么要隔离?
设计为什么就是“丑陋”的?

隔离、美丽,都要付出代价的,这些代价,究竟该不该付出,是需要考虑的。

a对你所见的是一个具体类,而不是一个抽象类。
比如说本来:
public class A implements AI
接口AI仅仅提供了稳定的method:doA();
然而在B里,你不仅仅看到了doA();你还看到了A所公开的其自身独有的一些public 方法。等于把这种易变的因素公开给了A的使用者。那么,使用者往往会很自然也很方便的使用了A的一些具体方法,而不是接口的稳定方法。那么,从这个意义上来说,这一句代码意味着A的变化将是B变化的直接因素。变化波及的范围越大,说明你的设计越是丑陋。

A这个具体类所包含太多的变化的咚咚。公开他们,这就是丑陋的。
0 请登录后投票
   发表时间:2004-09-22  
如果你选择了Java,但你却没有选择Java的面向接口。
那么,我还是想说:你没用好Java。
0 请登录后投票
   发表时间:2004-09-22  
to:firebody

我们来说一些概念,比如说,什么叫“用法”。

一个类 ClassA,有n个public函数,还有m个private的函数。对于外界来说:ClassA的用法,就是由那n个public函数来定义的。

当且仅当,ClassA有一个以上的用法:
1、doA(),doB()
2、doA(),doC()

这时,我们才需要定义两个interface:IAB,IAC

然后重构ClassA,使其implements IAB,IAC
然后再利用工厂模式,在需要按IAB方式使用ClassA的地方,返回一个以IAB接口表示的ClassA,在需要按IAC方式使用ClassA的地方,返回一个以IAC接口表示的ClassA。

以这样的方式,使用接口,才是对于java的正确使用。

而如果你的ClassA只有一种用法
doA(),doB(),doC()
而你为了这个唯一的用法,去声明一个interface IABC,
然后再用ClassA implements IABC
然后再用工厂方式,返回一个IABC

你说我们俩,谁没有用好java!?

只有在需求出现之后,你才需要重构你的代码,使之支持两种不同的“用法”。一开始就搞出,类+接口+工厂,这就是典型的过度设计!

最后问你一个问题:
谁告诉你接口就是稳定的?类就是不稳定的?
他们都是java代码,要改一样可以改。
0 请登录后投票
论坛首页 Java企业应用版

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