最近在看Casa博客上組件化相關(guān)的一些文章,感覺收獲很大。
這是他的一個系列文章,有三篇繼承、多態(tài)、封裝。
Casa博客鏈接
他的意思實際上不是摒棄面向?qū)ο蟮乃枷耄侵赋鲈诓糠智闆r下不要濫用面向?qū)ο蟮哪J健?br> 以下是文章的摘錄,括號內(nèi)是個人理解。??
繼承
繼承概念:子類自動共享父類數(shù)據(jù)結(jié)構(gòu)和方法的機(jī)制。
其實不是說繼承不好,而是要做到不要盲目使用繼承。
首先繼承的優(yōu)點是很方便可以做到代碼復(fù)用,但是這個特性容易在開發(fā)中被濫用,從而導(dǎo)致高耦合,變成了父類牽一發(fā)而動全身。
需要注意以下幾點:
- 解決問題的時候優(yōu)先使用組合替代繼承(組合替代繼承,單一職責(zé))
- 繼承的時候需要考慮父子類層級之間的職責(zé)關(guān)系(父類是給子類提供服務(wù),不涉及子類的業(yè)務(wù)邏輯;層次關(guān)系明確,父子類各做各的;父類的所有改動都需要在子類中體現(xiàn),此時耦合成為了需求)
總結(jié):從目前的開發(fā)場景來說,真正用到繼承的地方并不多,而使用組合需要比繼承更強(qiáng)的抽象能力,這使得我們在開發(fā)工作中會下意識的使用更符合直覺的繼承,但從長遠(yuǎn)角度來看,使用組合的好處更多,能夠使用組合來實現(xiàn)的就不要使用繼承。
多態(tài)
多態(tài)概念:不同對象接收同一消息可以產(chǎn)生不同結(jié)果,多態(tài)的本質(zhì)是子類覆蓋或重載父類的方法,使得調(diào)用同一類對象的同一方法產(chǎn)生不同效果。
在這里討論的是以下幾種情況如何去解決:
- 父類有部分public的方法是不需要,也不允許子類覆重(比如業(yè)務(wù)的固定調(diào)用順序。這里不允許子類覆重如何實現(xiàn)?)
- 父類有一些特別的方法是必須要子類去覆重的,在父類的方法其實是個空方法(如何保證子類的實現(xiàn)者不會忽略必須要重載的方法)
- 父類有一些方法是可選覆重的,一旦覆重,則以子類為準(zhǔn)
- 父類有一些方法即便被覆重,父類原方法還是要執(zhí)行的(而且需要保證一定的調(diào)用順序)
作者給出的解決方案是使用IOP。
父類中預(yù)留子類child作為屬性,協(xié)議公開需要或可選覆重的方法,自己可以不實現(xiàn),子類必須實現(xiàn)協(xié)議,父類中直接調(diào)用child對應(yīng)方法。即可解決以上問題。
1.通過約定,public方法一般不允許覆重,可以覆重的是協(xié)議中的方法
2.協(xié)議中的require方法都是子類必須覆重的
3.協(xié)議中的optional方法都是子類可選覆重的
4.父類在想要調(diào)用的地方調(diào)用child的對應(yīng)方法(此時子類的對應(yīng)方法中不能調(diào)用父類的super的同方法,否則會死循環(huán))
當(dāng)然,濫用子類多態(tài)可能會導(dǎo)致類的功能不單純,實際上在工作中,不要再覆重方法中執(zhí)行與方法本意不相關(guān)的邏輯,需要判斷此處是否真的需要多態(tài),把可以不用多態(tài)的地方,可以使用IOP,提高代碼的可移植性。
封裝
概念:隱藏對象的屬性及實現(xiàn)細(xì)節(jié),僅對外公開接口。
這篇文章中主要討論的是數(shù)據(jù)結(jié)構(gòu)和函數(shù)實現(xiàn)是否應(yīng)該連在一起的問題。(在去model化這篇文章中也討論了數(shù)據(jù)結(jié)構(gòu)應(yīng)該怎么處理的問題)
觀點是不是所有的東西都需要專門封裝成對象,函數(shù)只需要它需要的參數(shù)即可,如果盡可能所有的數(shù)據(jù)都有一個普適的容器用來傳遞(如實現(xiàn)某協(xié)議的id,dic之類),這樣就能做到降低耦合。而且這樣做是更加傾向與組合而不是繼承,可以避免很多不恰當(dāng)?shù)睦^承。
具體做法:
1.字典
2.IOP
總結(jié):面向?qū)ο笤诩軜?gòu)設(shè)計時是一種非常好的程序設(shè)計思想,但是如果將其簡單的映射到程序?qū)崿F(xiàn)上來,可能會有水土不服的情況。