1. 程式人生 > >設計模式--中介者模式(Mediator)

設計模式--中介者模式(Mediator)

 本文是設計模式學習筆記的第三篇文章,主要分析的是中介者模式。是清華大學出版社的《研讀設計模式》的讀書筆記。在此感謝原作者。

這次應用的是一個例項去理解中介者模式

先來看這樣一個例項,電腦播放電影。

我們需要一個DVD,然後放入播放器中,播放器獲得資料傳遞給CPU處理在將資料傳給顯示卡和音效卡,迴圈這個流程。簡單麼?

實際上,如果沒有主機板,各部件要自行互動的話是非常複雜的,而且各個配件的介面不同,還要進行轉化才能匹配,這是多麼煩躁的事情。

所以,我們的電腦上會有主機板,每個配件只需要做自己的本職工作就好,做好的東西給主機板,需要的東西從主機板拿。主機板就是一箇中介者。

在軟體開發上,其實就是解耦

。如果每個類都需要和其他類進行互動,那麼當一個類發生改變的時候,其他類也要改變,我們可不希望這樣。

讓我們看看應用中介者模式模擬的電腦播放電影的過程。體驗下中介者所幹的事情。

先準備好CD,在工程下建立一個a.txt檔案,內容如下:

READY?GO!,碾碎他們
~\(≧▽≦)/~,啦啦啦德瑪西亞
~\(≧▽≦)/~~\(≧▽≦)/~,啦啦啦啦德瑪西亞
~\(≧▽≦)/~~\(≧▽≦)/~~\(≧▽≦)/~,德瑪德瑪德瑪西亞
  ╭︿︿︿╮     ,{/ o  o /}
 ( (oo) )  , ︶ ︶︶    
>>>>FIRST BLOOD<<<<,FIRST BLOOD

首先是CD類:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class CD {

	//設定cd
	private String filePath = null;
	
	private File myFile = null;
	
	public File getFile(){
		return myFile;
	}
	
	public CD(String filePath){
		this.filePath = filePath;
		myFile = new File(filePath);
	}
	
}


然後是中介者介面:

public interface Mediator {

	/**
	 * 同時物件在自身改變的時候來通知中介者的方法
	 * 讓中介者去負責相應的與其他同時物件的互動
	 * @param colleague 同時物件自身,好讓中介者物件通過物件例項
	 *                  去獲取同時物件的狀態
	 */
	public void changed(Colleague colleague);
}


然後是實現中介者介面的主機板類:

public class MotherBoard implements Mediator{

	private CDDriver cdDriver = null;
	
	private CPU cpu = null;
	
	private VideoCard videoCard = null;

	private SoundCard soundCard = null;

	public void setCdDriver(CDDriver cdDriver) {
		this.cdDriver = cdDriver;
	}

	public void setCpu(CPU cpu) {
		this.cpu = cpu;
	}

	public void setVideoCard(VideoCard videoCard) {
		this.videoCard = videoCard;
	}

	public void setSoundCard(SoundCard soundCard) {
		this.soundCard = soundCard;
	}
	
	public void changed(Colleague colleague){
		if(colleague == cdDriver){
			//表示光碟機讀取資料了
			this.opeCDDriverReadData((CDDriver)colleague);
		}else if (colleague == cpu) {
			//表示CPU處理完了
			this.opeCPU((CPU)colleague);
		}
	}
	
	/**
	 * 處理光碟機讀取資料後與其他物件的互動
	 * @param cdDriver 光碟機物件
	 */
	public void opeCDDriverReadData(CDDriver cdDriver){
		//1:先獲取光碟機讀取的資料
		String data = cdDriver.getData();
		//2:把這些資料傳遞給CPU進行處理
		this.cpu.executeData(data);
	}
	
	public void opeCPU(CPU cpu){
		//獲取CPU處理後的資料
		String videoData = cpu.getVideoData();
		String soundData = cpu.getSoundData();
		//把這些資料傳遞給顯示卡和音效卡
		this.videoCard.showData(videoData);
		this.soundCard.soundData(soundData);
	}

}


然後是同事(部件)的父類(抽象類):

public abstract class Colleague {

	private Mediator mediator;
	
	public Colleague(Mediator mediator){
		this.mediator = mediator;
	}
	
	public  Mediator getMediator() {
		return mediator;
	}
}


然後是部件CDDriver類:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * 光碟機類,一個同事類
 * 
 * @author qian.xu
 * 
 */
public class CDDriver extends Colleague {

	public CDDriver(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}

	/**
	 * 光碟機讀出來的資料
	 */
	private String data = "";

	/**
	 * 光碟機讀取出來的資料
	 * 
	 * @return 光碟機讀取出來的資料
	 */
	public String getData() {
		return this.data;
	}

	/**
	 * 讀取光碟機
	 */
	public void readCD(CD cd) {

		try {

			File file = cd.getFile();
			FileReader reader = new FileReader(file);
			BufferedReader br = new BufferedReader(reader);
			while ((data = br.readLine()) != null) {
				this.getMediator().changed(this);
				Thread.sleep(3000);
			}

			br.close();
			reader.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


然後是部件CPU類:

/**
 * COU,一個同事類
 * @author qian.xu
 *
 */
public class CPU extends Colleague{

	public CPU(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}

	/**
	 * 分解出來的視訊資料
	 */
	private String videoData = "";
	/**
	 * 分解出來的音訊資料
	 */
	private String soundData = "";
	
	/**
	 * 獲取分解出來的視訊資料
	 * @return 分解出來的視訊資料
	 */
	public String getVideoData(){
		return videoData;
	}
	
	/**
	 * 獲取分解出來的音訊資料
	 * @return 分解出來的音訊資料
	 */
	public String getSoundData(){
		return soundData;
	}
	
	public void executeData(String data){
		//處理資料,分解視訊流和音訊流
		String[] ss = data.split(",");
		this.videoData = ss[0];
		this.soundData = ss[1];
		//通知主機板,CPU工作完成
		this.getMediator().changed(this);
	}
}


然後是部件顯示卡類:

/**
 * 顯示卡類,一個同事類
 * @author qian.xu
 *
 */
public class VideoCard extends Colleague{

	public VideoCard(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}
	
	
	/**
	 * 顯示視訊資料
	 * @param data 被顯示的資料
	 */
	public void showData(String data){
		System.out.println("視訊流:"+data);
	}
}


最後是部件音效卡類:

public class SoundCard extends Colleague{

	public SoundCard(Mediator mediator) {
		super(mediator);
		// TODO Auto-generated constructor stub
	}
	
	
	/**
	 * 音效卡工作
	 * @param data 要發出的聲音
	 */
	public void soundData(String data){
		System.out.println("音訊流:"+data);
	}

}


終於完事了,讓我們開啟播放器開電影吧,下面是測試類:

public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//創造主機板
		MotherBoard mediator = new MotherBoard();
		//建立各部件
		CD cd = new CD("a.txt");
		CDDriver cdDriver = new CDDriver(mediator);
		CPU cpu = new CPU(mediator);
		VideoCard videoCard = new VideoCard(mediator);
		SoundCard soundCard = new SoundCard(mediator);
		
		//組裝各部件到主機板上	
		mediator.setCdDriver(cdDriver);
		mediator.setCpu(cpu);
		mediator.setVideoCard(videoCard);
		mediator.setSoundCard(soundCard);
		//將CD放入播放器中
		cdDriver.readCD(cd);

	}


輸出結果(為了模仿的更像,加入了執行緒睡眠,有了延遲輸出的效果,所有建議將程式跑起來看下):

視訊流:READY?GO!
音訊流:碾碎他們
視訊流:~\(≧▽≦)/~
音訊流:啦啦啦德瑪西亞
視訊流:~\(≧▽≦)/~~\(≧▽≦)/~
音訊流:啦啦啦啦德瑪西亞
視訊流:~\(≧▽≦)/~~\(≧▽≦)/~~\(≧▽≦)/~
音訊流:德瑪德瑪德瑪西亞
視訊流:  ╭︿︿︿╮     
音訊流:    {/ o  o /}
視訊流:     ( (oo) )  
音訊流:     ︶ ︶︶    
視訊流:>>>>FIRST BLOOD<<<<
音訊流:FIRST BLOOD



中介者的本質

中介者的本質是封裝互動。中介者的目的,就是用來封裝多個物件的互動,這些互動的處理多在中介者物件裡面實現。因此中介物件的複雜程度,取決於他封裝的互動的複雜程度。

何時選用中介者模式

建議在以下情況時選用中介者模式。

★  如果一組物件之間的通訊方式比較複雜,導致相互依賴、結構混亂。可以採用中介者模式,把這些物件的互動管理起來,各個物件都只需要和中介者互動,從而使得各個物件鬆散耦合,結構也更清晰易懂。

★ 如果一個物件引用很多的物件,並直接跟這些對些物件互動,導致難以複用該物件,可以採用中介者模式,把這個物件跟其他物件的互動封裝到中介者物件裡邊,這個物件只需要和中介者物件互動就好了。

中介者模式的不足

中介者模式的一個潛在缺點是,過度集中化。如果同事物件的互動非常多,而且比較複雜,當這些複雜性全部集中到中介者的時候,會導致中介者物件變得十分複雜,難於管理和維護。

廣義中介者

在應用開發中,經常會簡化中介者模式,來使開發變得簡單,比如:

★通常會去掉同事物件的父類,這樣可以讓任意的物件,只需要相互互動,就可以成為同事。

★通常不定義Mediator介面,把具體的中介者物件實現為單例。

★同事物件不再持有中介者,而是在需要的時候直接獲取中介者物件並呼叫,對應的,中介者也不再持有物件同事,而是在具體的處理方法裡去建立,或者讀取。


相關推薦

設計模式-中介模式Mediator

中介者模式是行為型模式的一種,在Mediator中,類之間的互動行為被統一放在Mediator物件中,物件通過Mediator物件同其他物件互動。 角色和職責: 1.中介者介面(Mediator):    中介者類的抽象父類 2.具體中介者(Concrete Mediator) -

設計模式--中介模式Mediator

 本文是設計模式學習筆記的第三篇文章,主要分析的是中介者模式。是清華大學出版社的《研讀設計模式》的讀書筆記。在此感謝原作者。 這次應用的是一個例項去理解中介者模式。 先來看這樣一個例項,電腦播放電影。 我們需要一個DVD,然後放入播放器中,播放器獲得資料傳遞給CPU

設計模式——中介模式/調停模式C++實現

con 分享 else .cn sign name 得到 ted esp 1 #include <iostream> 2 #include <string> 3 4 using namespace std;

Java設計模式十一訪問者模式 中介模式

(二十一)訪問者模式 對已存在的類進行擴充套件,通常需要增加方法,但是如果需要的行為與現有的物件模型不一致,或者無法修改現有程式碼。在這種情況下,不更改類的層次結構,就無法擴充套件該層次結構的行為。如果運用了訪問者模式,就可以支援開發人員擴充套件該類層次結構的行為。 和直譯

設計模式-中介模式Java實現

1. 摘要 中介者模式可以把互相關聯的兩者解耦。這裡的互相關聯,就是關係資料庫中的關聯關係。如班級和學生的關係,每個班級有多個學生,但每個學生只屬於一個班級。(關係資料庫中的一對多關係)通過中介者模式,就能很好的實現一對多、多對多關係。本文僅介紹一對多的實現,多對多的實現與

23種設計模式--中介模式-Mediator Pattern

ole 缺點 業務 -m ram -- 成了 ons 錯誤 一、中介者模式的介紹 中介者模式第一下想到的就是中介,房子中介,婚姻中介啊等等,當然筆者也希望來個婚姻中介給我介紹一個哈哈哈,,回歸正題中介者模式分成中介者類和用戶類,根據接口編程的方式我們再把中介和用戶類

用心理解設計模式——中介模式 / 調停模式 (Mediator Pattern)

前置文章: 用心理解設計模式——設計模式的原則  設計模式相關程式碼已統一放至 我的 Github   一、定義   行為型模式之一。 Define an object that encapsulates how a set of obje

設計模式------中介模式(Mediator Pattern)

//IChatroom.h class User; class IChatroom   { public:     IChatroom();     virtual ~IChatroom();     virtual void Register(User*) = 0;     virtual void Sen

java設計模式---中介模式(Mediator pattern)

java設計模式—中介者模式(Mediator pattern) 1. 概述 如果在一個系統中物件之間存在多對多的相互關係,我們可以將物件之間的一些互動行為從各個物件中分離出來,並集中封裝在一箇中介者物件中,並由該中介者進行統一協調,這樣物件之間多對多的複雜

大話設計模式中介模式

java string word 實例 發生 scrip ron 成了 維護 中介者模式(Mediator Pattern)是用來減少多個對象和類之間的通信復雜性。這種模式提供了一個中介類,該類通常處理不同類之間的通信,並支持松耦合。使代碼易於維護。中介

設計模式------中介模式

而且 作用 dos some 自己的 eth pan 沒有 self 中介者模式定義 用一個中介對象封裝一系列的對象交互,中介者使各對象不需要顯示地相互作用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。 Mediator抽象中介者角色 抽象中介者角色定義統一的接

設計模式——中介模式

解耦 用戶名 進行 edi 目標 tac visitor 適用場景 行為 中介者模式定義 中介者對象封裝系列的對象交互,中介者使得對象不需要顯示地相互作用,從而松耦合,能夠獨立改變它們之間的交互。 中介者模式角色 抽象中介者: 用於各個同事類之間的通信,同事類對象到中介者

設計模式-中介模式

設計模式 中介者模式 場景:服務端與客戶端通過webSocket方式通話,websocket充當中介 abstract class TongXinObject { protected Agency agency; public TongXinO

設計模式 --- 中介模式

1.定義 中介者模式包裝了一系列物件相互作用方式,使得這些物件不必相互明顯作用。從而使他們可以鬆耦合。當某些物件之間作用發生改變的時候,不會立即影響其他的一些物件之間的作用。保證這些作用可以彼此獨立變化。中介者模式將多對多的相互作用轉化為一對多的相互作用。中介者模式將物件的行為和協作抽象化,把物

設計模式-行為型模式-中介模式

設計模式-行為型模式-中介者模式 行為型模式 劃分類和物件的職責。 中介者模式 進銷存管理,即採購,銷售,庫存。 其中類圖 程式碼如下 public class Purchase { // 採購IBM電腦 public void buyIBMcomputer(int numb

java23種設計模式-中介模式

定義 用一箇中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。 角色 Colleague:是一個抽象類或者介面,提供和其他Colleague通訊的方法 notify(String nam

設計模式 | 中介模式及典型應用

本文的主要內容: 介紹中介者模式 資料同步示例 中介者模式總結 原始碼分析中介者模式的典型應用 Java Timer 中的中介者模式 中介者模式 世界上存在著各種各樣的資料庫,不同資料庫有各自的應用場景,對於同一份資料,最開始可能使用關係型資料庫(如M

移動開發之設計模式- 中介模式(IOS&Android)

資源 完全參照 直譯器模式|菜鳥教程但不包括IOS程式碼 中介者模式 中介者模式(Mediator Pattern)是用來降低多個物件和類之間的通訊複雜性。這種模式提供了一箇中介類,該類通常處理不同類之間的通訊,並支援鬆耦合,使程式碼易於維護。中介者模式屬於行為型模式。 介紹

“戲”說設計模式——中介模式

首先請出今天的主人公——“丐幫幫主”喬峰  蕭峰一生有情有義,對愛情堅貞,對國家和民族忠誠,人生經歷坎坷悲壯,其胸襟氣吞山河,他提倡人道和平,選擇為拯救世人而自我毀滅,是一個心繫蒼生、悲天憫人、思想境界超越國界和民族的悲劇英雄。 中介者模式簡介: 中介是作用於多個事物

設計模式- 中介模式

中介者模式 在我們做遊戲的時候,我們會把整體分為幾個系統,如戰鬥系統,介面系統等等。在類的數量比較小的時候,我們只需要相互呼叫就可以輕鬆的解決問題。但是當類的數量變多了之後,類之間相互依賴相互呼叫的話,首先破壞了單一職責原則。 單一系統引入太多其他系統的功能,不易於維護。若要是被太多其他系統