前言
Android的設(shè)計(jì)模式系列文章介紹,歡迎關(guān)注,持續(xù)更新中:
Android的設(shè)計(jì)模式-設(shè)計(jì)模式的六大原則
一句話總結(jié)23種設(shè)計(jì)模式則
創(chuàng)建型模式:
Android的設(shè)計(jì)模式-單例模式
Android的設(shè)計(jì)模式-建造者模式
Android的設(shè)計(jì)模式-工廠方法模式
Android的設(shè)計(jì)模式-簡(jiǎn)單工廠模式
Android的設(shè)計(jì)模式-抽象工廠模式
Android的設(shè)計(jì)模式-原型模式
行為型模式:
Android的設(shè)計(jì)模式-策略模式
Android的設(shè)計(jì)模式-狀態(tài)模式
Android的設(shè)計(jì)模式-責(zé)任鏈模式
Android的設(shè)計(jì)模式-觀察者模式
Android的設(shè)計(jì)模式-模板方法模式
Android的設(shè)計(jì)模式-迭代器模式
Android的設(shè)計(jì)模式-備忘錄模式
Android的設(shè)計(jì)模式-訪問(wèn)者模式
Android的設(shè)計(jì)模式-中介者模式
Android的設(shè)計(jì)模式-解釋器模式
Android的設(shè)計(jì)模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計(jì)模式-代理模式
Android的設(shè)計(jì)模式-組合模式
Android的設(shè)計(jì)模式-適配器模式
Android的設(shè)計(jì)模式-裝飾者模式
Android的設(shè)計(jì)模式-享元模式
Android的設(shè)計(jì)模式-外觀模式
Android的設(shè)計(jì)模式-橋接模式
1.定義
用一個(gè)中介者對(duì)象來(lái)封裝一系列的對(duì)象交互。中介者使得各對(duì)象不需要顯式地相互引用,從而使其松散耦合,而且可以獨(dú)立地改變它們之間的交互。
2.介紹
- 中介者模式屬于行為型模式。
- 中介者模式也稱為調(diào)解者模式或者調(diào)停者模式。
-
當(dāng)程序存在大量的類時(shí),多個(gè)對(duì)象之間存在著依賴的關(guān)系,呈現(xiàn)出網(wǎng)狀結(jié)構(gòu),那么程序的可讀性和可維護(hù)性就變差了,并且修改一個(gè)類需要牽涉到其他類,不符合開(kāi)閉原則。
網(wǎng)狀結(jié)構(gòu).jpg
因此我們可以引入中介者,將網(wǎng)狀結(jié)構(gòu)轉(zhuǎn)化成星型結(jié)構(gòu),可以降低程序的復(fù)雜性,并且可以減少各個(gè)對(duì)象之間的耦合。
星型結(jié)構(gòu).jpg
3.UML類圖

角色說(shuō)明:
- Mediator(抽象中介者角色):抽象類或者接口,定義統(tǒng)一的接口,用于各同事角色之間的通信。
- ConcreteMediator(具體中介者角色):繼承或者實(shí)現(xiàn)了抽象中介者,實(shí)現(xiàn)了父類定義的方法,協(xié)調(diào)各個(gè)具體同事進(jìn)行通信。
- Colleague(抽象同事角色):抽象類或者接口,定義統(tǒng)一的接口,它只知道中介者而不知道其他同事對(duì)象。
- ConcreteColleague(具體同事角色):繼承或者實(shí)現(xiàn)了抽象同事角色,每個(gè)具體同事類都知道自己本身的行為,其他的行為只能通過(guò)中介者去進(jìn)行。
4.實(shí)現(xiàn)
說(shuō)到中介者,肯定就想到了房屋中介,下面以房屋中介為例,房東通過(guò)中介發(fā)布出售信息,中介就會(huì)把房屋信息傳遞給有這需求的購(gòu)房者,購(gòu)房者再通過(guò)中介去看房買房等等。
4.1 創(chuàng)建抽象同事角色
無(wú)論是房東還是購(gòu)房者,他們都能夠發(fā)布信息和接受信息:
public abstract class Person {//人物類
protected HouseMediator houseMediator;
public Person(HouseMediator houseMediator) {
this.houseMediator = houseMediator;//獲取中介
}
public abstract void send(String message);//發(fā)布信息
public abstract void getNotice(String message);//接受信息
}
4.2 創(chuàng)建具體同事角色
下面分別創(chuàng)建一個(gè)房東類和一個(gè)買房者類:
public class Purchaser extends Person {//買房者類,繼承Person
public Purchaser(HouseMediator houseMediator) {
super(houseMediator);
}
@Override
public void send(String message) {
System.out.println("買房者發(fā)布信息:" + message);
houseMediator.notice(this, message);
}
@Override
public void getNotice(String message) {
System.out.println("買房者收到消息:" + message);
}
}
public class Landlord extends Person {//房東者類,繼承Person
public Landlord(HouseMediator houseMediator) {
super(houseMediator);
}
@Override
public void send(String message) {
System.out.println("房東發(fā)布信息:" + message);
houseMediator.notice(this, message);
}
@Override
public void getNotice(String message) {
System.out.println("房東收到消息:" + message);
}
}
4.3 創(chuàng)建抽象中介者角色
這里就是房屋中介,定義一個(gè)通知的方法:
public interface HouseMediator {//房屋中介類
void notice(Person person, String msg);//通知方法
}
4.4 創(chuàng)建具體中介者角色
具體的房屋中介,以鏈家為例,他們能從房東和買房者獲得信息,然后做出不同的行為:
public class Lianjia implements HouseMediator {//鏈家,實(shí)現(xiàn)HouseMediator
Purchaser mPurchaser;
Landlord mLandlord;
public void setPurchaser(Purchaser purchaser) {//設(shè)置買房者
mPurchaser = purchaser;
}
public void setLandlord(Landlord landlord) {//設(shè)置房東
mLandlord = landlord;
}
@Override
public void notice(Person person, String message) {//發(fā)送通知
System.out.println("中介收到信息,并轉(zhuǎn)發(fā)給相應(yīng)的目標(biāo)人群");
if (person == mPurchaser) {
mLandlord.getNotice(message);
} else if (person == mLandlord) {
mPurchaser.getNotice(message);
}
}
}
4.5 客戶端測(cè)試:
public void test() {
Lianjia houseMediator = new Lianjia();
Purchaser purchaser = new Purchaser(houseMediator);
Landlord landlord = new Landlord(houseMediator);
houseMediator.setLandlord(landlord);
houseMediator.setPurchaser(purchaser);
landlord.send("出售一套別墅");
System.out.println("------------------------");
purchaser.send("求購(gòu)一套學(xué)區(qū)房");
}
輸出結(jié)果:
房東發(fā)布信息:出售一套別墅
中介收到信息,并轉(zhuǎn)發(fā)給相應(yīng)的目標(biāo)人群
買房者收到消息:出售一套別墅
------------------------
買房者發(fā)布信息:求購(gòu)一套學(xué)區(qū)房
中介收到信息,并轉(zhuǎn)發(fā)給相應(yīng)的目標(biāo)人群
房東收到消息:求購(gòu)一套學(xué)區(qū)房
5. 應(yīng)用場(chǎng)景
- 在程序中,如果類的依賴關(guān)系過(guò)于復(fù)雜,呈現(xiàn)網(wǎng)狀的結(jié)構(gòu),可以使用中介者模式對(duì)其進(jìn)行解耦。
6. 優(yōu)點(diǎn)
- 降低類的關(guān)系復(fù)雜度,將多對(duì)多轉(zhuǎn)化成一對(duì)多,實(shí)現(xiàn)解耦。
- 符合迪米特原則,依賴的類最少。
7. 缺點(diǎn)
- 同事類越多,中介者的邏輯就越復(fù)雜,會(huì)變得越難維護(hù)。
- 如果本來(lái)類的依賴關(guān)系不復(fù)雜,但是使用了中介者會(huì)使原來(lái)不復(fù)雜的邏輯變得復(fù)雜。因此需要根據(jù)實(shí)際情況去考慮,不要濫用中介者。
8. Android中的源碼分析
Android中的鎖屏功能就用到了中介者模式,KeyguardService(鎖屏服務(wù))通過(guò)KeyguardViewMediator(鎖屏中介者)來(lái)協(xié)調(diào)各種Manager的狀態(tài)以達(dá)到鎖屏的功能。這里KeyguardService和各種Manager等等都充當(dāng)了同事的角色。
8.1 KeyguardService的源碼
public class KeyguardService extends Service {//鎖屏服務(wù),同事角色
private KeyguardViewMediator mKeyguardViewMediator;//鎖屏中介者
@Override
public void onCreate() {
((SystemUIApplication) getApplication()).startServicesIfNeeded();
//初始化中介者
mKeyguardViewMediator = ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
}
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
@Override // Binder interface
public void addStateMonitorCallback(IKeyguardStateCallback callback) {
checkPermission();
mKeyguardViewMediator.addStateMonitorCallback(callback);//調(diào)用中介者的接口
}
@Override // Binder interface
public void verifyUnlock(IKeyguardExitCallback callback) {
checkPermission();
mKeyguardViewMediator.verifyUnlock(callback);//調(diào)用中介者的接口
}
//其他代碼略
};
}
8.2 KeyguardViewMediator的源碼
public class KeyguardViewMediator extends SystemUI {//鎖屏中介者
//各種Manager
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
private PowerManager mPM;
private IWindowManager mWM;
private TrustManager mTrustManager;
private SearchManager mSearchManager;
private PowerManager.WakeLock mShowKeyguardWakeLock;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
//其他代碼略
private void playSound(int soundId) {//通過(guò)AudioManager去播放聲音
if (soundId == 0) return;
final ContentResolver cr = mContext.getContentResolver();
if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
mLockSounds.stop(mLockSoundStreamId);
// Init mAudioManager
if (mAudioManager == null) {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
if (mAudioManager == null) return;
mUiSoundsStreamType = mAudioManager.getUiSoundsStreamType();
}
// If the stream is muted, don't play the sound
if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
mLockSoundStreamId = mLockSounds.play(soundId,
mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
}
}
}
KeyguardViewMediator中通過(guò)playSound方法能夠協(xié)調(diào)AudioManager去控制聲音的播放等等,其他Manager同理。
相關(guān)文章閱讀
Android的設(shè)計(jì)模式-設(shè)計(jì)模式的六大原則
一句話總結(jié)23種設(shè)計(jì)模式則
創(chuàng)建型模式:
Android的設(shè)計(jì)模式-單例模式
Android的設(shè)計(jì)模式-建造者模式
Android的設(shè)計(jì)模式-工廠方法模式
Android的設(shè)計(jì)模式-簡(jiǎn)單工廠模式
Android的設(shè)計(jì)模式-抽象工廠模式
Android的設(shè)計(jì)模式-原型模式
行為型模式:
Android的設(shè)計(jì)模式-策略模式
Android的設(shè)計(jì)模式-狀態(tài)模式
Android的設(shè)計(jì)模式-責(zé)任鏈模式
Android的設(shè)計(jì)模式-觀察者模式
Android的設(shè)計(jì)模式-模板方法模式
Android的設(shè)計(jì)模式-迭代器模式
Android的設(shè)計(jì)模式-備忘錄模式
Android的設(shè)計(jì)模式-訪問(wèn)者模式
Android的設(shè)計(jì)模式-中介者模式
Android的設(shè)計(jì)模式-解釋器模式
Android的設(shè)計(jì)模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計(jì)模式-代理模式
Android的設(shè)計(jì)模式-組合模式
Android的設(shè)計(jì)模式-適配器模式
Android的設(shè)計(jì)模式-裝飾者模式
Android的設(shè)計(jì)模式-享元模式
Android的設(shè)計(jì)模式-外觀模式
Android的設(shè)計(jì)模式-橋接模式

