舉個栗子
在M和N兩種品牌的手機里面各做通訊錄和游戲兩種軟體,前提:M和N手機之間不通用,
反例思路1
以手機品牌為主體,各自實作軟體,

反例思路2
以手機軟體為主體,各自適配品牌,

弊端說明
- 物件的繼承關系是在編譯時就定義好了,所以無法在運行時改變從父類繼承的實作,
- 子類的實作與它的父類有非常緊密的依賴關系,以至于父類實作中的任何變化必然會導致子類發生變化,
- 當你需要復用子類時,如果繼承下來的實作不適合解決新的問題,則父類必須重寫或被其他更適合的類替換,
- 這種依賴關系限制了靈活性并最終限制了復用性,
引申:合成/聚合復用原則(CARP)
定義
即:盡量使用合成/聚合,盡量不要使用類繼承,
- 聚合表示一種弱的‘擁有’關系,體現的是A物件可以包含B物件,但B物件不是A物件的一部分;
- 合成則是一種強的‘擁有關系’,體現了嚴格的部分和整體的關系,部分和整體的生命周期一樣,
好處
優先使用物件的合成/聚合將有助于你保持每個類被封裝,并被集中在單個任務上,這樣的類和類繼承層次會保持較小的規模,并且不太可能增長為不可控制的龐然大物,
應用上述原則對例子進行改造

Talk is cheap, show me the code
(屁話少說,放碼過來)
/**
* 手機軟體
* Created by callmeDevil on 2019/12/14.
*/
public abstract class HandsetSoft {
public abstract void run();
}
/**
* 手機游戲
* Created by callmeDevil on 2019/12/14.
*/
public class HandsetGame extends HandsetSoft{
@Override
public void run() {
System.out.println("運行手機游戲");
}
}
/**
* 手機通訊錄
* Created by callmeDevil on 2019/12/14.
*/
public class HandsetAddressList extends HandsetSoft{
@Override
public void run() {
System.out.println("運行手機通訊錄");
}
}
/**
* 手機品牌
* Created by callmeDevil on 2019/12/14.
*/
public abstract class HandsetBrand {
protected HandsetSoft soft;
// 設定手機軟體
public void setHandsetSort(HandsetSoft sort){ // 品牌需要關注軟體,所以可在機器中安裝軟體,以備運行
this.soft = sort;
}
public abstract void run();
}
/**
* 手機品牌M
* Created by callmeDevil on 2019/12/14.
*/
public class HandsetBrandM extends HandsetBrand{
@Override
public void run() {
soft.run();
}
}
/**
* 手機品牌N
* Created by callmeDevil on 2019/12/14.
*/
public class HandsetBrandN extends HandsetBrand{
@Override
public void run() {
soft.run();
}
}
public class Test {
public static void main(String[] args) {
HandsetBrand ab;
System.out.println("---手機品牌N:");
ab = new HandsetBrandN();
ab.setHandsetSort(new HandsetGame());
ab.run();
ab.setHandsetSort(new HandsetAddressList());
ab.run();
System.out.println("---手機品牌M:");
ab = new HandsetBrandM();
ab.setHandsetSort(new HandsetGame());
ab.run();
ab.setHandsetSort(new HandsetAddressList());
ab.run();
}
}
運行結果
---手機品牌N:
運行手機游戲
運行手機通訊錄
---手機品牌M:
運行手機游戲
運行手機通訊錄
需求變更
增加一個MP3音樂播放功能,只需要添加一個類,其他無需改造
/**
* 手機MP3
* Created by callmeDevil on 2019/12/14.
*/
public class HandsetMP3 extends HandsetSoft{
@Override
public void run() {
System.out.println("運行手機MP3");
}
}
如果是增加一個品牌,也只需要添加一個類
/**
* 手機品牌S
* Created by callmeDevil on 2019/12/14.
*/
public class HandsetBrandS extends HandsetBrand{
@Override
public void run() {
soft.run();
}
}
橋接模式
定義
將抽象部分與它的實作部分分離,使它們都可以獨立的變化,
需要注意的是,實作分離,并不是說讓抽象類與其派生類分離,因為這沒有任何意義,實作指的是抽象類和它的派生類用來實作自己的物件,
UML圖

總結
- 實作系統可能有多角度的分類,每一種分類都有可能變化,那么就把這種多角度分離出來讓他們獨立,減少他們之間的耦合,
- 只要真正深入的理解了設計原則,很多設計模式其實就是原則的應用而已,或許在不知不覺中就在使用設計模式了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/32486.html
標籤:設計模式
上一篇:代理模式
