此为历史版本和 IPFS 入口查阅区,回到作品页
kirato
IPFS 指纹 这是什么

作品指纹

《K的技術學習筆記》——良好OOP的設計原則:<SOLID Principles>(五)

kirato
·
·
SOLID Principles的I就是接口隔離(Interface segregation principle)

接口隔離(Interface Segregation Principle)

Client只依賴它所需要使用的方法。因此,以功能性去劃分及創建不同的Interface,再以組合形式創造class。若果不劃分功能性把所有方法集中在一個Interface,哪class就可能持有用不到的方法,必須覆寫該方法。這樣就會違反上一篇所說的里氏替換原則(Liskov Substitution Principle)。遵守接口隔離,能確保class不會持有不需要的方法,防止了不可預測的bug,而且具有彈性,可以以不同Interface組合出需要的class,方便日後的擴展及使用多態(Polymorphism)。

現在我們以動物來做例子。

動物介面(Animal Interface)

現在我們有一個動物Interface,動物可能有的行為分別是進食(eat),喝水(drink),走路(walk),游泳(swim)和飛行(fly)。這些行為都會為他寫一個方法,在建構一個需要實作動物Interface的class時,實作這些方法。

狗(Dog)

狗是動物的一種,因此,他要實作所有動物Interface的方法。可是這裡有個問題,他是不會飛的。他因為動物Interface而有飛行(fly)的方法,但是這方法其實他是不需要的。

鳥(Bird)

他和狗一樣都有所有動物Interface的方法。他們都有個問題,鳥不一定會游泳。他因為動物Interface而有游泳(swim)的方法,但是這方法其實他是不需要的。

企鵝(Penguin)

他是鳥的一種,他繼承鳥class,但是他並不會飛行,只會游泳。在這裡我們只好覆寫飛行(fly)和游泳(swim)兩個方法,但這就有可能違反了里氏替換原則(Liskov Substitution Principle)。

對於這種因為繼承了class或是實作Interface,而出現了不需要的方法,這會導致其他開發人員用了不該用的方法,從而產生了bug,就像上一篇里氏替換原則(Liskov Substitution Principle)中的不會飛的鳥參加飛行比賽。我們有時對於要如何實作不需要的方法,也是一個問題。這是因為我們不知其他人會如何使用他,所以不知道如何編寫才不會有問題。如果我們現在要寫一個鴕鳥的class,除了加他的新行為,還要記得覆寫他不需要的方法,這會浪費開發時間。

現在我們來看看遵守接口隔離的例子。

動物介面(Animal Interface)<遵守接口隔離>

現在動物只有三個行為,分別只有進食(eat),喝水(drink)和走路(walk)。

飛行介面(Volant)<遵守接口隔離>

跟據功能性劃分,我們現在有一個飛行interface,而當中只有飛行(fly)這一方法。

游泳介面(Volant)<遵守接口隔離>

跟據功能性劃分,我們現在有一個游泳interface,而當中只有游泳(swim)這一方法。

狗(Dog)<遵守接口隔離>

這次狗就繼承動物和游泳Interface,他只需要實作他會用到的方法。

鳥(Bird)<遵守接口隔離>

這次鳥實作動物Interface,和狗一樣只實作他會用到的方法。

企鵝(Penguin)<遵守接口隔離>

企鵝繼承鳥class和實作游泳Interface,他不需要再實作進食(eat),喝水(drink)和走路(walk)。因為鳥class已經實作了,而他都繼承這些行為。這次他多了一個功能,就是能游泳。這次我們就只需實作游泳(swim)。

鷹(Eagle)<遵守接口隔離>

鷹繼承鳥class和實作飛行Interface,他和企鵝一樣已繼承鳥class的所有方法。這次他多了一個功能,就是能飛行。這次我們就只需實作飛行(fly)。

結論

遵守接口隔離,class就少了不需要的方法。這樣我們就不用覆寫不需要的方法,減少違反里氏替換原則(Liskov Substitution Principle)的機會。再加上按功能性劃分了不少Interface,我們可以用不同Interface組合要用的class,這是重用代碼的一個例子,而且這樣我們就可以做到下一章講解的依賴轉換(Dependency inversion principle)。

這樣還能更好的維護和擴展我們的代碼,當我們要創造一個和舊有相似的class時,可以使用繼承和實作相應想加入的Interface。這樣重覆的代碼就減少,而且可以使用多態(Polymorphism),令代碼更簡潔。

簡單說,就是不把所有方法都放在一個Interface裡,而是按功能性拆散為不同Interface,從而減少不必要的代碼,例如不會用到的方法。

CC BY-NC-ND 2.0 授权