论坛首页 Java版 企业应用

阿Q:革命了,革命了!(也谈IOC的好处)

浏览 17206 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
时间:2005-03-18
age0 写道
to youcai

你的代码有一个非常严重的问题,就是你假设PC的所有部件都是由同一个部件供应商提供的,但实际情况并非如此,我们的销售策略是非常灵活的,任何需要的时候我们都可以从不同的厂家选取不同的部件组装成一台PC,比如高档机的CPU由Intel提供,内存则由kingMax提供,中挡机的CPU由AMD提供,内存则由现代提供,你该不会是想把这些供应商都注射进去吧。

经销商决定部件供应商,那么厂商就要提供ioc机制让经销商来注射部件供应商,
如果厂商决定部件供应商,那么pc就要提供ico机制让厂商注射部件供应商,
如果pc自己能决定部件供应商,当然pc内部解决了.
ajoo说的很明白了撒.
   
0 请登录后投票
时间:2005-03-18
youcai 写道

经销商决定部件供应商,那么厂商就要提供ioc机制让经销商来注射部件供应商,
如果厂商决定部件供应商,那么pc就要提供ico机制让厂商注射部件供应商,
如果pc自己能决定部件供应商,当然pc内部解决了.
ajoo说的很明白了撒.


还记得我们说过的层次问题吗?经销商是不可以跨越层次去指定PC制造商去采用哪些部件供应商的,如果可以的话,那就是DIY了,经销商只能向Dell或联想购买某档次的机器,Dell或联想是不可能接受经销商的DIY订单的,接收DIY订单的是那些售卖自己组装PC的小店,但那是另外的问题,不要和PC制造商混为一谈。

另,to gigix,封贴大可不必,我还没有把大容量Memory的内容写出来,等我写出来后再作结论吧。
   
0 请登录后投票
时间:2005-03-18
还是封了吧,我那几个如果算是白写了.
   
0 请登录后投票
时间:2005-03-18
奇怪,为什么还再讨论这个什么IOC????
偶像ajoo已经总结过这个千万遍了。要么可能是我把偶像的话理解错了。
我个人觉得偶像的意思就是再重复前人说过的话,那就是要把类的创建职责和类的使用职责分开!

假设你做一个系统,你可以把这个系统划分为好多层次,设计各种组件,然后,根据你的设计,实现各种组件。最后,你要用这些组件把这个系统组装起来运行。

根据ajoo的意思,如果组件A要使用组件B的话:一,就是组件A在内部自己创建组件B的实例,然后使用组件B;二,由别的东东创建组件B的实例,并注射给组件A,A只管使用。
到底什么情况下该使用哪一种呢?我不清楚!偶像们没有给过任何比较好的参考信息。我从来没主持过什么系统设计啊,或者类库设计。但是我猜,做应用的大部分应该选择第二种。

这是我的理解,可能有不少的错误,还请楼上所有的偶像啊,牛人啊,再给我补补课!特别是potian,o6z,ajoo,Trustno1,gigix等。

多谢啦。
   
0 请登录后投票
时间:2005-03-18
根据偶像ajoo的话说,这个什么ioc根本就不是什么神奇或者新鲜的东东,他老人家几百年前就这么用了,只是他原来一直没把这个东东叫IOC。偶像是不是叫她小甜甜?

呵呵 :)

原来一直没有这么一个组装的工具,所以Rod Johnson等人都做了这么一个万能组装器的东东。这个组装器能根据你的元数据(偶像gigix,问一个问题,可以认为这是元数据吗?),组装起整个系统。当然如果你在使用这个组装器的时候,非要让你的组件依赖这个组装器,那Rod Johnson也没则!毕竟怎么使用还是看个人!如果真的方便的话,即使你的部分少量应用组件依赖了容器,我想也不大紧!

不好意思,就当我瞎说。庄表伟大哥要删就删了吧。
   
0 请登录后投票
时间:2005-03-19
其实frankensteinlin说的一句话很对:
引用
这不是推卸责任吗?

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

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

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

do one thing and do one thing well.

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

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

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






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

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

[code:1]A:
A(){
b = new B();
}[/code:1]

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

[code:1]X:
A a = new A();
......[/code:1]


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


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

[code:1]
A:
A(B b){
this.b = b;
}[/code:1]

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

[code:1]A a = new A(new B());[/code:1]

如果这样,不是说明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同志,他老人家对下属关怀备至,一人为本,一定要买最爽的头等舱,那么这样:
[code:1]
BillGates:
A = new A(new BuyMostComfortableFirstClassWithStrippers());
[/code:1]
不是很自然?


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

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

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

[code:1]X:
A a;
X(A a){
this.a = a;
}
[/code:1]

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


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

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

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


[code:1]
A a1 = new A(new B1(new C1(), new D1()));
A a2 = new A(new B2(new C2(), new D2()));
...
[/code:1]




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

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

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

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

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


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

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

你这里难道要转移话题谈fail over之类的事情了吗?
   
0 请登录后投票
时间:2005-03-19
这个话题确实应该打住,如果ioc是向左走的话,那么我的设计则是向右走,从向右走的角度去评论向左走是毫无意义的,我竟然会犯这种低级错误,真是罪过。

有时间的话我会另开一个向右走的专题,ajoo记得来捧场,我要将你推卸责任的不负责艺术华丽的轰至渣。
   
0 请登录后投票
时间:2005-03-19
大家并没有说IOC是万能的,拿IOC当银弹,而前面已经说了IOC也不是新概念,是一个OO的程序员早就一直在使用的工具,就如同if ,for循环一样常用的东西.
   
0 请登录后投票
时间:2005-03-20
ajoo 写道
其实frankensteinlin说的一句话很对:
引用
这不是推卸责任吗?

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

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

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

do one thing and do one thing well.

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

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

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






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

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

[code:1]A:
A(){
b = new B();
}[/code:1]

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

[code:1]X:
A a = new A();
......[/code:1]


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


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

[code:1]
A:
A(B b){
this.b = b;
}[/code:1]

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

[code:1]A a = new A(new B());[/code:1]

如果这样,不是说明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同志,他老人家对下属关怀备至,一人为本,一定要买最爽的头等舱,那么这样:
[code:1]
BillGates:
A = new A(new BuyMostComfortableFirstClassWithStrippers());
[/code:1]
不是很自然?


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

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

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

[code:1]X:
A a;
X(A a){
this.a = a;
}
[/code:1]

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


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

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

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


[code:1]
A a1 = new A(new B1(new C1(), new D1()));
A a2 = new A(new B2(new C2(), new D2()));
...
[/code:1]




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

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

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

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

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


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

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

你这里难道要转移话题谈fail over之类的事情了吗?


偶像强呀,就是强呀!不好意思的说,我看得好象大致明白了一点,但又不是很明白。呵呵
   
0 请登录后投票
时间:2005-03-22
一个好帖被灌成什么样了,可惜啊
   
0 请登录后投票
论坛首页 Java版 企业应用

跳转论坛:
JavaEye推荐