設計模式--中介者模式Mediator(行為型)

benbenxiongyuan發表於2014-04-15

1 定義:

1.1 定義:Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.(用一箇中介物件封裝一系列的物件互動,中介者使各物件不需要顯示地相互作用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。)

1.2 通用類圖:

Mediator抽象中介者角色

定義統一的介面,用於各同事角色之間的通訊。

Concrete Mediator具體中介者角色

協調各同事角色實現協作行為,因此它必須依賴於各個同事角色。

Colleague同事角色

每一個同事角色都知道中介者角色,而且與其他的同事角色通訊的時候,一定要通過中介者角色協作。每個同事類的行為分為兩種:一種是同事本身的行為,比如改變物件本身的狀態,處理自己的行為等,這種方法叫做自發行為(Self-Method),與其他同事類或中介者沒有任何的依賴;第二種是必須依賴中介者才能完成的行為,叫做依賴方法(Dep-Method)。

1.3 通用程式碼:

 
	public abstract class Mediator {
		// 定義同事類
		protected ConcreteColleague1 c1;
		protected ConcreteColleague2 c2;

		// 通過getter/setter方法吧同事類注入進來
		public ConcreteColleague1 getC1() {
			return c1;
		}

		public void setC1(ConcreteColleague1 c1) {
			this.c1 = c1;
		}

		public ConcreteColleague2 getC2() {
			return c2;
		}

		public void setC2(ConcreteColleague2 c2) {
			this.c2 = c2;
		}

		// 中介者模式的業務邏輯
		public abstract void doSomething1();

		public abstract void doSomething2();
	}

	public class ConcreteMediator extends Mediator {
		@Override
		public void doSomething1() {
			// 呼叫同事類的方法,只要是public方法都可以呼叫
			super.c1.selfMethod1();
			super.c2.selfMethod2();
		}

		public void doSomething2() {
			super.c1.selfMethod1();
			super.c2.selfMethod2();
		}
	}

	public abstract class Colleague {
		protected Mediator mediator;

		public Colleague(Mediator _mediator) {
			this.mediator = _mediator;
		}
	}

	public class ConcreteColleague1 extends Colleague {
		// 通過建構函式傳遞中介者
		public ConcreteColleague1(Mediator _mediator) {
			super(_mediator);
		}

		// 自有方法 self-method
		public void selfMethod1() {
			// 處理自己的業務邏輯
		}

		// 依賴方法 dep-method
		public void depMethod1() {
			// 處理自己的業務邏輯
			// 自己不能處理的業務邏輯,委託給中介者處理
			super.mediator.doSomething1();
		}
	}

	public class ConcreteColleague2 extends Colleague {
		// 通過建構函式傳遞中介者
		public ConcreteColleague2(Mediator _mediator) {
			super(_mediator);
		}

		// 自有方法 self-method
		public void selfMethod2() {
			// 處理自己的業務邏輯
		}

		// 依賴方法 dep-method
		public void depMethod2() {
			// 處理自己的業務邏輯
			// 自己不能處理的業務邏輯,委託給中介者處理
			super.mediator.doSomething2();
		}
	}


注意:

A Mediator抽象類中我們只定義了同事類的get/set注入,為什麼不使用抽象注入呢?這是因為同事類雖然有抽象,但是沒有每個同事類必須要完成的業務方法。當然如果每個同事類都有相同的方法,比如execute handler等,那當然注入抽象類,做到依賴倒置。

B 為什麼同事類要使用建構函式注入中介者,而中介者注入同事類只使用getter/setter方式呢?因為同事類必須有中介者,而中介者卻可以只有部分同事類

2 優點

減少類間的依賴,把原有的一對多的依賴變成了一對一依賴,同事類只依賴中介者,減少了依賴,當然同時也降低了類間的耦合。

3 缺點

中介者會膨脹得很大,而且邏輯複雜,原本N個物件直接的相互依賴關係轉換為中介者和同事類的依賴關係,同事類越多,中介者的邏輯就越複雜。

4 應用場景

類之間的聯絡是必然的,並非有多個依賴時就要使用中介者模式。中介者模式只適用於多個物件間緊密耦合的情況,緊密耦合的標準是:在類圖中出現了蜘蛛網狀結構。在這種情況下一定要考慮使用中介者模式,這有利於把蜘蛛網梳理為星型結構,使原本複雜混亂的關係變得清晰簡單。

4.1 符合上述緊密耦合標準時使用;

4.2 N個物件之間產生了相互的依賴關係(N>2);

4.3 多個物件有依賴關係,但是依賴的行為沿不確定或者有發生改變的可能,在這種情況下一般建議採用中介者模式,降低變更引起的風險擴散;

4.4 產品開發。一個明顯的例子就是MVC框架,把中介者模式應用到產品中,可以提升產品的效能和擴充套件性,但是對於專案開發就未必,因為專案是以交付投產為目標,而產品則是以穩定、高效、擴充套件為宗旨。

生活中的使用情境:

A。機場排程中心;

BMVC框架;

C。媒體閘道器;(如MSN通過伺服器轉發訊息,而飛鴿直接使用UDP廣播卻不是。)

D。各種中介服務;

5 注意事項

5.1 遵循緊密耦合的標準來用中介者模式;

5.2 中介者模式很少用到介面或抽象類,這與依賴倒置原則是衝突的:首先,既然是同事類而不是兄弟類(有相同的血緣),那就說明這些類之間是協作關係,完成不同的任務,處理不同的業務,所以不能在抽象類或介面中嚴格定義同事類必須具有的方法。因此,如果兩個物件不能提煉出共性,就不要刻意去追求兩者的抽象,抽象只要定義出模式需要的角色即可

其次,在一個專案中使用中介者模式可能被多個模組採用,每個中介者所圍繞的同事類各不相同,抽象出一個具有共性的中介者也不太可能。

6 擴充套件

7 範例

(進銷存案例,這三者間已形成了網狀關係)

加入了一箇中介者作為三個模組的交流核心每個模組之間不再相互交流,要交流就通過中介者進行。每個模組只負責自己的業務邏輯,不屬於自己的則丟給中介者來處理,簡化了各模組之間的耦合關係,類圖如下:


 
	/**
	 * @author cbf4Life cbf4life@126.com I'm glad to share my knowledge with you
	 *         all.
	 */
	public abstract class AbstractMediator {
		protected Purchase purchase;
		protected Sale sale;
		protected Stock stock;

		// 建構函式
		public AbstractMediator() {
			purchase = new Purchase(this);
			sale = new Sale(this);
			stock = new Stock(this);
		}

		// 中介者最重要的方法,叫做事件方法,處理多個物件之間的關係
		public abstract void execute(String str, Object... objects);
	}

	public class Mediator extends AbstractMediator {
		// 中介者最重要的方法
		public void execute(String str, Object... objects) {
			if (str.equals("purchase.buy")) { // 採購電腦
				this.buyComputer((Integer) objects[0]);
			} else if (str.equals("sale.sell")) { // 銷售電腦
				this.sellComputer((Integer) objects[0]);
			} else if (str.equals("sale.offsell")) { // 折價銷售
				this.offSell();
			} else if (str.equals("stock.clear")) { // 清倉處理
				this.clearStock();
			}
		}

		// 採購電腦
		private void buyComputer(int number) {
			int saleStatus = super.sale.getSaleStatus();
			if (saleStatus > 80) { // 銷售情況良好
				System.out.println("採購IBM電腦:" + number + "臺");
				super.stock.increase(number);
			} else { // 銷售情況不好
				int buyNumber = number / 2; // 折半採購
				System.out.println("採購IBM電腦:" + buyNumber + "臺");
			}
		}

		// 銷售電腦
		private void sellComputer(int number) {
			if (super.stock.getStockNumber() < number) { // 庫存數量不夠銷售
				super.purchase.buyIBMcomputer(number);
			}
			super.stock.decrease(number);
		}

		// 折價銷售電腦
		private void offSell() {
			System.out.println("折價銷售IBM電腦" + stock.getStockNumber() + "臺");
		}

		// 清倉處理
		private void clearStock() {
			// 要求清倉銷售
			super.sale.offSale();
			// 要求採購人員不要採購
			super.purchase.refuseBuyIBM();
		}
	}

中介者Mediator定義了多個private方法,其目的是處理各個物件之間的依賴關係,就是說把原有一個物件要依賴的多個物件的情況移動到中介者的private方法中實現

但在實際專案中,一般的做法是中介者按照職責進行劃分,每個中介者處理一個或多個類似的關聯請求。

 
public abstract class AbstractColleague {
		protected AbstractMediator mediator;

		public AbstractColleague(AbstractMediator _mediator) {
			this.mediator = _mediator;
		}
	}

	public class Purchase extends AbstractColleague {
		public Purchase(AbstractMediator _mediator) {
			super(_mediator);
		}

		// 採購IBM型號的電腦
		public void buyIBMcomputer(int number) {
			super.mediator.execute("purchase.buy", number);
		}

		// 不在採購IBM電腦
		public void refuseBuyIBM() {
			System.out.println("不再採購IBM電腦");
		}
	}

	public class Stock extends AbstractColleague {
		public Stock(AbstractMediator _mediator) {
			super(_mediator);
		}

		// 剛開始有100臺電腦
		private static int COMPUTER_NUMBER = 100;

		// 庫存增加
		public void increase(int number) {
			COMPUTER_NUMBER = COMPUTER_NUMBER + number;
			System.out.println("庫存數量為:" + COMPUTER_NUMBER);
		}

		// 庫存降低
		public void decrease(int number) {
			COMPUTER_NUMBER = COMPUTER_NUMBER - number;
			System.out.println("庫存數量為:" + COMPUTER_NUMBER);
		}

		// 獲得庫存數量
		public int getStockNumber() {
			return COMPUTER_NUMBER;
		}

		// 存貨壓力大了,就要通知採購人員不要採購,銷售人員要儘快銷售
		public void clearStock() {
			System.out.println("清理存貨數量為:" + COMPUTER_NUMBER);
			super.mediator.execute("stock.clear");
		}
	}

	public class Sale extends AbstractColleague {
		public Sale(AbstractMediator _mediator) {
			super(_mediator);
		}

		// 銷售IBM型號的電腦
		public void sellIBMComputer(int number) {
			super.mediator.execute("sale.sell", number);
			System.out.println("銷售IBM電腦" + number + "臺");
		}

		// 反饋銷售情況,0——100之間變化,0代表根本就沒人賣,100代表非常暢銷,出1一個賣一個
		public int getSaleStatus() {
			Random rand = new Random(System.currentTimeMillis());
			int saleStatus = rand.nextInt(100);
			System.out.println("IBM電腦的銷售情況為:" + saleStatus);
			return saleStatus;
		}

		// 折價處理
		public void offSale() {
			super.mediator.execute("sale.offsell");
		}
	}

	public class Client {
		public static void main(String[] args) {
			AbstractMediator mediator = new Mediator();
			// 採購人員採購電腦
			System.out.println("------採購人員採購電腦--------");
			Purchase purchase = new Purchase(mediator);
			purchase.buyIBMcomputer(100);
			// 銷售人員銷售電腦
			System.out.println("\n------銷售人員銷售電腦--------");
			Sale sale = new Sale(mediator);
			sale.sellIBMComputer(1);
			// 庫房管理人員管理庫存
			System.out.println("\n------庫房管理人員清庫處理--------");
			Stock stock = new Stock(mediator);
			stock.clearStock();
		}
	}

在場景類中增加了一箇中介者,然後分別傳遞到三個同事類中,三個類都具有相同的特性:只負責處理自己的活動(行為),與自己無關的活動就丟給中介者處理。

 

轉自:http://blog.csdn.net/yuanlong_zheng/article/details/7574441

相關文章