我們平時(shí)寫代碼的過程罚屋,一個(gè)類必然會(huì)與其他類產(chǎn)生依賴關(guān)系,如果這種依賴關(guān)系如網(wǎng)狀般錯(cuò)綜復(fù)雜嗅绸,那么必然會(huì)影響我們的代碼邏輯以及執(zhí)行效率脾猛,適當(dāng)?shù)厥褂弥薪檎吣J娇梢詫?duì)這種依賴關(guān)系進(jìn)行解耦使邏輯結(jié)構(gòu)清晰,本篇博客鱼鸠,我們就一起學(xué)習(xí)中介者模式猛拴。
定義:中介者模式包裝了一系列對(duì)象相互作用的方式,使得這些對(duì)象不必相互明顯作用蚀狰。從而使它們可以松散耦合愉昆。當(dāng)某些對(duì)象之間的作用發(fā)生改變時(shí),不會(huì)立即影響其他的一些對(duì)象之間的作用麻蹋。保證這些作用可以彼此獨(dú)立的變化跛溉。
使用場(chǎng)景:
當(dāng)對(duì)象之間的交互操作很多且每個(gè)對(duì)象的行為操作都依賴彼此時(shí),為防止在修改一個(gè)對(duì)象的行為時(shí)扮授,同時(shí)涉及很多其他對(duì)象的行為芳室,可使用中介者模式。
Mediator:抽象中介者角色刹勃,定義了同事對(duì)象到中介者對(duì)象的接口堪侯,一般以抽象類的方式實(shí)現(xiàn)。ConcreteMediator:具體中介者角色荔仁,繼承于抽象中介者伍宦,實(shí)現(xiàn)了父類定義的方法芽死,它從具體的同事對(duì)象接受消息,向具體同事對(duì)象發(fā)出命令次洼。
Colleague:抽象同事類角色关贵,定義了中介者對(duì)象的接口,它只知道中介者而不知道其他的同事對(duì)象卖毁。
ConcreteColleague1坪哄、ConcreteColleague2:具體同事類角色,繼承于抽象同事類势篡,每個(gè)具體同事類都知道本身在小范圍的行為,而不知道在大范圍內(nèi)的目的模暗。
抽象同事類:
Colleague.java
package?com.qianfeng.agent;
public?abstract?class?Colleague {
? ??????????protected?Mediator mediator;
public?void?setMediator(Mediator mediator) {
? ??????????this.mediator=mediator;
}
? ??????????public?abstract?void?operation();
}
具體同事類
ConcreteColleagueA.java && ConcreteColleagueB.java
package?com.qianfeng.agent;
public?class?ConcreteColleagueA extends?Colleague{
? ??????????????????public?void?notifyColleagueB() {
????????????????????????????mediator.notifyColleagueB();
}
@Override
public?void?operation() {
????????????System.out.println("this is ConcreteColleagueA's operation\n");
????????}
}
package?com.qianfeng.agent;
public?class?ConcreteColleagueB extends?Colleague{
? ??????????public?void?notifyColleagueA() {
????????????????????????mediator.notifyColleagueA();
}
@Override
public?void?operation() {
????????????System.out.print("this is ConcreteColleagueB's operation\n");
????????}
}
抽象中介者角色:
Mediator.java
package?com.qianfeng.agent;
public?abstract?class?Mediator {
? ??????protected?Colleague colleagueA;
? ???????protected?Colleague colleagueB;
/**
?* @param?colleagueA
?* @param?colleagueB
?*/
public?Mediator(Colleague colleagueA, Colleague colleagueB) {
? ?????????????????????this.colleagueA?= colleagueA;
? ??????????????????????this.colleagueB?= colleagueB;
}
public?abstract?void?notifyColleagueA();
????????public?abstract?void?notifyColleagueB();
}
測(cè)試代碼:
ConcretrMediator.java
package?com.qianfeng.agent;
public?class?ConcreteMediator extends?Mediator{
public?ConcreteMediator(Colleague colleagueA, Colleague colleagueB) {
? ??????????????super(colleagueA, colleagueB);
}
@Override
public?void?notifyColleagueA() {
? ? ? ??if(colleagueA?!=null) {
????????????????colleagueA.operation();
????????????}
}
@Override
public?void?notifyColleagueB() {
? ? ? ? ? ??if(colleagueB?!=null) {
????????????????????colleagueB.operation();
????????????????}
????????}
}
兩個(gè)Colleague 類成功通過 Mediator 進(jìn)行了相互作用禁悠。上面是中介者模式的標(biāo)準(zhǔn)寫法,在平時(shí)項(xiàng)目中兑宇,硬是將各業(yè)務(wù)的類抽象出一個(gè) Colleague 父類是不太合理的碍侦,因?yàn)樽宇愔g的業(yè)務(wù)邏輯的不同,導(dǎo)致他們很難抽象出一些公用方法隶糕,所以這時(shí)候使用中介者模式瓷产,可以省去 Colleague 這個(gè)角色,讓 Mediator 直接依賴于幾個(gè)同事子類枚驻;同時(shí)也可以不定義Mediator接口濒旦,把具體的中介者對(duì)象實(shí)現(xiàn)成為單例,這樣同事對(duì)象不再持有中介者再登,而是在需要的時(shí)候直接獲取中介者對(duì)象并調(diào)用尔邓;中介者也不再持有同事對(duì)象,而是在具體處理方法里面去創(chuàng)建锉矢,或獲取梯嗽,或從數(shù)據(jù)傳入需要的同事對(duì)象。
同事:
//抽象同事類 ?
abstract?class?AbstractColleague { ?
????protected?AbstractMediator?mediator; ?
????/**既然有中介者沽损,那么每個(gè)具體同事必然要與中介者有聯(lián)系灯节, ?
?????* 否則就沒必要存在于 這個(gè)系統(tǒng)當(dāng)中,這里的構(gòu)造函數(shù)相當(dāng) ?
?????* 于向該系統(tǒng)中注冊(cè)一個(gè)中介者绵估,以取得聯(lián)系 ?
?????*/?
????public?AbstractColleague(AbstractMediator?mediator) { ?
????????????????????????this.mediator?= mediator; ?
????} ?
????// 在抽象同事類中添加用于與中介者取得聯(lián)系(即注冊(cè))的方法 ?
????public?void?setMediator(AbstractMediator?mediator) { ?
????????????????????????this.mediator?= mediator; ?
????} ?
} ?
//具體同事A ?
class?ColleagueA extends?AbstractColleague { ?
????//每個(gè)具體同事都通過父類構(gòu)造函數(shù)與中介者取得聯(lián)系 ?
????public?ColleagueA(AbstractMediator?mediator) { ?
????????????????????????super(mediator); ?
????} ?
????//每個(gè)具體同事必然有自己分內(nèi)的事炎疆,沒必要與外界相關(guān)聯(lián) ?
????public?void?self() { ?
????????????????????System.out.println("同事A --> 做好自己分內(nèi)的事情 ..."); ?
????} ?
????//每個(gè)具體同事總有需要與外界交互的操作,通過中介者來處理這些邏輯并安排工作 ?
????public?void?out() { ?
????????????????System.out.println("同事A --> 請(qǐng)求同事B做好分內(nèi)工作 ..."); ?
????????????????super.mediator.execute("ColleagueB", "self"); ?
????} ?
} ?
中介者:
//抽象中介者 ?
abstract?class?AbstractMediator { ?
????????????????//中介者肯定需要保持有若干同事的聯(lián)系方式 ?
????????????????protected?Hashtable colleagues?= new?Hashtable(); ?
????????????????//中介者可以動(dòng)態(tài)地與某個(gè)同事建立聯(lián)系 ?
????public?void?addColleague(String name, AbstractColleague?c) { ?
????????????????this.colleagues.put(name, c); ?
????} ? ??
????//中介者也可以動(dòng)態(tài)地撤銷與某個(gè)同事的聯(lián)系 ?
????public?void?deleteColleague(String name) { ?
????????????????this.colleagues.remove(name); ?
????} ?
????//中介者必須具備在同事之間處理邏輯壹士、分配任務(wù)磷雇、促進(jìn)交流的操作 ?
????????????public?abstract?void?execute(String name, String method); ??
} ?
//具體中介者 ?
class?Mediator extends?AbstractMediator{ ?
????//中介者最重要的功能,來回奔波與各個(gè)同事之間 ?
????public?void?execute(String name, String method) { ?
????????????????if("self".equals(method)){ ?//各自做好分內(nèi)事 ?
????????????????????????if("ColleagueA".equals(name)) { ?
????????????????????????????????ColleagueA?colleague?= (ColleagueA)super.colleagues.get("ColleagueA"); ?
????????????????????????????????colleague.self(); ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else?{ ?
????????????????????????????ColleagueB?colleague?= (ColleagueB)super.colleagues.get("ColleagueB"); ?
???????????????????????????colleague.self(); ?
????????????} ?
????????????????????????????????}else?{ //與其他同事合作 ?
????????????????????????????????if("ColleagueA".equals(name)) { ?
????????????????????????????ColleagueA?colleague?= (ColleagueA)super.colleagues.get("ColleagueA"); ?
????????????????????????????colleague.out(); ?
???????????????????????????????}else?{ ?
????????????????ColleagueB?colleague?= (ColleagueB)super.colleagues.get("ColleagueB"); ?
????????????????colleague.out(); ?
????????????} ?
????????} ?
????} ?
}
測(cè)試類:
//測(cè)試類 ?
public?class?Client?{ ?
????public?static?void?main(String[] args) { ?
????????//創(chuàng)建一個(gè)中介者 ?
????????AbstractMediator?mediator?= new?Mediator(); ?
????????//創(chuàng)建兩個(gè)同事 ?
????????ColleagueA?colleagueA?= new?ColleagueA(mediator); ?
????????ColleagueB?colleagueB?= new?ColleagueB(mediator); ?
????????//中介者分別與每個(gè)同事建立聯(lián)系 ?
????????mediator.addColleague("ColleagueA", colleagueA); ?
????????mediator.addColleague("ColleagueB", colleagueB); ?
????????//同事們開始工作 ?
????????colleagueA.self(); ?
????????colleagueA.out(); ?
????????System.out.println("======================合作愉快躏救,任務(wù)完成唯笙!\n"); ?
????????colleagueB.self(); ?
????????colleagueB.out(); ?
????????System.out.println("======================合作愉快螟蒸,任務(wù)完成!"); ?
????} ?
}
具體中介者類Mediator中的execute()方法中現(xiàn)在就有一堆冗長(zhǎng)的判斷代碼了崩掘。雖然可以把它分解并增加到Mediator類中的其它private方法中七嫌,但是具體的業(yè)務(wù)邏輯是少不了的。
所以苞慢,在解耦同事類之間的聯(lián)系的同時(shí)诵原,中介者自身也不免任務(wù)過重,因?yàn)閹缀跛械臉I(yè)務(wù)邏輯都交代到中介者身上了挽放,這就是中介者模式的不足之處绍赛。
對(duì)上面的例子還可以進(jìn)行如下優(yōu)化:
修改后的同事
//抽象同事類 ?
abstract?class?AbstractColleague { ?
????????protected?AbstractMediator?mediator; ? ? ?
????????//舍去在構(gòu)造函數(shù)中建立起與中介者的聯(lián)系 ?
????????// ?public AbstractColleague(AbstractMediator mediator) { ?
????????// ?????this.mediator = mediator; ?
????????// ?} ?
????????// 在抽象同事類中添加用于與中介者取得聯(lián)系(即注冊(cè))的方法 ?
????????public?void?setMediator(AbstractMediator?mediator) { ?
????????????????this.mediator?= mediator; ?
????????} ?
} ?
//具體同事A ?
class?ColleagueA extends?AbstractColleague { ?
????????????????//舍去在構(gòu)造函數(shù)中建立起與中介者的聯(lián)系 ?
? ? ? ? ? ? ?// public ColleagueA(AbstractMediator mediator) { ?
? ? ? ? ? ? ? ?// ? ? ? ? ? super(mediator); ?
? ? ? ? ? ? ? //} ?
????//每個(gè)具體同事必然有自己分內(nèi)的事,沒必要與外界相關(guān)聯(lián) ?
????public?void?self() { ?
????????????System.out.println("同事A --> 做好自己分內(nèi)的事情 ..."); ?
????} ?
????//每個(gè)具體同事總有需要與外界交互的操作辑畦,通過中介者來處理這些邏輯并安排工作 ?
????public?void?out() { ?
????????System.out.println("同事A --> 請(qǐng)求同事B做好分內(nèi)工作 ..."); ?
????????super.mediator.execute("ColleagueB", "self"); ?
????} ?
} ?
//具體同事B ?
class?ColleagueB extends?AbstractColleague { ?
????????????????????//舍去在構(gòu)造函數(shù)中建立起與中介者的聯(lián)系 ?
? ? ? ? ? ? ? // ?public ColleagueB(AbstractMediator mediator) { ?
? ? ? ? ? ? ? ?// ?????super(mediator); ?
????????????????// ?} ?
????????public?void?self() { ?
????????????????System.out.println("同事B --> 做好自己分內(nèi)的事情 ..."); ?
????} ?
????????public?void?out() { ?
????????????????System.out.println("同事B --> 請(qǐng)求同事A做好分內(nèi)工作 ?..."); ?
????????????????super.mediator.execute("ColleagueA", "self"); ?
????} ?
}
修改后的中介者:
//抽象中介者 ?
abstract?class?AbstractMediator { ?
????????????//中介者肯定需要保持有若干同事的聯(lián)系方式 ?
????????protected?Hashtable colleagues?= new?Hashtable(); ?
????????????//中介者可以動(dòng)態(tài)地與某個(gè)同事建立聯(lián)系 ?
????????public?void?addColleague(String name, AbstractColleague?c) { ?
????????????????// 在中介者這里幫助具體同事建立起于中介者的聯(lián)系 ?
????????????????c.setMediator(this); ?
????????????????this.colleagues.put(name, c); ?
????????} ? ??
????????????//中介者也可以動(dòng)態(tài)地撤銷與某個(gè)同事的聯(lián)系 ?
????????????public?void?deleteColleague(String name) { ?
????????????????????????????this.colleagues.remove(name); ?
????????????} ?
? ? ? ? ? ?//中介者必須具備在同事之間處理邏輯吗蚌、分配任務(wù)、促進(jìn)交流的操作 ?
????????????public?abstract?void?execute(String name, String method); ??
????????????}
測(cè)試類:
public?class?Client?{ ?
????public?static?void?main(String[] args) { ?
????????????//創(chuàng)建一個(gè)中介者 ?
???????????AbstractMediator?mediator?= new?Mediator(); ?
????????????//不用構(gòu)造函數(shù)為具體同事注冊(cè)中介者來取得聯(lián)系了 ?
????????????//ColleagueA colleagueA = new ColleagueA(mediator); ?
????????????//ColleagueB colleagueB = new ColleagueB(mediator); ?
????????????ColleagueA?colleagueA?= new?ColleagueA(); ?
????????????ColleagueB?colleagueB?= new?ColleagueB(); ?
????????????//中介者分別與每個(gè)同事建立聯(lián)系 ?
????????????mediator.addColleague("ColleagueA", colleagueA); ?
????????????mediator.addColleague("ColleagueB", colleagueB); ?
????????????//同事們開始工作 ?
???????????colleagueA.self(); ?
? ? ? ? ? ?colleagueA.out(); ?
????????????System.out.println("======================合作愉快纯出,任務(wù)完成蚯妇!\n"); ?
????????????colleagueB.self(); ?
????????????colleagueB.out(); ?
????????????System.out.println("======================合作愉快,任務(wù)完成暂筝!"); ?
????} ?
}
1.優(yōu)點(diǎn)
(1)適當(dāng)?shù)厥褂弥薪檎吣J娇梢员苊馔骂愔g的過度耦合箩言,使得各同事類之間可以相對(duì)獨(dú)立地使用。
(2)使用中介者模式可以將對(duì)象的行為和協(xié)作進(jìn)行抽象焕襟,能夠比較靈活的處理對(duì)象間的相互作用陨收。
(3)使用中介者模式可以將對(duì)象間多對(duì)多的關(guān)聯(lián)轉(zhuǎn)變?yōu)橐粚?duì)多的關(guān)聯(lián),使對(duì)象間的關(guān)系易于理解和維護(hù)鸵赖。
2.缺點(diǎn)
????中介者模式是一種比較常用的模式畏吓,也是一種比較容易被濫用的模式蓉冈。對(duì)于大多數(shù)的情況森书,同事類之間的關(guān)系不會(huì)復(fù)雜到混亂不堪的網(wǎng)狀結(jié)構(gòu)渔工,因此畜份,大多數(shù)情況下领追,將對(duì)象間的依賴關(guān)系封裝的同事類內(nèi)部就可以的睬涧,沒有必要非引入中介者模式馅而。濫用中介者模式瓜晤,只會(huì)讓事情變的更復(fù)雜包吝。所以饼煞,我們決定使用中介者模式之前要多方考慮、權(quán)衡利弊诗越。