Android的設(shè)計(jì)模式-中介者模式

前言

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類圖

中介者模式UML類圖.jpg
角色說(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ì)模式-橋接模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容