【设计模式之美】<Reading Notes>继承与组合
繼承缺點
繼承是面向對象的四大特性之一,用來表示類之間的 is-a 關系,可以解決代碼復用的問題。雖然繼承有諸多作用,但繼承層次過深、過復雜,也會影響到代碼的可維護性。在這種情況下,我們應該盡量少用,甚至不用繼承.
使用組合替換繼承
繼承主要有三個作用:表示 is-a 關系,支持多態特性,代碼復用。而這三個作用都可以通過組合、接口、委托三個技術手段來達成。
設計一個關于鳥的類,使用組合、接口、委托完成
定義為一個抽象類 AbstractBird,麻雀、鴿子、烏鴉等,都繼承這個抽象類。由于不是所有鳥都會飛,所以不是所有鳥都有fly()這個方法。
我們可以從鳥會不會飛、會不會叫來對鳥進行劃分。兩個行為搭配起來會產生四種情況:會飛會叫、不會飛會叫、會飛不會叫、不會飛不會叫。如果假如新行為,我們可能還需要繼續構建更加細分的抽象類,這樣就比較麻煩。繼承層次過深、繼承關系過于復雜會影響到代碼的可讀性和可維護性。
可以利用組合(composition)、接口、委托(delegation)三個技術手段解決這個問題。
接口表示具有某種行為特性:
可以定義一個 Flyable 接口,只讓會飛的鳥去實現這個接口。
對于會叫、會下蛋這些行為特性,我們可以類似地定義 Tweetable 接口、EggLayable 接口。
1、定義接口
2、通過多個接口實現多個特性:鴕鳥不會飛,但是會叫會下蛋,所以只有兩個接口。注意,mplements 是實現多個接口, 接口的方法一般為空的, 必須重寫才能使用 。
public class Ostrich implements Tweetable, EggLayable {//鴕鳥 //... 省略其他屬性和方法... @Override public void tweet() { //... } @Override public void layEgg() { //... } }3、接口只聲明方法,不定義實現。也就是說,每個會下蛋的鳥都要實現一遍 layEgg() 方法,并且實現邏輯是一樣的,這就會導致代碼重復的問題。
可以針對三個接口再定義三個實現類:
實現了 fly() 方法的 FlyAbility 類、
實現了 tweet() 方法的 TweetAbility 類、
實現了 layEgg() 方法的 EggLayAbility 類。
然后,通過組合和委托技術來消除代碼重復:
public class Ostrich implements Tweetable, EggLayable {//鴕鳥 private TweetAbility tweetAbility = new TweetAbility(); //組合 private EggLayAbility eggLayAbility = new EggLayAbility(); //組合 //... 省略其他屬性和方法... @Override public void tweet() { tweetAbility.tweet(); // 委托 }@Override public void layEgg() { eggLayAbility.layEgg(); // 委托 } }由于對Java不太熟悉,可能還需要關注一下這個知識點:
extends和implements區別
總結
以上是生活随笔為你收集整理的【设计模式之美】<Reading Notes>继承与组合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C++基础】模板基础与函数模板
- 下一篇: dnf2012盛世 狂欢 不是永久的乜?