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,就是一個推卸責(zé)任的藝術(shù)。
我曾經(jīng)說OO是一種政治掛帥的設(shè)計方法,就是指這種責(zé)任分配。
不能越俎代庖,能推卸責(zé)任就推卸責(zé)任,這是每個參與到這個政治游戲中的模塊都應(yīng)該遵守的。
do one thing and do one thing well.
就是說,你要做最好只作一件事,不是兩件,也不是半件。
當(dāng)你寫A的時候,你先要明確A的責(zé)任是什么。如果A唯一負責(zé)的就是創(chuàng)建B,好吧,你那么作沒錯。
但是,我的假設(shè)是,A的職責(zé)是做另外一件事(比如出差),而買票只不過是要達到這個目標(biāo)的一種實現(xiàn)方法所需要的一個前提條件。你要是自己也負責(zé)買票,你就是做了兩件事。
當(dāng)然,什么是“一件”事的定義并不明確。如果你的買票這個動作可以被完全封裝進A,外界看不到,也不想看到,并且你也可以預(yù)知永遠不會有其它的搞到票的方法(比如,搶票,彎腰在地上揀票,不要發(fā)票打折,中關(guān)村買假車票,買電腦附贈車票等等),你可以選擇自己買票。(我好像曾經(jīng)就什么時候正向控制,什么時候反向給了一個大致的標(biāo)準(zhǔn)吧?)
試著從frankensteinlin的角度理解一下。
假設(shè)X是A的使用者,本來如果A這么設(shè)計:
那么,我的X的代碼就是:
這樣,只有A依賴B,X依賴A。
但是如果你要ioc,A變成這樣:
此時,我的X豈不是要變成:
如果這樣,不是說明A要用到B這樣一個實現(xiàn)細節(jié)暴露給X了?
而且X要使用的接口也復(fù)雜了。
如果X是老板,那么
為什么·還要我老板來給你小兵買票?到底誰是老板?。?
而且現(xiàn)在是X依賴A, X依賴B,A依賴B但不依賴B的創(chuàng)建。依賴也沒有減少啊!
好。對frankensteinlin的理解敘述完畢。
下面·我來回答,
1。首先,還是要根據(jù)我前面給的標(biāo)準(zhǔn)分析。B是否是一個對它要實現(xiàn)的功能的一個100%標(biāo)準(zhǔn)的實現(xiàn)?它是否可能有B1, B2, ..., Bn等等不同的實現(xiàn)競爭對手?
2。如果1是true,那么A能否自己對選擇那一個B做決定?A選擇B1和B2是否都能夠給出合法的語義,這兩個合法的語義是否可能不同?
A的設(shè)計者如何在不知道使用者意圖的時候決定采用哪個語義?
比如說出差買票。中關(guān)村買假票便宜,但是風(fēng)險高;去代理點預(yù)定價格適中,但是要提前定購,有點麻煩和不靈活;想走了拍拍屁股現(xiàn)場買票最瀟灑,但是可能價格非常高,bill gates無所謂,小業(yè)務(wù)員就別想這么奢侈了。
其它還有買臥鋪?買軟臥?買頭等艙飛機票? 等等等等。
這些,你A同志能否都自己決定?假如你買頭等艙,結(jié)果X窮,不買單怎么辦?
還是說你A只給bill gates專職服務(wù),換個老板你就辭職?
3。說到ioc把A的實現(xiàn)細節(jié)暴露給X,這也不好說。
假設(shè)B就是一個買票的策略或者是一張票。
首先,X是否有可能本身就想控制這個買票的策略呢?它真是A的實現(xiàn)細節(jié)嗎?
比如bill gates同志,他老人家對下屬關(guān)懷備至,一人為本,一定要買最爽的頭等艙,那么這樣:
不是很自然?
其次,是有可能X不想控制這個買票策略。象你說的“老板”的情況。這個老板不在乎買票怎么買,花多少錢,就是不想過問實現(xiàn)細節(jié)的。它就是希望你把事情做好。
但是,請注意,在你說new A()的時候,你等于讓老板自己尋找一個能夠出差的人再下命令。老板必須認(rèn)識A,必須自己構(gòu)造A。這,這難道就爽了?
為什么老板自己不能直接說:“給我一個能出差的家伙”。這不是更爽?
看看你的X的代碼,它難道不能繼續(xù)ioc?不能繼續(xù)推諉責(zé)任?它為什么要new A()?
如此,不就沒有什么實現(xiàn)細節(jié)暴露?接口不是比new A()還要簡單?
這個老板做的不是更徹底?
至于用xml編程,我是不太喜歡的。xml配置的好處在于可以隨時修改,不用重編譯系統(tǒng)。這是operation上的好處,從軟件結(jié)構(gòu)上,依賴關(guān)系上,它和把依賴寫在java里沒什么不同。而且往往比java還要繁瑣,易錯,難維護。
只不過,ioc并不必然意味著xml配置。把組裝代碼寫在java里也一樣是ioc。
比如,在main()函數(shù)里,我可以自己手工組裝如下:
這樣,程序其它地方都避免了不必要的依賴。
確實,依賴必須存在,就象你再program against interface,最終也必須new一個class一樣。ioc也不是魔術(shù),不可能把依賴變沒。
但是依賴放在什么地方就是學(xué)問了。
通過讓main()或者是任何一個其它的組裝模塊來單獨處理程序所有的依賴,我們實現(xiàn)了職責(zé)單一化。
另外,如果要改動系統(tǒng)的行為(比如從B1變成B2,或者D2改用D1),直接改動組裝者就可。
更重要的是,我們可以通過注射不同的零件來讓同一個組件展現(xiàn)不同的行為。
比如,上面的main()代碼構(gòu)造了兩個A對象,這兩個A對象行為不同。但是都同時存在于程序之中。
請問,你如果完全把new B()這種東西固定到A中去,怎么達到這個效果?
至于說配置著出錯,就全完蛋了之類的話,就有點不知所云了。
一個軟件系統(tǒng),如果一個模塊有bug,那么整個系統(tǒng)就是有bug。
如果你的main()函數(shù)不工作了,那么整個程序就不工作了。
你這里難道要轉(zhuǎn)移話題談fail over之類的事情了嗎?
其實frankensteinlin說的一句話很對:
引用: |
這不是推卸責(zé)任嗎? |
太對了!ioc,推而廣之,OO,就是一個推卸責(zé)任的藝術(shù)。

我曾經(jīng)說OO是一種政治掛帥的設(shè)計方法,就是指這種責(zé)任分配。
不能越俎代庖,能推卸責(zé)任就推卸責(zé)任,這是每個參與到這個政治游戲中的模塊都應(yīng)該遵守的。
do one thing and do one thing well.
就是說,你要做最好只作一件事,不是兩件,也不是半件。
當(dāng)你寫A的時候,你先要明確A的責(zé)任是什么。如果A唯一負責(zé)的就是創(chuàng)建B,好吧,你那么作沒錯。
但是,我的假設(shè)是,A的職責(zé)是做另外一件事(比如出差),而買票只不過是要達到這個目標(biāo)的一種實現(xiàn)方法所需要的一個前提條件。你要是自己也負責(zé)買票,你就是做了兩件事。
當(dāng)然,什么是“一件”事的定義并不明確。如果你的買票這個動作可以被完全封裝進A,外界看不到,也不想看到,并且你也可以預(yù)知永遠不會有其它的搞到票的方法(比如,搶票,彎腰在地上揀票,不要發(fā)票打折,中關(guān)村買假車票,買電腦附贈車票等等),你可以選擇自己買票。(我好像曾經(jīng)就什么時候正向控制,什么時候反向給了一個大致的標(biāo)準(zhǔn)吧?)
試著從frankensteinlin的角度理解一下。
假設(shè)X是A的使用者,本來如果A這么設(shè)計:
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這樣一個實現(xiàn)細節(jié)暴露給X了?
而且X要使用的接口也復(fù)雜了。
如果X是老板,那么
引用: |
老板不應(yīng)該事事躬親!我交給你辦至于你怎么辦我就不管了 |
為什么·還要我老板來給你小兵買票?到底誰是老板?。?
而且現(xiàn)在是X依賴A, X依賴B,A依賴B但不依賴B的創(chuàng)建。依賴也沒有減少啊!
好。對frankensteinlin的理解敘述完畢。
下面·我來回答,
1。首先,還是要根據(jù)我前面給的標(biāo)準(zhǔn)分析。B是否是一個對它要實現(xiàn)的功能的一個100%標(biāo)準(zhǔn)的實現(xiàn)?它是否可能有B1, B2, ..., Bn等等不同的實現(xiàn)競爭對手?
2。如果1是true,那么A能否自己對選擇那一個B做決定?A選擇B1和B2是否都能夠給出合法的語義,這兩個合法的語義是否可能不同?
A的設(shè)計者如何在不知道使用者意圖的時候決定采用哪個語義?
比如說出差買票。中關(guān)村買假票便宜,但是風(fēng)險高;去代理點預(yù)定價格適中,但是要提前定購,有點麻煩和不靈活;想走了拍拍屁股現(xiàn)場買票最瀟灑,但是可能價格非常高,bill gates無所謂,小業(yè)務(wù)員就別想這么奢侈了。
其它還有買臥鋪?買軟臥?買頭等艙飛機票? 等等等等。
這些,你A同志能否都自己決定?假如你買頭等艙,結(jié)果X窮,不買單怎么辦?
還是說你A只給bill gates專職服務(wù),換個老板你就辭職?
3。說到ioc把A的實現(xiàn)細節(jié)暴露給X,這也不好說。
假設(shè)B就是一個買票的策略或者是一張票。
首先,X是否有可能本身就想控制這個買票的策略呢?它真是A的實現(xiàn)細節(jié)嗎?
比如bill gates同志,他老人家對下屬關(guān)懷備至,一人為本,一定要買最爽的頭等艙,那么這樣:
java代碼: |
BillGates: A = new A(new BuyMostComfortableFirstClassWithStrippers()); |
不是很自然?
其次,是有可能X不想控制這個買票策略。象你說的“老板”的情況。這個老板不在乎買票怎么買,花多少錢,就是不想過問實現(xiàn)細節(jié)的。它就是希望你把事情做好。
但是,請注意,在你說new A()的時候,你等于讓老板自己尋找一個能夠出差的人再下命令。老板必須認(rèn)識A,必須自己構(gòu)造A。這,這難道就爽了?
為什么老板自己不能直接說:“給我一個能出差的家伙”。這不是更爽?
看看你的X的代碼,它難道不能繼續(xù)ioc?不能繼續(xù)推諉責(zé)任?它為什么要new A()?
java代碼: |
X: A a; X(A a){ this.a = a; } |
如此,不就沒有什么實現(xiàn)細節(jié)暴露?接口不是比new A()還要簡單?
這個老板做的不是更徹底?
至于用xml編程,我是不太喜歡的。xml配置的好處在于可以隨時修改,不用重編譯系統(tǒng)。這是operation上的好處,從軟件結(jié)構(gòu)上,依賴關(guān)系上,它和把依賴寫在java里沒什么不同。而且往往比java還要繁瑣,易錯,難維護。
只不過,ioc并不必然意味著xml配置。把組裝代碼寫在java里也一樣是ioc。
比如,在main()函數(shù)里,我可以自己手工組裝如下:
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也不是魔術(shù),不可能把依賴變沒。
但是依賴放在什么地方就是學(xué)問了。
通過讓main()或者是任何一個其它的組裝模塊來單獨處理程序所有的依賴,我們實現(xiàn)了職責(zé)單一化。
另外,如果要改動系統(tǒng)的行為(比如從B1變成B2,或者D2改用D1),直接改動組裝者就可。
更重要的是,我們可以通過注射不同的零件來讓同一個組件展現(xiàn)不同的行為。
比如,上面的main()代碼構(gòu)造了兩個A對象,這兩個A對象行為不同。但是都同時存在于程序之中。
請問,你如果完全把new B()這種東西固定到A中去,怎么達到這個效果?
至于說配置著出錯,就全完蛋了之類的話,就有點不知所云了。
一個軟件系統(tǒng),如果一個模塊有bug,那么整個系統(tǒng)就是有bug。
如果你的main()函數(shù)不工作了,那么整個程序就不工作了。
你這里難道要轉(zhuǎn)移話題談fail over之類的事情了嗎?