Android源码看设计模式(十三)--------关于中介者模式的锁屏功能的相关分析

中介者模式

定义:

中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使它们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。中介者模式将多对多的相互作用转化为一对多的相互作用。中介者模式将对象的行为和协作抽象化。

使用场景

当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一个对象的行为时,同时涉及很多其他对象的行为,可使用中介者模式。中介者对象将系统从网状结构变成以调停者为中心的星型结构,达到降低系统的复杂性,提高可扩展性的作用

中介者模式的写法

UML图如下:
这里写图片描述

  • Mediator:抽象中介者,定义了同时对象到中介者对象的接口
  • ConcreteMediator:具体中介者,继承抽象中介者,实现了父类定义方法,它从具体的同事对象接收消息,向具体的同事对象发出命令
  • Colleague:抽象同事类,定义了中介者对象的接口,它只知道中介者而不知道其他的同事对象
  • ConcreteColleagueA/B:具体同事类,继承于抽象同事类,每个具体的同事类都知道本身在小范围的行为,而不知道它在大范围的目的

我们以电脑为例,电脑主机部分分为:CPU、内存、显卡、IO设备,他们之间存在通信关系,这是主板就是起了中介者的作用,连接各个部分

定义抽象同事:

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;
    }

    public void decodeData(String data) {
        String[] tem = data.split(",");
        //解析视频
        dataVideo = tem[0];
        //解析音频
        dataSound = tem[1];
        //通知中介者自身状态的改变
        mediator.changed(this);
    }
}


//创建CD设备
public class CDDevice extends Colleague {
    private String data;   //视频数据
    public CDDevice(Mediator mediator) {
        super(mediator);
    }

    /**
     * 读取视频数据
     * @return
     */
    public String read() {
        return data;
    }

    public void load() {
        //实际情况中视频数据和音频数据都是在一个数据流中
        data = "视频数据,音频数据";
        //通知中介者,也就是主板数据改变
        mediator.changed(this);
    }
}

//显卡
public class GraphicsCard extends Colleague {

    public GraphicsCard(Mediator mediator) {
        super(mediator);
    }

    /**
     * 播放视频
     * @param data
     */
    public void videoPlay(String data) {
        Log.e("视频",data);
    }
}

//声卡
public class SoundCard extends Colleague {

    public SoundCard(Mediator mediator) {
        super(mediator);
    }

    public void soundPlay(String data) {
        Log.e("音频",data);
    }
}

定义抽象中介者:

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

创建具体中介者:

//主板
public class MainBoard extends Mediator {

    private CDDevice cdDevice;  //光驱设备
    private CPU cpu;   //CPU
    private SoundCard soundCard;   //声卡设备
    private GraphicsCard graphicsCard;   //显卡设备

    @Override
    public void changed(Colleague c) {
        //若是光驱读取了数据
        if (c == cdDevice) {
            handleCD((CDDevice)c);
        } else if (c == cpu) {
            //若是CPU处理完数据
            handleCPU((CPU)c);
        }
    }

    /**
     * 处理CPU读取数据后与其他设备的交互
     * @param c CPU
     */
    private void handleCPU(CPU c) {
        soundCard.soundPlay(c.getDataSound());
        graphicsCard.videoPlay(c.getDataVideo());
    }

    /**
     * 处理光驱读取数据之后与其他设备的交互
     * @param cdDevice 光驱设备
     */
    private void handleCD(CDDevice cdDevice) {
        cpu.decodeData(cdDevice.read());
    }

    /**
     * 设置CD设备
     * @param cdDevice
     */
    public void setCdDevice(CDDevice cdDevice) {
        this.cdDevice = cdDevice;
    }

    /**
     * 设置CPU
     * @param 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 mainBoard = new MainBoard();

        //分别构造各个零部件
        CDDevice cd = new CDDevice(mainBoard);
        CPU cpu = new CPU(mainBoard);
        GraphicsCard graphicsCard = new GraphicsCard(mainBoard);
        SoundCard soundCard = new SoundCard(mainBoard);

        //各个零部件安装到主板
        mainBoard.setCdDevice(cd);
        mainBoard.setCpu(cpu);
        mainBoard.setGraphicsCard(graphicsCard);
        mainBoard.setSoundCard(soundCard);

        //完成之后可以开始播放
        cd.load();
    }
}

上述是中介者模式的基本用法,但是在很多情况下,我们并不是按照中介者模式的框架来实现,大多数的情况下是直接让Activity来充当一个中介者并在其中处理相关逻辑,比方说在多UI控件交互的情境下,不同的UI状态涉及到其他UI的状态等

锁屏功能

Android中的锁屏功能就用到了中介者模式,KeyguardService(锁屏服务)通过KeyguardViewMediator(锁屏中介者)来协调各种Manager的状态以达到锁屏的功能。这里KeyguardService和各种Manager等等都充当了同事的角色

KeyguardService:

public class KeyguardService extends Service {//锁屏服务,同事角色

    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);//调用中介者的接口
        }

        @Override // Binder interface
        public void verifyUnlock(IKeyguardExitCallback callback) {
            checkPermission();

            mKeyguardViewMediator.verifyUnlock(callback);//调用中介者的接口
        }

        //其他代码略

    };
}

KeyguardViewMediator:

/**
 KeyguardViewMediator中通过playSound方法能够协调AudioManager去控制声音的播放等等,其他Manager同理
*/
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*/);
      }
  }
}

https://www.jianshu.com/p/9b50004446dd
Android源码设计模式解析与实战

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值