中介者模式/調(diào)停者模式

通過進(jìn)銷存分析

比如 XX 超市枚碗,采購(gòu)部門要采購(gòu) IBM 型號(hào)的電腦了东揣,它是根據(jù)什么來決定采購(gòu)的呢揩页?

- 銷售情況罢维。銷售部門要反饋銷售情況,暢銷就多采購(gòu)拒逮,滯銷就不采購(gòu)磅甩;

-?庫(kù)存情況糊识。即使是暢銷產(chǎn)品玷氏,庫(kù)存都有 1000 臺(tái)了堵未,每天才賣出去 10 臺(tái),還要采購(gòu)嗎盏触?

- 采購(gòu)渗蟹。在特殊情況下,比如一個(gè)企業(yè)客戶一下子要賣 100 臺(tái)電腦赞辩,你庫(kù)存里自由 80 臺(tái)拙徽,怎么辦?催采購(gòu)部門趕快采購(gòu)呀

從以上分析來看诗宣,這三個(gè)模塊都是有自己的行為,并且與其他模塊之間的行為產(chǎn)生關(guān)聯(lián)關(guān)系

進(jìn)銷存類圖:

Purchase 負(fù)責(zé)采購(gòu)管理想诅,buyIBMComputer 是指定了采購(gòu) IBM 電腦召庞,refuseBuyIBM 是不再采購(gòu) IBM 了

public class Purchase {

????//采購(gòu)IBM型號(hào)的電腦

????public void buyIBMcomputer(int number){

????????//訪問庫(kù)存

????????Stock stock = new Stock();

????????//訪問銷售

????????Sale sale = new Sale();

????????//電腦的銷售情況

????????int saleStatus = sale.getSaleStatus();

????????if(saleStatus>80){ //銷售情況良好

????????????System.out.println("采購(gòu)IBM電腦:"+number + "臺(tái)");

????????????stock.increase(number);

????????}else{ //銷售情況不好

????????????int buyNumber = number/2; //折半采購(gòu)

????????????System.out.println("采購(gòu)IBM電腦:"+buyNumber+ "臺(tái)");

????????}

????}

????//不再采購(gòu)IBM電腦

????public void refuseBuyIBM(){

????????System.out.println("不再采購(gòu)IBM電腦");

????}

}

Purchase 定義了采購(gòu)電腦的一個(gè)標(biāo)準(zhǔn),如果銷售情況比較好来破,大于 80 分篮灼,你讓我采購(gòu)多少我就采購(gòu)多少;銷售情況不好徘禁,你讓我采購(gòu) 100 臺(tái)诅诱,我就采購(gòu) 50 臺(tái),對(duì)折采購(gòu)送朱。電腦采購(gòu)?fù)戤吜四锏矗隙ㄒ诺綆?kù)房中干旁,因此要調(diào)用庫(kù)存的方法,增加庫(kù)存電腦數(shù)量炮沐。

庫(kù)房 Stock 類:

public class Stock {

????//剛開始有100臺(tái)電腦

????private static int COMPUTER_NUMBER =100;

????//庫(kù)存增加

????public void increase(int number){

????????COMPUTER_NUMBER = COMPUTER_NUMBER + number;

????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);

????}

????//庫(kù)存降低

????public void decrease(int number){

????????COMPUTER_NUMBER = COMPUTER_NUMBER - number;

????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);

????}

????//獲得庫(kù)存數(shù)量

????public int getStockNumber(){

????????return COMPUTER_NUMBER;

????}

????//存貨壓力大了争群,就要通知采購(gòu)人員不要采購(gòu),銷售人員要盡快銷售

????public void clearStock(){

????????Purchase purchase = new Purchase();

????????Sale sale = new Sale();

????????System.out.println("清理存貨數(shù)量為:"+COMPUTER_NUMBER);

????????//要求折價(jià)銷售

????????sale.offSale();

????????//要求采購(gòu)人員不要采購(gòu)

????????purchase.refuseBuyIBM();

????}

}

庫(kù)房中的貨物數(shù)量肯定有增加和減少了大年,同時(shí)庫(kù)房還有一個(gè)容量顯示换薄,達(dá)到一定的容量后就要求對(duì)一些商品進(jìn)行折價(jià)處理,騰出更多的空間容納新產(chǎn)品翔试,于是就有了 clearStock 方法轻要,既然是清倉(cāng)處理肯定就要折價(jià)銷售了,于是在 Sale 這個(gè)類中就有了 offSale 方法垦缅。

Sale 源代碼:

public class Sale {

????//銷售IBM型號(hào)的電腦

????public void sellIBMComputer(int number){

????????//訪問庫(kù)存

????????Stock stock = new Stock();

????????//訪問采購(gòu)

????????Purchase purchase = new Purchase();

????????if(stock.getStockNumber()<number){ //庫(kù)存數(shù)量不夠銷售

????????????purchase.buyIBMcomputer(number);

????????}

????????System.out.println("銷售IBM電腦"+number+"臺(tái)");

????????stock.decrease(number);

????}

????//反饋銷售情況,0——100之間變化冲泥,0代表根本就沒人賣,100代表非常暢銷失都,出一個(gè)賣一個(gè)

????public int getSaleStatus(){

????????Random rand = new Random(System.currentTimeMillis());

????????int saleStatus = rand.nextInt(100);

????????System.out.println("IBM電腦的銷售情況為:"+saleStatus);

????????return saleStatus;

????}

????//折價(jià)處理

????public void offSale(){

????????//庫(kù)房有多少賣多少

????????Stock stock = new Stock();

????????System.out.println("折價(jià)銷售IBM電腦"+stock.getStockNumber()+"臺(tái)");

????}

}

Sale 類中的 getSaleStatus 是獲得銷售情況柏蘑,這個(gè)當(dāng)然要出現(xiàn)在 Sale 類中了,記住恰當(dāng)?shù)念惙诺角‘?dāng)?shù)念愔写馀樱N售情況當(dāng)然只有銷售人員才能反饋出來了咳焚,通過百分制的機(jī)制衡量銷售情況。

public class Client {

????public static void main(String[] args) {

????????//采購(gòu)人員采購(gòu)電腦

????????System.out.println("------采購(gòu)人員采購(gòu)電腦--------");

????????Purchase purchase = new Purchase();

????????purchase.buyIBMcomputer(100);

????????//銷售人員銷售電腦

????????System.out.println("\n------銷售人員銷售電腦--------");

????????Sale sale = new Sale();

????????sale.sellIBMComputer(1);

????????//庫(kù)房管理人員管理庫(kù)存

????????System.out.println("\n------庫(kù)房管理人員清庫(kù)處理--------");

????????Stock stock = new Stock();

????????stock.clearStock();

????}

}

場(chǎng)景類中模擬了三種人員類型的活動(dòng):采購(gòu)人員采購(gòu)電腦庞溜,銷售人員銷售電腦革半,庫(kù)管員管理庫(kù)存,運(yùn)行結(jié)果如下:

------采購(gòu)人員采購(gòu)電腦--------

IBM 電腦的銷售情況為:95

采購(gòu) IBM 電腦:100 臺(tái)

庫(kù)存數(shù)量為:200

------銷售人員銷售電腦--------

銷售 IBM 電腦 1 臺(tái)

庫(kù)存數(shù)量為:199

------庫(kù)房管理人員清庫(kù)處理--------

清理存貨數(shù)量為:199

折價(jià)銷售 IBM 電腦 199 臺(tái)

不再采購(gòu) IBM 電腦

迪米特法則教育我們“每個(gè)類只和朋友類交流”流码,這個(gè)朋友類可不是越多越好又官,越多耦合性越大,改一個(gè)對(duì)象而要修改一片對(duì)象漫试,這可不是面向?qū)ο笤O(shè)計(jì)所期望的六敬,而且這還是就三個(gè)模塊的情況,比較簡(jiǎn)單的一個(gè)小項(xiàng)目驾荣,如果有十個(gè)八個(gè)這樣的模塊是不是就要歇菜了外构,我們把進(jìn)銷存擴(kuò)充一下,如下圖的情況:

星型網(wǎng)絡(luò)拓?fù)渲忻總€(gè)計(jì)算機(jī)通過交換機(jī)和其他計(jì)算機(jī)進(jìn)行數(shù)據(jù)交換播掷,各個(gè)計(jì)算機(jī)之間并沒有直接出現(xiàn)交互的情況审编,結(jié)構(gòu)簡(jiǎn)單,而且穩(wěn)定歧匈,只要中間那個(gè)交換機(jī)不癱瘓垒酬,整個(gè)網(wǎng)絡(luò)就不會(huì)發(fā)生大的故障,公司和網(wǎng)吧一般都采用星型網(wǎng)絡(luò),那也說明星型拓?fù)涫巧畹妹裥目本浚俏覀儊硐胂胧遣皇强梢园堰@種星型結(jié)構(gòu)引入到我們的設(shè)計(jì)中呢矮湘?


加入了一個(gè)中介者作為三個(gè)模塊的交流核心,每個(gè)模塊之間不再相互交流乱顾,要交流就通過中介者進(jìn)行板祝,每個(gè)模塊只負(fù)責(zé)自己的業(yè)務(wù)邏輯,不屬于自己的則丟給中介者來處理.


建立了兩個(gè)抽象類 AbstractMediator 和 AbstractColeague走净,每個(gè)對(duì)象只是與中介者 Mediator 之間產(chǎn)生依賴券时,與其他對(duì)象之間沒有直接的關(guān)系,AbstractMediator 的作用是把中介者的抽象定義伏伯。

public abstract class AbstractMediator {

????protected Purchase purchase;

????protected Sale sale;

????protected Stock stock;

????//構(gòu)造函數(shù)

????public AbstractMediator(){

????????purchase = new Purchase(this);

????????sale = new Sale(this);

????????stock = new Stock(this);

????}

????//中介者最重要的方法橘洞,叫做事件方法,處理多個(gè)對(duì)象之間的關(guān)系

????public abstract void execute(String str,Object...objects);

}

我們?cè)賮砜淳唧w的中介者说搅,中介者可以根據(jù)業(yè)務(wù)的要求產(chǎn)生多個(gè)中介者(一般情況只有一個(gè)中介者)

public class Mediator extends AbstractMediator {

????//中介者最重要的方法

????public void execute(String str,Object...objects){

????????if(str.equals("purchase.buy")){ //采購(gòu)電腦

????????????this.buyComputer((Integer)objects[0]);

????????}else if(str.equals("sale.sell")){ //銷售電腦

????????????this.sellComputer((Integer)objects[0]);

????????}else if(str.equals("sale.offsell")){ //折價(jià)銷售

????????????this.offSell();

????????}else if(str.equals("stock.clear")){ //清倉(cāng)處理

????????????this.clearStock();

????????}

????}

????//采購(gòu)電腦

????private void buyComputer(int number){

????????int saleStatus = super.sale.getSaleStatus();

????????if(saleStatus>80){ //銷售情況良好

????????????System.out.println("采購(gòu)IBM電腦:"+number + "臺(tái)");

????????????super.stock.increase(number);

????????}else{ //銷售情況不好

????????????int buyNumber = number/2; //折半采購(gòu)

????????????System.out.println("采購(gòu)IBM電腦:"+buyNumber+ "臺(tái)");

????????}

????}

????//銷售電腦

????private void sellComputer(int number){

????????if(super.stock.getStockNumber()<number){ //庫(kù)存數(shù)量不夠銷售

? ??????????super.purchase.buyIBMcomputer(number);

????????}

? ??????super.stock.decrease(number);

? ? }

? ??//折價(jià)銷售電腦

????private void offSell(){

????????System.out.println("折價(jià)銷售IBM電腦"+stock.getStockNumber()+"臺(tái)");

????}

????//清倉(cāng)處理

????private void clearStock(){

????????//要求清倉(cāng)銷售

????????super.sale.offSale();

????????//要求采購(gòu)人員不要采購(gòu)

????????super.purchase.refuseBuyIBM();

????}

}

中介者 Mediator 有定義了多個(gè) Private 方法炸枣,其目標(biāo)是處理各個(gè)對(duì)象之間的依賴關(guān)系,即是說把原有一個(gè)對(duì)象要依賴多個(gè)對(duì)象的情況移到中介者的 Private 方法中實(shí)現(xiàn)弄唧,在實(shí)際項(xiàng)目中适肠,一般的做法是中介者按照職責(zé)進(jìn)行劃分,每個(gè)中介者處理一個(gè)或多個(gè)類似的關(guān)聯(lián)請(qǐng)求候引。

AbstractColleague 源碼:

public abstract class AbstractColleague {

????protected AbstractMediator mediator;

????public AbstractColleague(AbstractMediator _mediator){

????????this.mediator = _mediator;

????}

}

采購(gòu)類 Purchase 的源碼如下:

public class Purchase extends AbstractColleague{

????public Purchase(AbstractMediator _mediator){

????????super(_mediator);

????}

????//采購(gòu)IBM型號(hào)的電腦

????public void buyIBMcomputer(int number){

????????super.mediator.execute("purchase.buy", number);

????}

????//不在采購(gòu)IBM電腦

????public void refuseBuyIBM(){

????????System.out.println("不再采購(gòu)IBM電腦");

????}

}

Purchase 類是不是簡(jiǎn)化了很多侯养,看著也清晰了很多,處理自己的職責(zé)澄干,與外界有關(guān)系的事件處理則交給了中介者來完成.

Stock 類:

public class Stock extends AbstractColleague {

????public Stock(AbstractMediator _mediator){

????????super(_mediator);

????}

????//剛開始有100臺(tái)電腦

????private static int COMPUTER_NUMBER =100;

????//庫(kù)存增加

????public void increase(int number){

????????COMPUTER_NUMBER = COMPUTER_NUMBER + number;

????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);

????}

????//庫(kù)存降低

????public void decrease(int number){

????????COMPUTER_NUMBER = COMPUTER_NUMBER - number;

????????System.out.println("庫(kù)存數(shù)量為:"+COMPUTER_NUMBER);

????}

????//獲得庫(kù)存數(shù)量

????public int getStockNumber(){

????????return COMPUTER_NUMBER;

????}

????//存貨壓力大了逛揩,就要通知采購(gòu)人員不要采購(gòu),銷售人員要盡快銷售

????public void clearStock(){

????????System.out.println("清理存貨數(shù)量為:"+COMPUTER_NUMBER);

????????super.mediator.execute("stock.clear");

????}

}

Sale 類的源碼:

public class Sale extends AbstractColleague {

????public Sale(AbstractMediator _mediator){

????????super(_mediator);

????}

????//銷售IBM型號(hào)的電腦

????public void sellIBMComputer(int number){

????????super.mediator.execute("sale.sell", number);

????????System.out.println("銷售IBM電腦"+number+"臺(tái)");

????}

????//反饋銷售情況,0——100之間變化麸俘,0代表根本就沒人賣辩稽,100代表非常暢銷,出1一個(gè)賣一個(gè)

????public int getSaleStatus(){

????????Random rand = new Random(System.currentTimeMillis());

????????int saleStatus = rand.nextInt(100);

????????System.out.println("IBM電腦的銷售情況為:"+saleStatus);

????????return saleStatus;

????}

????//折價(jià)處理

????public void offSale(){

????????super.mediator.execute("sale.offsell");

????}

}

再來看場(chǎng)景類的變化

public class Client {

????public static void main(String[] args) {

????????AbstractMediator mediator = new Mediator();

????????//采購(gòu)人員采購(gòu)電腦

????????System.out.println("------采購(gòu)人員采購(gòu)電腦--------");

????????Purchase purchase = new Purchase(mediator);

????????purchase.buyIBMcomputer(100);

????????//銷售人員銷售電腦

????????System.out.println("\n------銷售人員銷售電腦--------");

????????Sale sale = new Sale(mediator);

????????sale.sellIBMComputer(1);

????????//庫(kù)房管理人員管理庫(kù)存

????????System.out.println("\n------庫(kù)房管理人員清庫(kù)處理--------");

????????Stock stock = new Stock(mediator);

????????stock.clearStock();

????}

}

在場(chǎng)景類中增加了一個(gè)中介者从媚,然后分別傳遞到三個(gè)同事類中逞泄,三個(gè)類都具有相同的特性:只負(fù)責(zé)處理自己的活動(dòng)(行為),與自己無關(guān)的活動(dòng)就丟給中介者處理拜效,從項(xiàng)目設(shè)計(jì)上來看炭懊,加入了中介者,設(shè)計(jì)結(jié)構(gòu)清晰了很多拂檩,而且類間的耦合性大大減少,代碼質(zhì)量也有了很大的提升嘲碧。

通用類圖為:


從類圖中看稻励,中介者模式有以下幾部分組成:

抽象中介者(Mediator)角色:抽象中介者角色定義統(tǒng)一的接口用于各同事角色之間的通信。

具體中介者(Concrete Mediator)角色:具體中介者角色通過協(xié)調(diào)各同事角色實(shí)現(xiàn)協(xié)作行為,因此它必須依賴于各個(gè)同事角色望抽。

同事(Colleague)角色:每一個(gè)同事角色都知道中介者角色加矛,而且與其他的同事角色通信的時(shí)候,一定要通過中介者角色協(xié)作煤篙。每個(gè)同事類的行為分為兩種:一種是同事本身的行為斟览,比如改變對(duì)象本身的狀態(tài),處理自己的行為等等辑奈,這種方法叫做自發(fā)行為(Self-Method)苛茂,與其他的同事類或中介者沒有任何的依賴;第二種是是必須依賴中介者才能完成的行為鸠窗,叫做依賴方法(Dep-Method)妓羊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市稍计,隨后出現(xiàn)的幾起案子躁绸,更是在濱河造成了極大的恐慌,老刑警劉巖臣嚣,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件净刮,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡硅则,警方通過查閱死者的電腦和手機(jī)淹父,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抢埋,“玉大人弹灭,你說我怎么就攤上這事【韭ⅲ” “怎么了穷吮?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)饥努。 經(jīng)常有香客問我捡鱼,道長(zhǎng),這世上最難降的妖魔是什么酷愧? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任驾诈,我火速辦了婚禮,結(jié)果婚禮上溶浴,老公的妹妹穿的比我還像新娘乍迄。我一直安慰自己,他們只是感情好士败,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布闯两。 她就那樣靜靜地躺著褥伴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪漾狼。 梳的紋絲不亂的頭發(fā)上重慢,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音逊躁,去河邊找鬼似踱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛稽煤,可吹牛的內(nèi)容都是我干的核芽。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼念脯,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼狞洋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绿店,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吉懊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后假勿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體借嗽,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年转培,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恶导。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浸须,死狀恐怖惨寿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情删窒,我是刑警寧澤裂垦,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站肌索,受9級(jí)特大地震影響蕉拢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诚亚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一晕换、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧站宗,春花似錦闸准、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腕唧。三九已至,卻和暖如春瘾英,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颂暇。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工缺谴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耳鸯。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓湿蛔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親县爬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阳啥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容