kapok

垃圾桶,嘿嘿,我藏的这么深你们还能找到啊,真牛!

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  455 随笔 :: 0 文章 :: 76 评论 :: 0 Trackbacks
http://forum.javaeye.com/viewtopic.php?t=11418&postdays=0&postorder=asc&highlight=%CF%B5%CD%B3%BC%DC%B9%B9&start=75

其实frankensteinlin说的一句话很对:
引用:
这不是推卸责任吗?

太对了!ioc,推而广之,OO,就是一个推卸责任的艺术。 Smile

我曾经说OO是一种政治挂帅的设计方法,就是指这种责任分配。

不能越俎代庖,能推卸责任就推卸责任,这是每个参与到这个政治游戏中的模块都应该遵守的。

do one thing and do one thing well.

就是说,你要做最好只作一件事,不是两件,也不是半件。

当你写A的时候,你先要明确A的责任是什么。如果A唯一负责的就是创建B,好吧,你那么作没错。

但是,我的假设是,A的职责是做另外一件事(比如出差),而买票只不过是要达到这个目标的一种实现方法所需要的一个前提条件。你要是自己也负责买票,你就是做了两件事。
当然,什么是“一件”事的定义并不明确。如果你的买票这个动作可以被完全封装进A,外界看不到,也不想看到,并且你也可以预知永远不会有其它的搞到票的方法(比如,抢票,弯腰在地上拣票,不要发票打折,中关村买假车票,买电脑附赠车票等等),你可以选择自己买票。(我好像曾经就什么时候正向控制,什么时候反向给了一个大致的标准吧?)






试着从frankensteinlin的角度理解一下。

假设X是A的使用者,本来如果A这么设计:

java代码: 

A:
  A(){
    b = new B();
  }



那么,我的X的代码就是:

java代码: 

X:
  A a = new A();
  ......




这样,只有A依赖B,X依赖A。


但是如果你要ioc,A变成这样:

java代码: 


A:
  A(B b){
    this.b = b;
  }



此时,我的X岂不是要变成:

java代码: 

A a = new A(new B());



如果这样,不是说明A要用到B这样一个实现细节暴露给X了?
而且X要使用的接口也复杂了。

如果X是老板,那么
引用:
老板不应该事事躬亲!我交给你办至于你怎么办我就不管了

为什么·还要我老板来给你小兵买票?到底谁是老板啊?

而且现在是X依赖A, X依赖B,A依赖B但不依赖B的创建。依赖也没有减少啊!



好。对frankensteinlin的理解叙述完毕。

下面·我来回答,


1。首先,还是要根据我前面给的标准分析。B是否是一个对它要实现的功能的一个100%标准的实现?它是否可能有B1, B2, ..., Bn等等不同的实现竞争对手?

2。如果1是true,那么A能否自己对选择那一个B做决定?A选择B1和B2是否都能够给出合法的语义,这两个合法的语义是否可能不同?
A的设计者如何在不知道使用者意图的时候决定采用哪个语义?
比如说出差买票。中关村买假票便宜,但是风险高;去代理点预定价格适中,但是要提前定购,有点麻烦和不灵活;想走了拍拍屁股现场买票最潇洒,但是可能价格非常高,bill gates无所谓,小业务员就别想这么奢侈了。
其它还有买卧铺?买软卧?买头等舱飞机票? 等等等等。
这些,你A同志能否都自己决定?假如你买头等舱,结果X穷,不买单怎么办?
还是说你A只给bill gates专职服务,换个老板你就辞职?


3。说到ioc把A的实现细节暴露给X,这也不好说。
假设B就是一个买票的策略或者是一张票。
首先,X是否有可能本身就想控制这个买票的策略呢?它真是A的实现细节吗?
比如bill gates同志,他老人家对下属关怀备至,一人为本,一定要买最爽的头等舱,那么这样:
java代码: 


BillGates:
  A = new A(new BuyMostComfortableFirstClassWithStrippers());


不是很自然?


其次,是有可能X不想控制这个买票策略。象你说的“老板”的情况。这个老板不在乎买票怎么买,花多少钱,就是不想过问实现细节的。它就是希望你把事情做好。

但是,请注意,在你说new A()的时候,你等于让老板自己寻找一个能够出差的人再下命令。老板必须认识A,必须自己构造A。这,这难道就爽了?
为什么老板自己不能直接说:“给我一个能出差的家伙”。这不是更爽?

看看你的X的代码,它难道不能继续ioc?不能继续推诿责任?它为什么要new A()?

java代码: 

X:
  A a;
  X(A a){
    this.a = a;
  }



如此,不就没有什么实现细节暴露?接口不是比new A()还要简单?
这个老板做的不是更彻底?


至于用xml编程,我是不太喜欢的。xml配置的好处在于可以随时修改,不用重编译系统。这是operation上的好处,从软件结构上,依赖关系上,它和把依赖写在java里没什么不同。而且往往比java还要繁琐,易错,难维护。

只不过,ioc并不必然意味着xml配置。把组装代码写在java里也一样是ioc。

比如,在main()函数里,我可以自己手工组装如下:


java代码: 


A a1 = new A(new B1(new C1(), new D1()));
A a2 = new A(new B2(new C2(), new D2()));
...






这样,程序其它地方都避免了不必要的依赖。

确实,依赖必须存在,就象你再program against interface,最终也必须new一个class一样。ioc也不是魔术,不可能把依赖变没。
但是依赖放在什么地方就是学问了。

通过让main()或者是任何一个其它的组装模块来单独处理程序所有的依赖,我们实现了职责单一化。

另外,如果要改动系统的行为(比如从B1变成B2,或者D2改用D1),直接改动组装者就可。
更重要的是,我们可以通过注射不同的零件来让同一个组件展现不同的行为。
比如,上面的main()代码构造了两个A对象,这两个A对象行为不同。但是都同时存在于程序之中。

请问,你如果完全把new B()这种东西固定到A中去,怎么达到这个效果?


至于说配置着出错,就全完蛋了之类的话,就有点不知所云了。

一个软件系统,如果一个模块有bug,那么整个系统就是有bug。
如果你的main()函数不工作了,那么整个程序就不工作了。

你这里难道要转移话题谈fail over之类的事情了吗?
posted on 2005-06-05 22:13 笨笨 阅读(327) 评论(1)  编辑  收藏 所属分类: J2EEHibernateAndSpringALL

评论

# re: Ioc吵架 2007-09-30 15:08 gembin
Yes  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: