新四季網

外觀模式與中介者模式的異同點(設計模式系列中介者模式)

2023-04-13 15:10:38 4

作者公眾號:一角錢技術(org_yijiaoqian)

前言23種設計模式速記單例(singleton)模式工廠方法(factory method)模式抽象工廠(abstract factory)模式建造者/構建器(builder)模式原型(prototype)模式享元(flyweight)模式外觀(facade)模式適配器(adapter)模式裝飾(decorator)模式觀察者(observer)模式策略(strategy)模式橋接(bridge)模式模版方法(template method)模式責任鏈(chain of responsibility)模式組合(composite)模式代理(proxy)模式備忘錄(memento)模式命令(command)模式狀態(state)模式持續更新中......

23種設計模式快速記憶的請看上面第一篇,本篇和大家一起來學習中介者模式相關內容。

模式定義

定義一個中介對象來封裝一系列對象之間的交互,使原有對象之間的耦合鬆散,且可以獨立地改變它們之間的交互。中介者模式又叫調停模式,它是迪米特法則的典型應用。

迪米特法則(Law of Demeter,LoD)又叫作最少知識原則(Least Knowledge Principle,LKP),產生於 1987 年美國東北大學(Northeastern University)的一個名為迪米特(Demeter)的研究項目,由伊恩·荷蘭(Ian Holland)提出,被 UML 創始者之一的布奇(Booch)普及,後來又因為在經典著作《程式設計師修煉之道》(The Pragmatic Programmer)提及而廣為人知。

迪米特法則的定義是:只與你的直接朋友交談,不跟「陌生人」說話(Talk only to your immediate friends and not to strangers)。其含義是:如果兩個軟體實體無須直接通信,那麼就不應當發生直接的相互調用,可以通過第三方轉發該調用。其目的是降低類之間的耦合度,提高模塊的相對獨立性。

迪米特法則中的「朋友」是指:當前對象本身、當前對象的成員對象、當前對象所創建的對象、當前對象的方法參數等,這些對象同當前對象存在關聯、聚合或組合關係,可以直接訪問這些對象的方法。

模板實現如下

packagecom.niuh.designpattern.mediator.v1;importjava.util.ArrayList;importjava.util.List;/****中介者模式**/publicclassMediatorPattern{publicstaticvoidmain(String[]args){Mediatormd=newConcreteMediator;Colleaguec1,c2;c1=newConcreteColleague1;c2=newConcreteColleague2;md.register(c1);md.register(c2);c1.send;System.out.println("==============");c2.send;}}//抽象中介者abstractclassMediator{publicabstractvoidregister(Colleaguecolleague);publicabstractvoidrelay(Colleaguecl);//轉發}//具體中介者classConcreteMediatorextendsMediator{privateListcolleagues=newArrayList;publicvoidregister(Colleaguecolleague){if(!colleagues.contains(colleague)){colleagues.add(colleague);colleague.setMedium(this);}}publicvoidrelay(Colleaguecl){for(Colleagueob:colleagues){if(!ob.equals(cl)){((Colleague)ob).receive;}}}}//抽象同事類abstractclassColleague{protectedMediatormediator;publicvoidsetMedium(Mediatormediator){this.mediator=mediator;}publicabstractvoidreceive;publicabstractvoidsend;}//具體同事類classConcreteColleague1extendsColleague{publicvoidreceive{System.out.println("具體同事類1收到請求。");}publicvoidsend{System.out.println("具體同事類1發出請求。");mediator.relay(this);//請中介者轉發}}//具體同事類classConcreteColleague2extendsColleague{publicvoidreceive{System.out.println("具體同事類2收到請求。");}publicvoidsend{System.out.println("具體同事類2發出請求。");mediator.relay(this);//請中介者轉發}}

結果實現如下

具體同事類1發出請求。具體同事類2收到請求。==============具體同事類2發出請求。具體同事類1收到請求。

解決的問題

對象與對象之間存在大量的關聯關係,這樣勢必會導致系統的結構變得很複雜,同時若一個對象發生改變,我們也需要跟蹤與之相關聯的對象,同時做出相應的處理。

模式組成

中介者模式實現的關鍵是找出「中介者」。

實例說明實例概況

用中介者模式編寫一個「北京房地產交流平臺」程序。

分析:北京房地產交流平臺是「房地產中介公司」提供給「賣方客戶」與「買方客戶」進行信息交流的平臺,比較適合用中介者模式來實現。

使用步驟

步驟1:定義一個中介公司(Medium)接口,它是抽象中介者,它包含了客戶註冊方法 register(Customer member) 和信息轉發方法 relay(String from,String ad);

interfaceMedium{//客戶註冊voidregister(Customermember);//轉發voidrelay(Stringfrom,Stringad);}

步驟2:定義一個北京房地產中介(EstateMedium)公司,它是具體中介者類,它包含了保存客戶信息的 List 對象,並實現了中介公司中的抽象方法。

//具體中介者:房地產中介classEstateMediumimplementsMedium{privateListmembers=newArrayList;publicvoidregister(Customermember){if(!members.contains(member)){members.add(member);member.setMedium(this);}}publicvoidrelay(Stringfrom,Stringad){for(Customerob:members){Stringname=ob.getName;if(!name.equals(from)){((Customer)ob).receive(from,ad);}}}}

步驟3:定義一個客戶(Qistomer)類,它是抽象同事類,其中包含了中介者的對象,和發送信息的 send(String ad) 方法與接收信息的 receive(String from,Stringad) 方法的接口,由於本程序是窗體程序,所以本類繼承 JPmme 類,並實現動作事件的處理方法 actionPerformed(ActionEvent e)。

//抽象同事類:客戶abstractclassCustomerextendsJFrameimplementsActionListener{privatestaticfinallongserialVersionUID=-7219939540794786080L;protectedMediummedium;protectedStringname;JTextFieldSentText;JTextAreaReceiveArea;publicCustomer(Stringname){super(name);this.name=name;}voidClientWindow(intx,inty){Containercp;JScrollPanesp;JPanelp1,p2;cp=this.getContentPane;SentText=newJTextField(18);ReceiveArea=newJTextArea(10,18);ReceiveArea.setEditable(false);p1=newJPanel;p1.setBorder(BorderFactory.createTitledBorder("接收內容:"));p1.add(ReceiveArea);sp=newJScrollPane(p1);cp.add(sp,BorderLayout.NORTH);p2=newJPanel;p2.setBorder(BorderFactory.createTitledBorder("發送內容:"));p2.add(SentText);cp.add(p2,BorderLayout.SOUTH);SentText.addActionListener(this);this.setLocation(x,y);this.setSize(250,330);this.setResizable(false);//窗口大小不可調整this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}publicvoidactionPerformed(ActionEvente){StringtempInfo=SentText.getText.trim;SentText.setText("");this.send(tempInfo);}publicStringgetName{returnname;}publicvoidsetMedium(Mediummedium){this.medium=medium;}publicabstractvoidsend(Stringad);publicabstractvoidreceive(Stringfrom,Stringad);}

步驟4:定義賣方(Seller)類和買方(Buyer)類,它們是具體同事類,是客戶(Customer)類的子類,它們實現了父類中的抽象方法,通過中介者類進行信息交流。

//具體同事類:賣方classSellerextendsCustomer{privatestaticfinallongserialVersionUID=-1443076716629516027L;publicSeller(Stringname){super(name);ClientWindow(50,100);}publicvoidsend(Stringad){ReceiveArea.append("我(賣方)說:" ad "\n");//使滾動條滾動到最底端ReceiveArea.setCaretPosition(ReceiveArea.getText.length);medium.relay(name,ad);}publicvoidreceive(Stringfrom,Stringad){ReceiveArea.append(from "說:" ad "\n");//使滾動條滾動到最底端ReceiveArea.setCaretPosition(ReceiveArea.getText.length);}}//具體同事類:買方classBuyerextendsCustomer{privatestaticfinallongserialVersionUID=-474879276076308825L;publicBuyer(Stringname){super(name);ClientWindow(350,100);}publicvoidsend(Stringad){ReceiveArea.append("我(買方)說:" ad "\n");//使滾動條滾動到最底端ReceiveArea.setCaretPosition(ReceiveArea.getText.length);medium.relay(name,ad);}publicvoidreceive(Stringfrom,Stringad){ReceiveArea.append(from "說:" ad "\n");//使滾動條滾動到最底端ReceiveArea.setCaretPosition(ReceiveArea.getText.length);}}

輸出結果

優點降低了對象之間的耦合性,使得對象易於獨立地被復用。將對象間的一對多關聯轉變為一對一的關聯,提高系統的靈活性,使得系統易於維護和擴展。缺點

當同事類太多時,中介者的職責將很大,它會變得複雜而龐大,以至於系統難以維護。

應用場景當對象之間存在複雜的網狀結構關係而導致依賴關係混亂且難以復用時。當想創建一個運行於多個類之間的對象,又不想生成新的子類時。模式的擴展

在實際開發中,通常採用以下兩種方法來簡化中介者模式,使開發變得更簡單。

不定義中介者接口,把具體中介者對象實現成為單例。同事對象不持有中介者,而是在需要的時候直接獲取中介者對象並調用。

程序代碼如下

packagecom.niuh.designpattern.mediator.v3;importjava.util.ArrayList;importjava.util.List;/****簡化中介者模式**/publicclassSimpleMediatorPattern{publicstaticvoidmain(String[]args){SimpleColleaguec1,c2;c1=newSimpleConcreteColleague1;c2=newSimpleConcreteColleague2;c1.send;System.out.println("==============");c2.send;}}//簡單單例中介者classSimpleMediator{privatestaticSimpleMediatorsmd=newSimpleMediator;privateListcolleagues=newArrayList;privateSimpleMediator{}publicstaticSimpleMediatorgetMedium{return(smd);}publicvoidregister(SimpleColleaguecolleague){if(!colleagues.contains(colleague)){colleagues.add(colleague);}}publicvoidrelay(SimpleColleaguescl){for(SimpleColleagueob:colleagues){if(!ob.equals(scl)){((SimpleColleague)ob).receive;}}}}//抽象同事類interfaceSimpleColleague{voidreceive;voidsend;}//具體同事類classSimpleConcreteColleague1implementsSimpleColleague{SimpleConcreteColleague1{SimpleMediatorsmd=SimpleMediator.getMedium;smd.register(this);}publicvoidreceive{System.out.println("具體同事類1:收到請求。");}publicvoidsend{SimpleMediatorsmd=SimpleMediator.getMedium;System.out.println("具體同事類1:發出請求...");smd.relay(this);//請中介者轉發}}//具體同事類classSimpleConcreteColleague2implementsSimpleColleague{SimpleConcreteColleague2{SimpleMediatorsmd=SimpleMediator.getMedium;smd.register(this);}publicvoidreceive{System.out.println("具體同事類2:收到請求。");}publicvoidsend{SimpleMediatorsmd=SimpleMediator.getMedium;System.out.println("具體同事類2:發出請求...");smd.relay(this);//請中介者轉發}}

輸出結果如下

具體同事類1:發出請求...具體同事類2:收到請求。==============具體同事類2:發出請求...具體同事類1:收到請求。

源碼中的應用

java.util.Timerjava.util.concurrent.Executer#executejava.util.concurrent.ExecuterService#submitjava.lang.reflect.Method#invoke

PS:以上代碼提交在 Github

https://github.com/Niuh-Study/niuh-designpatterns.git

文章持續更新,可以公眾號搜一搜「 一角錢技術 」第一時間閱讀, 本文 GitHub org_hejianhui/JavaStudy 已經收錄,歡迎 Star。

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了