對 橋接模式 的個人理解,以及與 工廠方法模式、建造者模式 的結合運用
學習了一段時間設計模式,就想分享一下自己的理解, 歡迎大家多多指點,指出不足之處哈
橋接模式:以商店與手機為例子來描述,先從簡單的依賴關係說起
public interface Phone { /** 充電 **/ void charge(); /** 解鎖 **/ void unlock(); } public class ApplePhone implements Phone { public void charge() { System.out.println("普通充電"); } public void unlock() { System.out.println("指紋解鎖"); } } public class SonyPhone implements Phone { public void charge() { System.out.println("快充"); } public void unlock() { System.out.println("面部解鎖"); } } public class Store { /** * 補充手機 */ public void supplyPhone() { Phone phone = new SonyPhone(); // 補充手機邏輯... System.out.println("補充手機完成"); } }
上面這類圖很簡單,就是Phone介面有兩個實現。Store只依賴Phone介面,不依賴具體實現,這樣方便Store更換手機。
如果現在,想增加個實現,NokiaPhone,而且有以下要求:
1、NokiaPhone的charge方法,要跟SonyPhone的一樣,同樣是快充。
2、NokiaPhone的unlock方法,要跟ApplePhone的一樣,同樣是指紋解鎖。
看到第1點,就讓人毫不猶豫想到,可以讓NokiaPhone繼承SonyPhone。
接著看到2點,就發現 NokiaPhone繼承SonyPhone 帶來的問題了。NokiaPhone無法通過繼承ApplePhone來重用指紋解鎖(不能繼承多個類),只能硬生生的複製ApplePhone的過來用。如下
public class NokiaPhone extends SonyPhone {
public void unlock() {
System.out.println("指紋解鎖");
}
}
由此可見,繼承也會出現程式碼不能複用的問題
除此之外,若現在NokiaPhone想增加個功能 照相(takePicture)。由於Store依賴的是Phone,所以Phone得加takePicture方法
從程式碼看,一旦其中一個實現增加特有的功能,其它的實現都得修改,增加很多空實現的程式碼。public interface Phone { /** 充電 **/ void charge(); /** 解鎖 **/ void unlock(); /** 照相 **/ void takePicture(); } public class ApplePhone implements Phone { public void charge() { System.out.println("普通充電"); } public void unlock() { System.out.println("指紋解鎖"); } public void takePicture() { // 空實現 return; } } public class SonyPhone implements Phone { public void charge() { System.out.println("快充"); } public void unlock() { System.out.println("面部解鎖"); } public void takePicture() { // 空實現 return; } } public class NokiaPhone extends SonyPhone { public void unlock() { System.out.println("指紋解鎖"); } public void takePicture() { System.out.println("雙攝"); } }
小結:繼承,不能很好解決程式碼重用,而且不方便擴充套件。
再看回原來的SonyPhone、ApplePhone實現的方法,可以歸類得出
charge: 普通充電,快充
unlock: 指紋解鎖,面部解鎖
之後新增的NokiaPhone相當於從上面每個功能,分別抽取所需的實現來組合而成。
這樣有沒感覺,若將 普通充電,快充,指紋解鎖,面部解鎖 分別放到不同的類,然後只要將按需set到NokiaPhone中即可。
事實上橋接模式,就類似這思路。
大家應該發現,這類圖跟大家經常看到的不同,Abstraction缺少了個子類RefineAbstraction。由於本小白一直想不通RefineAbstraction的作用,所以也想通過這文章,希望各位大神能拔刀相助。
下面根據本例畫上相應的類圖
public interface Locker {
void unlock();
}
public class FaceLocker implements Locker {
public void unlock() {
System.out.println("指紋解鎖");
}
}
public class FingerprintLocker implements Locker {
public void unlock() {
System.out.println("面部解鎖");
}
}
////////////////////////////
public interface Charger {
void charge();
}
public class QuickCharger implements Charger {
public void charge() {
System.out.println("普通充電");
}
}
public class SimpleCharger implements Charger {
public void charge() {
System.out.println("快充");
}
}
////////////////////////////
public class Phone {
private Charger charger;
private Locker locker;
public void charge() {
if (charger == null) {
return;
}
charger.charge();
}
public void unlock() {
if (locker == null) {
return;
}
locker.unlock();
}
public void setCharger(Charger charger) {
this.charger = charger;
}
public void setLocker(Locker locker) {
this.locker = locker;
}
}
////////////////////////////
public class Store {
/**
* 補充手機
*/
public void supplyPhone() {
Phone phone = getNokiaPhone();
// 補充手機邏輯...
System.out.println("補充手機完成");
}
private Phone getSonyPhone(){
Phone phone = new Phone();
phone.setCharger(new QuickCharger());
phone.setLocker(new FaceLocker());
return phone;
}
private Phone getApplePhone(){
Phone phone = new Phone();
phone.setCharger(new SimpleCharger());
phone.setLocker(new FingerprintLocker());
return phone;
}
private Phone getNokiaPhone(){
Phone phone = new Phone();
phone.setCharger(new QuickCharger());
phone.setLocker(new FingerprintLocker());
return phone;
}
}
用了橋接模式的話,Store就可以隨意組合出所需的手機種類。
大家可能問,使用者類Store要是更換其它種類手機,就得修改程式碼,不科學呀。
這問題就牽涉到 如何獲取例項物件 問題,橋接模式解決的只是如何處理例項物件依賴 問題。(後面將提到如何結合 工廠方法模式,建造者模式 來方便獲取不同的手機)
此時若新增 照相功能(takePicture)
public interface Camera {
void takePicture();
}
public class DoubleCamera implements Camera {
public void takePicture() {
System.out.println("雙攝");
}
}
///////////////////////////////
public class Phone {
private Charger charger;
private Locker locker;
private Camera camera;
public void charge() {
if (this.charger == null) {
return;
}
this.charger.charge();
}
public void unlock() {
if (locker == null) {
return;
}
this.locker.unlock();
}
public void takePicture() {
if (this.camera == null) {
return;
}
this.camera.takePicture();
}
public void setCharger(Charger charger) {
this.charger = charger;
}
public void setLocker(Locker locker) {
this.locker = locker;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
}
///////////////////////////////
public class Store {
/**
* 補充手機
*/
public void supplyPhone() {
Phone phone = getNokiaPhone();
// 補充手機邏輯...
System.out.println("補充手機完成");
}
private Phone getSonyPhone(){
Phone phone = new Phone();
phone.setCharger(new QuickCharger());
phone.setLocker(new FaceLocker());
return phone;
}
private Phone getApplePhone(){
Phone phone = new Phone();
phone.setCharger(new SimpleCharger());
phone.setLocker(new FingerprintLocker());
return phone;
}
private Phone getNokiaPhone(){
Phone phone = new Phone();
phone.setCharger(new QuickCharger());
phone.setLocker(new FingerprintLocker());
phone.setCamera(new DoubleCamera());
return phone;
}
}
此時Phone類只需增加一個takePicture方法,而且Store類,只修改了getNokiaPhone的方法(因為只有Nokia需要加照相功能),沒有影響到其它方法。
小結:一類產品(本例的Phone)若多維上有多個不同實現(charge、camera、takePicture等方法都有多個實現)。此時若使用繼承,會出現 程式碼難以重用、新增維度不方便 等問題,此時適合使用橋接模式
public interface PhoneBuilder {
void buildCharger();
void buildLocker();
Phone getResult();
}
public class ApplePhoneBuilder implements PhoneBuilder {
private Phone phone = new Phone();
public void buildCharger() {
phone.setCharger(new SimpleCharger());
}
public void buildLocker() {
phone.setLocker(new FingerprintLocker());
}
public Phone getResult() {
return phone;
}
}
public class SonyPhoneBuilder implements PhoneBuilder {
private Phone phone = new Phone();
public void buildCharger() {
phone.setCharger(new QuickCharger());
}
public void buildLocker() {
phone.setLocker(new FaceLocker());
}
public Phone getResult() {
return phone;
}
}
///////////////////////////////
public class PhoneDirector {
public Phone construct(PhoneBuilder builder) {
builder.buildCharger();
builder.buildLocker();
return builder.getResult();
}
}
public interface PhoneFactory {
Phone getPhone();
}
public class ApplePhoneFactory implements PhoneFactory {
private PhoneDirector director = new PhoneDirector();
public Phone getPhone() {
ApplePhoneBuilder builder = new ApplePhoneBuilder();
return director.construct(builder);
}
}
public class SonyPhoneFactory implements PhoneFactory {
private PhoneDirector director = new PhoneDirector();
public Phone getPhone() {
SonyPhoneBuilder builder = new SonyPhoneBuilder();
return director.construct(builder);
}
}
///////////////////////////////
public class Store {
private PhoneFactory phoneFactory;
public Store(PhoneFactory phoneFactory) {
super();
this.phoneFactory = phoneFactory;
}
/**
* 補充手機
*/
public void supplyPhone() {
Phone phone = phoneFactory.getPhone();
// 補充手機邏輯...
System.out.println("補充" + phone.getBrand() + "手機完成");
}
public static void main(String[] args) {
StoreB storeB = new StoreB(new SonyPhoneFactory());
storeB.supplyPhone();
}
}
總結:
橋接模式將一類產品(本例的手機)的多維變化(charge、unlock方法各有不同實現),抽取成單獨的類(Charger、Locker等實現)。
建造者模式的Builder角色負責從每個維度選取所需的實現類
工廠類,最後就變成只需將對應的Builder傳入到Director裡,呼叫Director開始按順序建造。
相關推薦
對 橋接模式 的個人理解,以及與 工廠方法模式、建造者模式 的結合運用
學習了一段時間設計模式,就想分享一下自己的理解, 歡迎大家多多指點,指出不足之處哈 橋接模式:以商店與手機為例子來描述,先從簡單的依賴關係說起 public interface Phone { /** 充電 **/ void charge(); /** 解鎖 *
對 工廠模式與建造者模式 的個人理解,以及結合運用
學習了一段時間設計模式,就想分享一下自己的理解, 歡迎大家多多指點,指出不足之處哈 個人理解,工廠模式用於處理 如何獲取例項物件 問題,建造者模式用於處理如何建造例項物件 問題(好像是廢話。。。)。兩者應該可以結合起來,下面將以商店售賣手機這場景來描述。 工廠模式: 簡單
java中構造方法的理解,super()與構造方法,無參,有參構造方法,this()與構造方法。
一、為什麼要引入構造方法。 當建立物件的時候需要對屬性值初始化,構造方法,即物件建立時要執行的方法。 要求在例項化的同時,就指定好name,和age的值。這就要用到構造方法。又叫做構造器Constructor. 二、構造方法的定義格式 構造方法在new的時候自動執行。且只執
java設計模式精講 Debug 方式+記憶體分析 第7章 建造者模式
建造者模式 7-1 建造者模式講解 7-2 建造者模式coding 7-3 建造者模式原始碼解析(jdk+guava+spring+mybatis) 7-1 建造者模式講解 7-2 建造者
設計模式學習總結(2)單例模式、建造者模式、原型模式
單例模式(Singleton Pattern) 這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。 單例模式有以下三點注意: 1、單例類只能有一個例項。 2、單
設計模式與XML(二)建造者模式和單例模式(C++)
一、實驗目的及要求 1、掌握建立型模式的概念。 2、掌握工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式的構造方式及使用情景。 二、實驗裝置(環境) 1、 軟體需求: Dev-Cpp5.4, Rational Rose / Microsoft Visio
設計模式之工廠模式、建造者模式
準備找工作那會看到了一本神書,《Head First 設計模式》,從此對設計模式有了很深的親睞,但是因為自己的專案經驗少的可憐,所以也基本沒有用過這些神一樣的方法,時間一長也就都忘乾淨了。現在工作了,師兄給了一個500M的程式碼,讓我吃透它。這期間真的有很多問題,很迷惑。忽
Picasso原始碼分析(四):不變模式、建造者模式和Request的預處理
Request的不變模式(Immutable Pattern) 不變模式可增強物件的強壯型,允許多個物件共享某一個物件,降低了對該物件進行併發訪問時的同步化開銷。如果需要修改一個不變物件的狀態,那麼就需要建立一個新的同類型物件,並在建立時將這個新的狀態
java23種設計模式——五、建造者模式
原始碼在我的[github](https://github.com/witmy/JavaDesignPattern)和[gitee](https://gitee.com/witmy/JavaDesignPattern)中獲取 # 目錄 [java23種設計模式—— 一、設計模式介紹](https://www.
設計模式 #3 (原型模式、建造者模式)
# 設計模式 #3 (原型模式、建造者模式) --- **文章中所有工程程式碼和`UML`建模檔案都在我的這個`GitHub`的公開庫--->[DesignPattern](https://github.com/L1ng14/DesignPattern)。**`Star`來一個好嗎?秋梨膏! ---
對巨集觀的力學中連續介質假設的理解,以及對流體力學中平均速度的理解
對巨集觀的力學中連續介質假設的理解: 巨集觀的力學(如流體力學、彈塑性力學等)研究的物件是大量分子的集合,這時候每個集合構成一個個小微元體,整個物件就是由這無數個小微元體連續無間隙地構成。因為我們只需要關注每個集合上物件的性質,如密度、速度、應力、形變等,不需要
初識Kafka----個人理解,希望對喜歡kafka的朋友有幫助
1、什麼是kafka? kafka是一個釋出訂閱系統,主要用作快取 2、核心概念 首先kafka是一個叢集,有很多個節點組成。 Broker['brəʊkə]:節點名稱每一個節點稱作broker me
Python中np.sum()對axis的個人理解,超詳細
你們討論的axis=0和1並不是簡單的行和列,axis=0表示的是第一個維度,在第一個維度上的元素間進行求和、比較大小,axis=1表示的是第二個維度,在第二個維度上的元素間進行求和、比較大小。一個維度的元素並不總是單值,有時候是一個數組或矩陣等等,這時候就要
代理模式,簡單(靜態)工廠模式,單例模式,模板方法模式個人理解
簡言: java中總共有23種設計模式,每個模式的出現都是為了解決某一方面的問題,所以這23種設計模式有他們各自適用的地方(廢話有點多),而設計模式的產生主要是為了降低類與類之間的耦合度。下面我們就簡單的瞭解一下幾種設計模式及使用的地方。 1.單例模式:
對Yii2中 yiiwebUser的理解,和自建的appmodelsUser(基礎版),frontendmodelsUser的應用原理
end his iat getter authent property 用戶id tails uniq yii\web\User 是一個統稱,為用戶,沒有具體實例,只能管理; 此處以app\models\User為基準; app\models\User 是映射數據表us
關於FFT的一些理解,以及如何手工計算FFT加深理解和驗證正確性
以及 手工 fft ges 系統 -1 nbsp 邏輯性 分享 總結缺少邏輯性和系統性,主要便於自己理解和記憶 關於FFT的一些理解,以及如何手工計算FFT加深理解和驗證正確性
QT初體驗1:如何學習QT之個人淺見,以及如何讀取文本文件,在調試信息中輸出。
沒有 c++教程 最簡 將不 ror 聽說 講解 知識點 括號 2017年11月初,隨著工作崗位的調動,我轉到了研發崗,開始了漫漫程序員的成長之路。首先介紹下個人知識儲備,大一學習過C語言,沒有工程經驗,所學是為了期末考試+2級考試,考完在大學+碩士期間沒有用到編程。 來到
軟件工程作業2.1:闡述對軟件工程的理解,學完這門課自己能學到什麽,學完後能做什麽
包括 數據結構和算法 很多 上線 可維護性 修復 學習 應用 實現 對軟件工程這門課的理解 軟件工程是把系統的、有序的、可量化的方法應用到軟件的開發、運營和維護上的過程。在軟件工程中,遠遠不止很多人以為的只是單純地進行軟件開發,其實真正的軟件開發的時間只是軟件工程中的一
對display主要屬性的探究,以及vertical-aligin
lln nbsp AD pad 沒有 com block ccf 圖片 display 首先要簡單說明一下display的主要3個主要屬性,分別為block,inline-block,inline,這裏只提及主要,關於其他的inherit,none等可以自行了解 inl
Linux搭建 iSCSI 共享存儲 個人理解,詳細配置 centos7
iscsi;網絡存儲 官方解釋: iSCSI( Internet Small Computer System Interface 互聯網小型計算機系統接口)是由IBM 下屬的兩大研發機構一一加利福尼亞AImaden和以色列Haifa研究中心共同開發的,是一個