Java設(shè)計(jì)模式之中介者模式
在我們實(shí)際業(yè)務(wù)中,可能存在多個(gè)類之間相互調(diào)用,形成了一個(gè)復(fù)雜的網(wǎng)狀結(jié)構(gòu)。這時(shí)候就需要有一種模式去“捋順”他們之間的關(guān)系,引出一個(gè)中間者讓類之間不再相互調(diào)用,該模式就是我們今天的主人公——中介者模式。
一、概念理解
我們先看中介者模式的官方概念:用一個(gè)中介者對(duì)象來(lái)封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯示地相互引用,從而使其松散耦合,而且可以獨(dú)立地改變它們之間的交互。
大白話解釋就是,引入一個(gè)“中介”,用于協(xié)調(diào)各個(gè)對(duì)象的關(guān)系,各個(gè)對(duì)象之間不用那么直白的直接調(diào),對(duì)象只需要調(diào)用中介的方法,中介內(nèi)部進(jìn)行邏輯判斷,由中介去調(diào)用各個(gè)對(duì)象的方法。
概念基本清楚以后接著看中介者模式包含的角色都有哪些:
中介者角色、各個(gè)對(duì)象角色是必須的,在面向接口編程原則下,中介者和對(duì)象應(yīng)該抽離出來(lái)接口,于是在中介者模式的結(jié)構(gòu)中就包括四種角色(各個(gè)對(duì)象角色稱為同事):
1.中介者(Mediator):中介者是一個(gè)接口,該接口定義了用于同事(Colleague)對(duì)象之間進(jìn)行通信的方法;
2.具體中介者(ConcreteMediator):具體中介者是實(shí)現(xiàn)中介者接口的類。具體中介者需要包含所有具體同事(ConcreteColleague)的引用,并通過(guò)實(shí)現(xiàn)中介者接口中的方法來(lái)滿足具體同事之間的通信要求;
3.同事(Colleague):一個(gè)接口,規(guī)定了具體同事需要實(shí)現(xiàn)的方法;
4.具體同事(ConcreteColleague):實(shí)現(xiàn)了同事接口的類。具體同事需要包含具體中介者的引用,一個(gè)具體同事需要和其他具體同事交互時(shí),只需將自己的請(qǐng)求通知給它所包含的具體中介者的引用。
如果在一個(gè)業(yè)務(wù)場(chǎng)景中,一個(gè)公司有很多同事,同事1 管理的有自己的數(shù)據(jù),有時(shí)候也會(huì)調(diào)用同事2的數(shù)據(jù)。
在中介者模式下,同事1和同事2 之間不再相互調(diào)用,由中介者統(tǒng)一調(diào)用,同事類中要持有中介者對(duì)象,中介者方法中要有判斷屬于哪個(gè)角色的方法。
基于四個(gè)角色,實(shí)現(xiàn)初試的demo。
讀者可以拉取完整代碼到本地進(jìn)行學(xué)習(xí),實(shí)現(xiàn)代碼均測(cè)試通過(guò)后上傳到碼云。
二、案例實(shí)現(xiàn)
抽象同事類:
抽象同事中要持有中介者的引用
/**
* 抽象同事類
* @author tcy
* @Date 14-09-2022
*/
public abstract class Colleague {
//抽象中介者引用
protected Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
//數(shù)據(jù)更新方法
public abstract void update();
//數(shù)據(jù)更改方法
public abstract void changed();
}具體同事類1、2:
具體同事類除了有自己的業(yè)務(wù)邏輯之外,應(yīng)該還有額外調(diào)用中介者的方法
/**
* 具體同事2
* @author tcy
* @Date 14-09-2022
*/
public class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator)
{
super(mediator);
}
//自己的方法
@Override
public void update()
{
System.out.println("更新同事類2");
}
//調(diào)用同事的方法
@Override
public void changed()
{
System.out.println("同事類2數(shù)據(jù)更改");
mediator.operation(this);
}
}
/**
* 具體同事1
* @author tcy
* @Date 14-09-2022
*/
public class ConcreteColleague1 extends Colleague{
public ConcreteColleague1(Mediator mediator)
{
super(mediator);
}
@Override
public void update()
{
System.out.println("更新同事類1");
}
@Override
public void changed()
{
System.out.println("同事類1數(shù)據(jù)更改");
mediator.operation(this);
}
}抽象中介者:
抽象中介者應(yīng)該是持有所有同事對(duì)象,并且應(yīng)該有一個(gè)方法去調(diào)用別的同事
/**
* 抽象中介者
*/
public abstract class Mediator {
protected ArrayList<Colleague> colleagues = new ArrayList<>();
public void add(Colleague colleague)
{
colleagues.add(colleague);
}
public abstract void operation(Colleague colleague);
}具體中介者:
具體中介者實(shí)現(xiàn)抽象中介者的方法,根據(jù)條件調(diào)用不同的同事
/**
* 具體中介者
* @author tcy
* @Date 14-09-2022
*/
public class ConcreteMediator extends Mediator {
@Override
public void operation(Colleague colleague)
{
if(colleague instanceof ConcreteColleague1)
colleagues.get(1).update();
else if(colleague instanceof ConcreteColleague2)
colleagues.get(0).update();
}
}三、中介者模式源碼中的應(yīng)用
中介者模式的典型應(yīng)用就是Jdk中的Timer 類。
我們知道Timer 類的主要作用是用于定時(shí)任務(wù),定時(shí)任務(wù)之間會(huì)存在通信問(wèn)題,如果眾多的定時(shí)任務(wù)都相互通信,那對(duì)于系統(tǒng)對(duì)象間的引用來(lái)說(shuō)就是一災(zāi)難,引出中介者模式就是理所應(yīng)當(dāng)?shù)牧恕?/p>
當(dāng)有新的任務(wù)加入到隊(duì)列中,均把該任務(wù)當(dāng)做同事,各個(gè)任務(wù)之間的通信都是由Timer 類來(lái)完成,Timer 類就相當(dāng)于中介者的角色。
我們知道,Timer 類實(shí)現(xiàn)定時(shí)任務(wù)的主要方法就是schedule(),schedule()有一堆的重載方法。
我們點(diǎn)開任意的schedule方法。
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}均調(diào)用了sched()私有方法。
我們重點(diǎn)看紅線標(biāo)記的代碼塊,將任務(wù)放入一個(gè) 隊(duì)列中,這個(gè)隊(duì)列和我們例子中的Arrlist是一個(gè)作用。
private final TaskQueue queue = new TaskQueue();
判斷以后,調(diào)用Object的notify()方法,進(jìn)行線程間的通信。
試想一下,如果沒(méi)有這個(gè)中介,每個(gè)定時(shí)任務(wù)都手動(dòng)的調(diào)用notify()方法,該有多么痛苦。
四、總結(jié)
網(wǎng)上講解設(shè)計(jì)模式的文章很多,能把中介模式講清楚很簡(jiǎn)單,但能說(shuō)明白何時(shí)使用合適的設(shè)計(jì)模式卻是難上加難。在前三章設(shè)計(jì)模式的基礎(chǔ)之上,第四章總結(jié)看完,希望讀者能對(duì)正確使用設(shè)計(jì)模式有一個(gè)清晰的輪廓。
很多網(wǎng)上的博客都說(shuō)要職責(zé)清晰才可使用中介者模式,如果類的職責(zé)是混亂的,那中介者的邏輯寫起來(lái)就很難受。還有多個(gè)對(duì)象間耦合嚴(yán)重,類圖之間出現(xiàn)了網(wǎng)狀結(jié)構(gòu),這時(shí)候就可以考慮中介者模式了,如果僅僅是為了使用中介者模式而使用,那就得不償失了。
中介者的優(yōu)點(diǎn)突出,中介者模式的出現(xiàn)會(huì)讓網(wǎng)狀結(jié)構(gòu),有序的轉(zhuǎn)化為星狀結(jié)構(gòu)。能有序降低類的復(fù)雜度,將多對(duì)多的關(guān)系轉(zhuǎn)化為一對(duì)多,降低了類之間的耦合。
缺點(diǎn)也很明顯,會(huì)增加類的個(gè)數(shù),同事類越多,中介者的邏輯也就越復(fù)雜。
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
java使用common-httpclient包實(shí)現(xiàn)post請(qǐng)求方法示例
這篇文章主要給大家介紹了關(guān)于java使用common-httpclient包實(shí)現(xiàn)post請(qǐng)求的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
Java 批量獲取地址間距離工具(支持中轉(zhuǎn)站)
本文主要介紹了Java批量獲取地址間距離,獲取兩個(gè)地址間距離,實(shí)現(xiàn)方式比較多,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
Java 實(shí)戰(zhàn)項(xiàng)目錘煉之IT設(shè)備固定資產(chǎn)管理系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java+SSM+jsp+mysql+maven實(shí)現(xiàn)一個(gè)IT設(shè)備固定資產(chǎn)管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11
在?Java?中將Object?轉(zhuǎn)換為?Int的四種方法
這篇文章主要介紹了在Java中如何將?Object?轉(zhuǎn)換為Int,本文研究了在?Java中將Object轉(zhuǎn)換為int的四種不同方法,結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
Spring Boot快速實(shí)現(xiàn) IP地址解析的示例詳解
這篇文章主要介紹了Spring Boot快速實(shí)現(xiàn)IP地址解析,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
SpringSecurity表單配置之登錄成功及頁(yè)面跳轉(zhuǎn)原理解析
這篇文章主要介紹了SpringSecurity表單配置之登錄成功及頁(yè)面跳轉(zhuǎn)原理解析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12



