Android設計模式之——中介者模式

一、介紹

中介者模式(Mediator Pattern)也稱為調解者模式或調停者模式,Mediator本身就有調停者和調解者的意思。

在日常生活中調停者或調解者這個角色我們見得比較多的是“和事老”,也就是說調解兩個有爭端的人的角色,舉個不恰當的例子,比如爸媽吵架,孩子或者雙方父母則會出面勸架或阻止爭吵,這里孩子或雙方父母則是充當的是調解者的模式。

而對于中介呢?大家平時聽得最多的莫過于房產中介了,在房地產飛速發展的今天,各種房產中介公司如雨后春筍般冒出來,房產中介承擔的責任很簡單,就是在買房者與賣房者之間建立一座橋梁溝通兩者,比如小民現在手里有套房子需要出售,于是他找房產中介并告訴房產中介房子的期望售價和房子的相關信息,然后房產中介則將這些信息收集匯總有時還會美化一番,然后把廣告掛在櫥窗里等待買房者,如果有人有意向購買這套房子,比如這里以小輝為例,房產中介就會告訴小輝關于這套房產的相關信息,如房齡、售價等,有時還會帶小輝去房子里實際參觀一番,最終小輝將自己的意愿告訴房產中介,再由房產中介去與小民進行溝通。也就是說在整個房產協商的過程中,小民和小輝買賣雙方是很少直接接觸的,大多數情況下都是通過房產中介來傳達信息,可能只有在最終進行房產交接時小民和小輝才會正式見面。

這就是我們現實生活中常見的調解者與中介者,但是,這里我們要說的中介者模式比起上述的兩個例子來要復雜的多,上面我們所述的例子中,中介者或調解者所要協調的也就兩類對象,而我們的中介者模式中需要協調的是多類對象。

這里還是舉一個小例子來說明,本書的閱讀者大多都是IT從業者,說得更準確些都是做APP的,一般來說,一個做APP的公司可以分為幾大模塊:運維、產品、開發、設計還有測試,每當一個新APP開始制作或者發布新版本需要制作之前,公司會開一個研討會,運維負責市場了解用戶使用傾向,研發的會說用戶反映界面不好看要求修改界面……這樣大家你一句我一句的討論一半天也沒有啥實質性結果,主要原因在于大家都站在自己的立場考慮問題,這樣的團隊研討會即使再開下去也沒什么意義,這時候如果有一個人不屬于運維、產品、開發、設計任一方的人站出來說,大家把各自的意見都跟我說,由我來權衡并作出最終的決定,不管決定如何你們都要照做。因為這個人不代表任何一方,于是大家都全票表示肯定,這么一來一個方案很快就定下來,而這個作出最終決定的人我們就稱之為中介者,這里的中介者與我們的中介者模式一樣面對的是多類對象,這里其實大家可以看到中介者模式的一些特性,每一個中介者都會知道所有的同事,比如上面我們所說的運維、產品、開發、設計還有測試,但是這些同事呢可以互不相識,而中介者不屬于同事的任何一方,也不偏袒任何一方,這么一說相信大家對中介者模式會有一個非常清晰的了解。

二、定義

中介者模式包裝了一系列對象互相作用的方式,使得這些對象不必相互明顯作用。從而使它們可以松散偶合。當某些對象之間的作用發生改變時,不會立即影響其他的一些對象之間的作用。保證這些作用可以彼此獨立的變化。中介者模式將多對多的相互作用轉化為一對多的相互作用。中介者模式將對象的行為和協作抽象化,把對象在小尺度的行為上與其他對象的相互作用分開處理。

三、使用場景

當對象之間的交互操作很多且每個對象的行為操作都依賴彼此時,為防止在修改一個對象的行為時,同時涉及修改很多其他對象的行為,可采用中介者模式,來解決緊耦合問題。該模式將對象之間的多對多關系變成一對多關系,中介者對象將系統從網狀結構變成以調停者為中心的星形結構,達到降低系統的復雜性,提高可擴展性的作用。

四、中介者模式的UML類圖

UML類圖:

這里寫圖片描述

角色介紹:

  • Mediator:抽象的中介者角色,定義了同事對象到中介者的接口。

  • ConcreteMediator:具體的中介者角色,從具體的同事對象接收消息,同時向具體的同事對象發出命令。

  • Colleague:抽象同事類角色,定義了中介者對象的接口,只知道中介而不知道其他同事對象。

  • ConcreteColleagueA,ConcreteColleagueB:具體的同事類角色,每個具體同事類都知道本身在小范圍內的行為,而不知道他在大范圍中的行為。

模板代碼:

抽象的中介者:

public interface Mediator {void change();
}

具體的中介者:

public class ConcreteMediator implements Mediator {public ConcreteColleagueA concreteColleagueA;public ConcreteColleagueB concreteColleagueB;public void setConcreteColleagueA(ConcreteColleagueA concreteColleagueA) {this.concreteColleagueA = concreteColleagueA;}public void setConcreteColleagueB(ConcreteColleagueB concreteColleagueB) {this.concreteColleagueB = concreteColleagueB;}@Overridepublic void change() {concreteColleagueA.action();concreteColleagueB.action();}
}

抽象的同事:

public abstract class Colleague {public Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}public abstract void action();
}

具體的同事A:

public class ConcreteColleagueA extends Colleague {public ConcreteColleagueA(Mediator mediator) {super(mediator);}@Overridepublic void action() {System.out.println("交給中介做A的事情");}
}

具體的同事B:

public class ConcreteColleagueB extends Colleague {public ConcreteColleagueB(Mediator mediator) {super(mediator);}@Overridepublic void action() {System.out.println("交給中介做B的事情");}
}

五、簡單示例

在電腦中,主機部分主要分為:CPU、內存、顯卡、IO設備,而將它們整合起來的就是主板,這里主板就是一個中介者。以此為例。

抽象中介者:

public abstract class Mediator {/*** 同事對象改變時通知中介者的方法* 在同事對象改變時由中介者去通知其他的同事對象* * @param c 同事對象*/public abstract void changed(Colleague c);
}

抽象同事:

public abstract class Colleague {protected Mediator mediator;//每一個同事都該知道其中介者public Colleague(Mediator mediator) {this.mediator = mediator;}}

CPU同事:

public class CPU extends Colleague{private String dataVideo, dataSound; //視頻和音頻數據public CPU(Mediator mediator) {super(mediator);}/*** 獲取視頻數據* * @return 視頻數據*/public String getDataVideo(){return dataVideo;}/*** 獲取音頻數據* * @return 音頻數據*/public String getDataSound(){return dataSound;}/*** 解碼數據* * @param data音、視頻數據*/public void decodeData(String data){//分割音、視頻數據String[] tmp = data.split(",");//解析音、視頻數據dataVideo = tmp[0];dataSound = tmp[1];//告訴中介者自身狀態改變mediator.changed(this);}
}

光驅同事:

public class CDDevice extends Colleague{private String data; //視頻數據public CDDevice(Mediator mediator) {super(mediator);}/*** 讀取視頻數據* * @return 視頻數據*/public String read(){return data;}/*** 加載視頻數據* * @return 音頻數據*/public void load(){data = "視頻數據,音頻數據";//告訴中介者自身狀態改變mediator.changed(this);}
}

顯卡同事:

public class GraphicsCard extends Colleague{public GraphicsCard(Mediator mediator) {super(mediator);}/*** 播放視頻數據* * @param 視頻數據*/public void videoPlay(String data){System.out.println("視頻:" + data);}
}

聲卡同事:

public class SoundCard extends Colleague{public SoundCard(Mediator mediator) {super(mediator);}/*** 播放音頻數據* * @param 音頻數據*/public void soundPlay(String data){System.out.println("音頻:" + data);}
}

主板中介者:

public class MainBoard extends Mediator{private CDDevice cdDevice; //光驅設備private CPU cpu; //CPUprivate SoundCard soundCard; //聲卡設備private GraphicsCard graphicsCard; //顯卡設備@Overridepublic void changed(Colleague c) {//如果光驅讀取了數據if(c == cdDevice){handleCD((CDDevice) c);}//如果CPU處理完數據else if(c == cpu){handleCD((CPU) c);}}/*** 處理光驅讀取數據后與其他設備的交互* * @param cdDevice 光驅設備*/public void handleCD(CDDevice cdDevice){cpu.decodeData(cdDevice.read());}/*** 處理CPU讀取數據后與其他設備的交互* * @param cpu CPU*/public void handleCD(CPU cpu){soundCard.soundPlay(cpu.getDataSound());graphicsCard.videoPlay(cpu.getDataVideo());}/*** 設置CD設備* * @param CDDevice CD設備*/public void setCDDevice(CDDevice cdDevice){this.cdDevice = cdDevice;}/*** 設置CPU* * @param cpu CPU*/public void setCPU(CPU cpu){this.cpu = cpu;}/*** 設置聲卡設備* * @param soundCard 聲卡設備*/public void setSoundCard(SoundCard soundCard){this.soundCard = soundCard;}/*** 設置顯卡設備* * @param graphicsCard 顯卡設備*/public void setGraphicsCard(GraphicsCard graphicsCard){this.graphicsCard = graphicsCard;}
}

播放電影:

public class Client {public static void main(String[] args) {//構造主板對象MainBoard mediator = new MainBoard();//分別構造各個零件CDDevice cd = new CDDevice(mediator);CPU cpu = new CPU(mediator);GraphicsCard gc = new GraphicsCard(mediator);SoundCard sc = new SoundCard(mediator);//將各個零件安裝到主板mediator.setCDDevice(cd);mediator.setCPU(cpu);mediator.setGraphicsCard(gc);mediator.setSoundCard(sc);//播放電影cd.load();}}

結果:

音頻:音頻數據
視頻:視頻數據

可以看出中介者模式將多對多的相互作用轉化為一對多的相互作用,將系統從網狀結構變為以中介者為中心的星形結構(這里就是主板),達到降低系統的復雜性,提高可擴展性。

六、Android源碼中的中介者模式

1、Keyguard解鎖屏

詳細機制參考:Android4.0 Keyguard解鎖屏機制

七、總結

其實在Android開發中我們可能無意間就使用了中介者模式,比如登錄注冊界面,我們使用EditText的addTextChangedListener監聽輸入密碼的位數、用戶名是否為空,密碼與確認密碼是否一致等等判斷時,此時多個控件交互,就是由Activity充當中介者來協調。

優點:

  • 適當地使用中介者模式可以避免同事類之間的過度耦合,使得各同事類之間可以相對獨立地使用。

  • 使用中介者模式可以將對象的行為和協作進行抽象,能夠比較靈活的處理對象間的相互作用。

  • 使用中介者模式可以將對象間多對多的關聯轉變為一對多的關聯,使對象間的關系易于理解和維護。

缺點:

  • 中介者模式是一種比較常用的模式,也是一種比較容易被濫用的模式。對于大多數的情況,同事類之間的關系不會復雜到混亂不堪的網狀結構,因此,大多數情況下,將對象間的依賴關系封裝的同事類內部就可以的,沒有必要非引入中介者模式。濫用中介者模式,只會讓事情變的更復雜。所以,我們決定使用中介者模式之前要多方考慮、權衡利弊。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/447002.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447002.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447002.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++智能指針中unique_ptr部分內容的講解

參考鏈接 std::unique_ptr 介紹 定義位于頭文件<memory>std::unique_ptr 是通過指針占有并管理另一對象&#xff0c;并在 unique_ptr 離開作用域時釋放該對象的智能指針。 在下列兩者之一發生時用關聯的刪除器釋放對象&#xff1a;1&#xff0c;銷毀了管理的 unique_pt…

Java基礎——Java多線程中sleep()、wait()和notify()

一、sleep()sleep()方法源碼&#xff1a;/** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does …

Key_handle的學習

代碼 一切盡在不言中 #pragma once#include "common/common.h" #include "sdf/sdf.h"#include <memory>namespace sdf {namespace algorithm {class KeyHandle {public:using erased_internal_data_t char; //使用erased_internal_data_t等效于ch…

Java基礎——虛擬機結構

一、Java平臺結構圖二、JVM、JRE和JDK關系JVM&#xff1a;Java Virtual Machine&#xff08;Java虛擬機&#xff09;&#xff0c;負責執行符合規范的Class文件 JRE&#xff1a; Java Runtime Environment &#xff08;java運行環境&#xff09;&#xff0c;包含JVM和類庫 JDK&a…

解決 SSH Connection closed by foreign host 問題

用 Xshell 連接服務器總是報錯 : Connection closed by foreign host.Disconnected from remote host... 原因可能是 SSH 服務器沒設置保活時間間隔 , 具體設置如下 : 操作 # vim /etc/ssh/sshd_config 添加兩行 , 或去掉注釋 : ClientAliveInterval 60ClientAliveCountMax…

Java基礎——synchronized

synchronized重要&#xff01;重要&#xff01;重要&#xff01;重要的事情說三遍&#xff0c;一定要記下來哦。 Java語言的關鍵字&#xff0c;當它用來修飾一個方法或者一個代碼塊的時候&#xff0c;能夠保證在同一時刻最多只有一個線程執行該段代碼。一、當兩個并發線程訪問同…

C++:MAC安裝Boost庫文件并且使用CLion開發

boost的filestem庫 C在17版本的標準庫中引入了一個filesystem庫&#xff0c;用來處理文件路徑&#xff0c;以及文件訪問。很多編譯器對filesystem庫的支持還不是很好。為了解決這個問題&#xff0c;可以臨時使用boost::filesystem來替代。其實C17標準中的filesystem庫就是從bo…

Java基礎——Java異常處理機制

一、引言 try…catch…finally恐怕是大家再熟悉不過的語句了&#xff0c;而且感覺用起來也是很簡單&#xff0c;邏輯上似乎也是很容易理解。不過&#xff0c;我親自體驗的“教訓”告訴我&#xff0c;這個東西可不是想象中的那么簡單、聽話。不信&#xff1f;那你看看下面的代碼…

clion在使用sqlite3的時候,顯示Undefined symbols for architecture x86_64錯誤的解決辦法

顯示Undefined symbols for architecture x86_64錯誤的原因 1、缺少靜態庫 環境&#xff1a;在模擬器上報錯但在真機上能運行成功&#xff0c;而且報的錯誤來自于第三方庫。原因&#xff1a;architecture x86_64 是指模擬器的架構&#xff0c;意思就是 Crypto 變量在模擬器架…

Java基礎——Java反射機制及IoC原理

一、概念 主要是指程序可以訪問&#xff0c;檢測和修改它本身狀態或行為的一種能力&#xff0c;并能根據自身行為的狀態和結果&#xff0c;調整或修改應用所描述行為的狀態和相關的語義。在java中&#xff0c;只要給定類的名字&#xff0c; 那么就可以通過反射機制來獲得類的所…

Ubuntu boost庫文件安裝編譯

簡單介紹 Boost庫是為C語言標準庫提供擴展的一些C程序庫的總稱&#xff0c;由Boost社區組織開發、維護.Boost向來有準標準庫之稱&#xff0c;很多新特性例如智能指針等都是先在boost中實現&#xff0c;后來被吸收到標準庫之中. Boost實現了日志、算法、日期、地理、數學、線程…

Java基礎——類加載機制及原理

一、什么是類的加載&#xff1f; 類的加載指的是將類的.class文件中的二進制數據讀入到內存中&#xff0c;將其放在運行時數據區的方法區內&#xff0c;然后在堆區創建一個java.lang.Class對象&#xff0c;用來封裝類在方法區內的數據結構。類的加載的最終產品是位于堆區中的Cl…

在Ubuntu環境下使用vcpkg安裝sqlite_orm包文件

Ubuntu安裝vcpkg 從github下載vcpkg的安裝包&#xff0c;在usr/local路徑下面執行如下命令 git clone https://github.com/Microsoft/vcpkg.git cd vcpkg //進入源碼目錄 ./bootstrap-vcpkg.sh //執行./bootstrap-vcpkg.sh進行編譯安裝&#xff0c;這個過程很慢 編譯安裝好…

finally語句與return語句的執行順序

網上有很多人探討Java中異常捕獲機制try...catch...finally塊中的finally語句是不是一定會被執行&#xff1f;很多人都說不是&#xff0c;當然他們的回答是正確的&#xff0c;經過我試驗&#xff0c;至少有兩種情況下finally語句是不會被執行的&#xff1a; try語句沒有被執行到…

window電腦查看ssh公鑰,以及將自己的公鑰添加到Github等類似網站

查看本機的ssh公鑰 使用命令 cd ~/.ssh使用命令 ls 可以看到 id_rsa id_rsa.pub known_hosts 三個文件&#xff0c;此處需要的是id_rsa.pub文件使用命令 cat id_rsa.pub 查看文件的內容拷貝這段內容 添加自己的公鑰 進入賬戶的設置頁面參照如下步驟&#xff0c;進入SSH Key…

java八大排序算法

一、概述 排序有內部排序和外部排序&#xff0c;內部排序是數據記錄在內存中進行排序&#xff0c;而外部排序是因排序的數據很大&#xff0c;一次不能容納全部的排序記錄&#xff0c;在排序過程中需要訪問外存。 我們這里說說八大排序就是內部排序。 當n較大&#xff0c;則應采…

密鑰安全性討論之密鑰分層管理結構

密鑰分層管理結構 密鑰的安全管理通常采用層次化的保護方法。密鑰管理分層管理機制將密鑰分為三層&#xff0c;即根密鑰、密鑰加密密鑰和工作密鑰下層密鑰為上層密鑰提供加密保護&#xff0c;采用分層的密鑰結構有助于密鑰的管理滿足本規范的要求 工作密鑰 工作密鑰對本地保存…

windows安裝 Git Large File Storage大文件下載工具ge

下載地址 導航到 git-lfs.github.com 并單擊Download開始下載git-lfs的用法指南 驗證安裝成功 打開Git Bash驗證安裝成功&#xff0c;使用命令 git lfs install &#xff0c;如果出現 >Git LFS initlized&#xff0c;就代表安裝成功參考鏈接 安裝 Git Large File Storag…

Java基礎——volatile關鍵字解析

簡介volatile關鍵字雖然從字面上理解起來比較簡單&#xff0c;但是要用好不是一件容易的事情。由于volatile關鍵字是與Java的內存模型有關的&#xff0c;因此在講述volatile關鍵之前&#xff0c;我們先來了解一下與內存模型相關的概念和知識&#xff0c;然后分析了volatile關鍵…

Linux ubuntu對于cmake的版本更新

問題產生 在ubuntu環境下運行C代碼&#xff0c;工程文件中CMakeLists文件顯示要求cmake的版本最低是3.15&#xff0c;但是我的本地版本是3.11&#xff0c;雖然修改CMakelists文件為3.11也是可以編譯通過&#xff0c;但是潛在的問題是未知的。 查看本地cmake的版本 cmake --ve…