1. 程式人生 > >對 橋接模式 的個人理解,以及與 工廠方法模式、建造者模式 的結合運用

對 橋接模式 的個人理解,以及與 工廠方法模式、建造者模式 的結合運用

學習了一段時間設計模式,就想分享一下自己的理解, 歡迎大家多多指點,指出不足之處哈

橋接模式:以商店與手機為例子來描述,先從簡單的依賴關係說起


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研究中心共同開發的,是一個