以前寫過一篇隨筆《剪刀剪紙》是給一些新同事講面向對象時用的,當時就感受有些不暢,不過用來給新同事入門足夠了就沒多想,最近看書時偶爾走神把這件事想起來了,順便羣裏討論時談到聚合之間的方法調用,因而決定寫一篇博客糾正一下那篇隨筆裏的問題。html
開頭先聲明一下,如下只是個例子,只是用來講明對象間交互的解耦,怎麼樣交互我以爲更好,可是若是是真的要寫一個剪刀剪紙的程序,以前隨筆的作法並不必定就是很差的,有些耦合只是在須要解的時候才應該去解。另外,如下作法只是理想的作法,可是現實的項目總會有各類各樣的妥協,因此主要仍是隨機應變,沒有最好的作法,只有最合適的作法,聲明暫時結束。post
在剪刀剪紙的隨筆裏寫了:剪刀只須要關心本身發出了剪的動做,不須要關心紙,因而給紙抽象了一個東西的基類。可是回頭細看其實這並無解決問題,剪刀雖然沒有和紙發生耦合,可是和東西發生了耦合,剪刀自己並不必定要剪東西,說不定就是個工藝品呢,剪刀剪紙隨筆中剪子的Cut(Thing thing)方法參數選擇了Thing等於將剪刀內部的邏輯對Thing公開了一部分,這種作法已經破壞了剪子的封裝,同時也表達了一種業務邏輯,既剪刀剪東西,並且Thing也已經不是單純的東西的概念,而是被剪子剪的東西。若是是一個初學者作項目,這麼作問題或許不大,可是深究這種作法從某種角度來講是錯的。url
上面一段說出的問題歸納一下:spa
1.剪刀和Thing(如下所說的Thing都表明」被剪的東西「這個概念)的耦合是多餘的,如何讓剪刀和Thing各自獨立;code
2.在須要的時候,剪子和Thing能夠交互完成剪東西這一業務。htm
上面說了Cut的參數使用Thing破壞了封裝,若是作好封裝的話就能夠解決上面的第一個問題。作好封裝也就是說剪刀只包含本身的職責,也就是抽象好本身的職責,封裝和抽象是相輔相成的存在。仔細思考下,剪子的職責應該是什麼的,能夠用來剪東西只是說明了它能夠作什麼,諾基亞還能夠用來砸核桃(其實還有用來開核桃的模特模型,你懂得。。。),但你能說砸核桃是諾基亞的職責麼,那剪刀的職責是什麼,很明顯沒Thing那就必定是剪了,怎麼表達這個剪呢,那就是發出一個剪的做用力,因此,咱們能夠增長一個做用力的對象,固然若是非要較真,做用力和剪刀仍是有耦合,不過剪刀本就是接受並傳遞做用力的,做用力只是參數,並且做用力在這個業務場景中也是在一個工做單元裏傳遞業務狀態變化的根本,整個業務其實就是由做用力驅動的,其實這個做用力用命令模式的命令來表達或許更貼切,不過這裏就不細說了。對象
//關於命名,我是故意的,緣由不想說,大家千萬別學,做用力的意思 public class KineticEnergy { public int Size { get; set; } public struct Point { public int X { get; set; } public int Y { get; set; } } }
而後是剪刀的:blog
public class Scissors { private KineticEnergy _kineticEnergyBeUsed { get; set; } public void Stress(KineticEnergy kineticEnergy) { _kineticEnergyBeUsed = kineticEnergy; } public KineticEnergy SendCutEnergy() { return SwitchKineticEnergy(); } private KineticEnergy SwitchKineticEnergy() { KineticEnergy kineticEnergyBeCut = _kineticEnergyBeUsed; //做用點和力的大小等變化 return kineticEnergyBeCut; } }
至於Thing仍是看剪紙那篇隨筆的,基本就是那意思,代碼就不改個名重貼一遍這麼費事了。ci
下面就是第二個問題了,想必你們也看出來了,第二個問題基本上也不是問題了,剪刀剪一次紙的過程咱們能夠用一個工做單元來表示(我偷懶,傳遞的力一直在改變,可是反正重點不在這,就不要在乎這些細節了):get
//工做單元UOW三個單詞不是這麼寫的,看到的注意,別學!!! public class CutThingsWorkUnit { private KineticEnergy _kineticEnergy; private Scissors _scissors; private Thing _thing; //剪刀和Thing應該由業務場景的Context來提供 public CutThingsWorkUnit(Scissors scissors, Thing thing) { _scissors = scissors; _thing = thing; } public void Execute() { //這裏的人,那篇隨筆我已經給抽象掉了,放這裏就是個意思,隨便實例化一下,這種細節就不要在乎了 Person person = new Person(); _kineticEnergy = person.UseScissorsKineticEnergy(); _scissors.Stress(_kineticEnergy); _kineticEnergy = _scissors.SendCutEnergy(); _thing.Stress(_kineticEnergy); } }
最後,至於這東西被剪的結果,剪紙那篇隨筆說過,就再也不說了。