23種設計模式(7):中介者模式

定義:用一箇中介者對象封裝一系列的對象交互,中介者使各對象不須要顯示地相互做用,從而使耦合鬆散,並且能夠獨立地改變它們之間的交互。java

類型:行爲類模式編程

類圖:架構

中介者模式的結構ide

中介者模式又稱爲調停者模式,從類圖中看,共分爲3部分:this

  • 抽象中介者:定義好同事類對象到中介者對象的接口,用於各個同事類之間的通訊。通常包括一個或幾個抽象的事件方法,並由子類去實現。
  • 中介者實現類:從抽象中介者繼承而來,實現抽象中介者中定義的事件方法。從一個同事類接收消息,而後經過消息影響其餘同時類。
  • 同事類:若是一個對象會影響其餘的對象,同時也會被其餘對象影響,那麼這兩個對象稱爲同事類。在類圖中,同事類只有一個,這實際上是現實的省略,在實際應用中,同事類通常由多個組成,他們之間相互影響,相互依賴。同事類越多,關係越複雜。而且,同事類也能夠表現爲繼承了同一個抽象類的一組實現組成。在中介者模式中,同事類之間必須經過中介者才能進行消息傳遞。

爲何要使用中介者模式設計

通常來講,同事類之間的關係是比較複雜的,多個同事類之間互相關聯時,他們之間的關係會呈現爲複雜的網狀結構,這是一種過分耦合的架構,即不利於類的複用,也不穩定。例如在下圖中,有六個同事類對象,假如對象1發生變化,那麼將會有4個對象受到影響。若是對象2發生變化,那麼將會有5個對象受到影響。也就是說,同事類之間直接關聯的設計是很差的。code

若是引入中介者模式,那麼同事類之間的關係將變爲星型結構,從圖中能夠看到,任何一個類的變更,只會影響的類自己,以及中介者,這樣就減少了系統的耦合。一個好的設計,一定不會把全部的對象關係處理邏輯封裝在本類中,而是使用一個專門的類來管理那些不屬於本身的行爲。對象

咱們使用一個例子來講明一下什麼是同事類:有兩個類A和B,類中各有一個數字,而且要保證類B中的數字永遠是類A中數字的100倍。也就是說,當修改類A的數時,將這個數字乘以100賦給類B,而修改類B時,要將數除以100賦給類A。類A類B互相影響,就稱爲同事類。代碼以下:繼承

abstract class AbstractColleague {
	protected int number;

	public int getNumber() {
		return number;
	}

	public void setNumber(int number){
		this.number = number;
	}
	//抽象方法,修改數字時同時修改關聯對象
	public abstract void setNumber(int number, AbstractColleague coll);
}

class ColleagueA extends AbstractColleague{
	public void setNumber(int number, AbstractColleague coll) {
		this.number = number;
		coll.setNumber(number*100);
	}
}

class ColleagueB extends AbstractColleague{
	
	public void setNumber(int number, AbstractColleague coll) {
		this.number = number;
		coll.setNumber(number/100);
	}
}

public class Client {
	public static void main(String[] args){

		AbstractColleague collA = new ColleagueA();
		AbstractColleague collB = new ColleagueB();
		
		System.out.println("==========設置A影響B==========");
		collA.setNumber(1288, collB);
		System.out.println("collA的number值:"+collA.getNumber());
		System.out.println("collB的number值:"+collB.getNumber());

		System.out.println("==========設置B影響A==========");
		collB.setNumber(87635, collA);
		System.out.println("collB的number值:"+collB.getNumber());
		System.out.println("collA的number值:"+collA.getNumber());
	}
}

上面的代碼中,類A類B經過直接的關聯發生關係,假如咱們要使用中介者模式,類A類B之間則不能夠直接關聯,他們之間必需要經過一箇中介者來達到關聯的目的。接口

abstract class AbstractColleague {
	protected int number;

	public int getNumber() {
		return number;
	}

	public void setNumber(int number){
		this.number = number;
	}
	//注意這裏的參數再也不是同事類,而是一箇中介者
	public abstract void setNumber(int number, AbstractMediator am);
}

class ColleagueA extends AbstractColleague{

	public void setNumber(int number, AbstractMediator am) {
		this.number = number;
		am.AaffectB();
	}
}

class ColleagueB extends AbstractColleague{

	@Override
	public void setNumber(int number, AbstractMediator am) {
		this.number = number;
		am.BaffectA();
	}
}

abstract class AbstractMediator {
	protected AbstractColleague A;
	protected AbstractColleague B;
	
	public AbstractMediator(AbstractColleague a, AbstractColleague b) {
		A = a;
		B = b;
	}

	public abstract void AaffectB();
	
	public abstract void BaffectA();

}
class Mediator extends AbstractMediator {

	public Mediator(AbstractColleague a, AbstractColleague b) {
		super(a, b);
	}

	//處理A對B的影響
	public void AaffectB() {
		int number = A.getNumber();
		B.setNumber(number*100);
	}

	//處理B對A的影響
	public void BaffectA() {
		int number = B.getNumber();
		A.setNumber(number/100);
	}
}

public class Client {
	public static void main(String[] args){
		AbstractColleague collA = new ColleagueA();
		AbstractColleague collB = new ColleagueB();
		
		AbstractMediator am = new Mediator(collA, collB);
		
		System.out.println("==========經過設置A影響B==========");
		collA.setNumber(1000, am);
		System.out.println("collA的number值爲:"+collA.getNumber());
		System.out.println("collB的number值爲A的10倍:"+collB.getNumber());

		System.out.println("==========經過設置B影響A==========");
		collB.setNumber(1000, am);
		System.out.println("collB的number值爲:"+collB.getNumber());
		System.out.println("collA的number值爲B的0.1倍:"+collA.getNumber());
		
	}
}

雖然代碼比較長,可是仍是比較容易理解的,其實就是把原來處理對象關係的代碼從新封裝到一箇中介類中,經過這個中介類來處理對象間的關係。

中介者模式的優勢

  • 適當地使用中介者模式能夠避免同事類之間的過分耦合,使得各同事類之間能夠相對獨立地使用。
  • 使用中介者模式能夠將對象間一對多的關聯轉變爲一對一的關聯,使對象間的關係易於理解和維護。
  • 使用中介者模式能夠將對象的行爲和協做進行抽象,可以比較靈活的處理對象間的相互做用。

適用場景

在面向對象編程中,一個類必然會與其餘的類發生依賴關係,徹底獨立的類是沒有意義的。一個類同時依賴多個類的狀況也至關廣泛,既然存在這樣的狀況,說明,一對多的依賴關係有它的合理性,適當的使用中介者模式可使本來凌亂的對象關係清晰,可是若是濫用,則可能會帶來反的效果。通常來講,只有對於那種同事類之間是網狀結構的關係,纔會考慮使用中介者模式。能夠將網狀結構變爲星狀結構,使同事類之間的關係變的清晰一些。

中介者模式是一種比較經常使用的模式,也是一種比較容易被濫用的模式。對於大多數的狀況,同事類之間的關係不會複雜到混亂不堪的網狀結構,所以,大多數狀況下,將對象間的依賴關係封裝的同事類內部就能夠的,沒有必要非引入中介者模式。濫用中介者模式,只會讓事情變的更復雜。