前言
Android的設(shè)計模式系列文章介紹侦高,歡迎關(guān)注霸饲,持續(xù)更新中:
Android的設(shè)計模式-設(shè)計模式的六大原則
一句話總結(jié)23種設(shè)計模式則
創(chuàng)建型模式:
Android的設(shè)計模式-單例模式
Android的設(shè)計模式-建造者模式
Android的設(shè)計模式-工廠方法模式
Android的設(shè)計模式-簡單工廠模式
Android的設(shè)計模式-抽象工廠模式
Android的設(shè)計模式-原型模式
行為型模式:
Android的設(shè)計模式-策略模式
Android的設(shè)計模式-狀態(tài)模式
Android的設(shè)計模式-責任鏈模式
Android的設(shè)計模式-觀察者模式
Android的設(shè)計模式-模板方法模式
Android的設(shè)計模式-迭代器模式
Android的設(shè)計模式-備忘錄模式
Android的設(shè)計模式-訪問者模式
Android的設(shè)計模式-中介者模式
Android的設(shè)計模式-解釋器模式
Android的設(shè)計模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計模式-代理模式
Android的設(shè)計模式-組合模式
Android的設(shè)計模式-適配器模式
Android的設(shè)計模式-裝飾者模式
Android的設(shè)計模式-享元模式
Android的設(shè)計模式-外觀模式
Android的設(shè)計模式-橋接模式
1.定義
用一個中介者對象來封裝一系列的對象交互。中介者使得各對象不需要顯式地相互引用秧饮,從而使其松散耦合傅事,而且可以獨立地改變它們之間的交互。
2.介紹
- 中介者模式屬于行為型模式旁趟。
- 中介者模式也稱為調(diào)解者模式或者調(diào)停者模式昼激。
-
當程序存在大量的類時庇绽,多個對象之間存在著依賴的關(guān)系锡搜,呈現(xiàn)出網(wǎng)狀結(jié)構(gòu),那么程序的可讀性和可維護性就變差了瞧掺,并且修改一個類需要牽涉到其他類耕餐,不符合開閉原則。
因此我們可以引入中介者辟狈,將網(wǎng)狀結(jié)構(gòu)轉(zhuǎn)化成星型結(jié)構(gòu)肠缔,可以降低程序的復(fù)雜性,并且可以減少各個對象之間的耦合哼转。
3.UML類圖
角色說明:
- Mediator(抽象中介者角色):抽象類或者接口,定義統(tǒng)一的接口明未,用于各同事角色之間的通信。
- ConcreteMediator(具體中介者角色):繼承或者實現(xiàn)了抽象中介者壹蔓,實現(xiàn)了父類定義的方法,協(xié)調(diào)各個具體同事進行通信趟妥。
- Colleague(抽象同事角色):抽象類或者接口,定義統(tǒng)一的接口,它只知道中介者而不知道其他同事對象佣蓉。
- ConcreteColleague(具體同事角色):繼承或者實現(xiàn)了抽象同事角色披摄,每個具體同事類都知道自己本身的行為,其他的行為只能通過中介者去進行勇凭。
4.實現(xiàn)
說到中介者疚膊,肯定就想到了房屋中介,下面以房屋中介為例虾标,房東通過中介發(fā)布出售信息寓盗,中介就會把房屋信息傳遞給有這需求的購房者,購房者再通過中介去看房買房等等璧函。
4.1 創(chuàng)建抽象同事角色
無論是房東還是購房者贞让,他們都能夠發(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)建一個房東類和一個買房者類:
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)建抽象中介者角色
這里就是房屋中介喳张,定義一個通知的方法:
public interface HouseMediator {//房屋中介類
void notice(Person person, String msg);//通知方法
}
4.4 創(chuàng)建具體中介者角色
具體的房屋中介,以鏈家為例美澳,他們能從房東和買房者獲得信息销部,然后做出不同的行為:
public class Lianjia implements HouseMediator {//鏈家,實現(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)的目標人群");
if (person == mPurchaser) {
mLandlord.getNotice(message);
} else if (person == mLandlord) {
mPurchaser.getNotice(message);
}
}
}
4.5 客戶端測試:
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("求購一套學區(qū)房");
}
輸出結(jié)果:
房東發(fā)布信息:出售一套別墅
中介收到信息舅桩,并轉(zhuǎn)發(fā)給相應(yīng)的目標人群
買房者收到消息:出售一套別墅
------------------------
買房者發(fā)布信息:求購一套學區(qū)房
中介收到信息,并轉(zhuǎn)發(fā)給相應(yīng)的目標人群
房東收到消息:求購一套學區(qū)房
5. 應(yīng)用場景
- 在程序中雨膨,如果類的依賴關(guān)系過于復(fù)雜擂涛,呈現(xiàn)網(wǎng)狀的結(jié)構(gòu),可以使用中介者模式對其進行解耦聊记。
6. 優(yōu)點
- 降低類的關(guān)系復(fù)雜度撒妈,將多對多轉(zhuǎn)化成一對多恢暖,實現(xiàn)解耦。
- 符合迪米特原則狰右,依賴的類最少杰捂。
7. 缺點
- 同事類越多,中介者的邏輯就越復(fù)雜棋蚌,會變得越難維護嫁佳。
- 如果本來類的依賴關(guān)系不復(fù)雜,但是使用了中介者會使原來不復(fù)雜的邏輯變得復(fù)雜谷暮。因此需要根據(jù)實際情況去考慮蒿往,不要濫用中介者。
8. Android中的源碼分析
Android中的鎖屏功能就用到了中介者模式湿弦,KeyguardService
(鎖屏服務(wù))通過KeyguardViewMediator
(鎖屏中介者)來協(xié)調(diào)各種Manager的狀態(tài)以達到鎖屏的功能熄浓。這里KeyguardService
和各種Manager等等都充當了同事的角色。
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) {//通過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
中通過playSound
方法能夠協(xié)調(diào)AudioManager
去控制聲音的播放等等赌蔑,其他Manager同理。
相關(guān)文章閱讀
Android的設(shè)計模式-設(shè)計模式的六大原則
一句話總結(jié)23種設(shè)計模式則
創(chuàng)建型模式:
Android的設(shè)計模式-單例模式
Android的設(shè)計模式-建造者模式
Android的設(shè)計模式-工廠方法模式
Android的設(shè)計模式-簡單工廠模式
Android的設(shè)計模式-抽象工廠模式
Android的設(shè)計模式-原型模式
行為型模式:
Android的設(shè)計模式-策略模式
Android的設(shè)計模式-狀態(tài)模式
Android的設(shè)計模式-責任鏈模式
Android的設(shè)計模式-觀察者模式
Android的設(shè)計模式-模板方法模式
Android的設(shè)計模式-迭代器模式
Android的設(shè)計模式-備忘錄模式
Android的設(shè)計模式-訪問者模式
Android的設(shè)計模式-中介者模式
Android的設(shè)計模式-解釋器模式
Android的設(shè)計模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計模式-代理模式
Android的設(shè)計模式-組合模式
Android的設(shè)計模式-適配器模式
Android的設(shè)計模式-裝飾者模式
Android的設(shè)計模式-享元模式
Android的設(shè)計模式-外觀模式
Android的設(shè)計模式-橋接模式