观察者模式
介绍
1.概念
定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相对依赖对象皆得到通知并被自动更新。
2.使用场景
一个对象的改变导致一个或多个对象也发生改变
使用观察者模式原因
有些场景需要频繁发送更新消息,如果使用广播的话,会有延迟的情况出现。
code
这里以我的音乐播放器的一个例子来说一下。
被观察者接口(目标类)
/**
* author : stoneWang
* date : 2019/4/38:59
* 被观察者接口
*/
public interface MusicSubjectListener {
void add(MusicObserverListener observerListener);
void notifyObserver(int content);
void remove(MusicObserverListener observerListener);
}
观察者接口
/**
* author : stoneWang
* date : 2019/4/38:58
* 观察者接口
*/
public interface MusicObserverListener {
void observerUpData(int content);//刷新操作
}
观察者管理类
import java.util.concurrent.CopyOnWriteArrayList;
/**
* author : stoneWang
* date : 2019/4/39:01
* 观察者管理类
*/
public class MusicObserverManager implements MusicSubjectListener {
private static String TAG = "MusicPositionObserverManager";
private static MusicObserverManager observerManager = null;
//观察者接口集合(使用CopyOnWriteArrayList而不是List是为了线程安全)
private CopyOnWriteArrayList<MusicObserverListener> list = new CopyOnWriteArrayList<>();
/**
* 静态内部类单例
* @return 观察者管理类的实例
*/
public static MusicObserverManager getInstance() {
return SingletonHolder.observerManager;
}
private static class SingletonHolder {
private static final MusicObserverManager observerManager = new MusicObserverManager();
}
/**
* 加入监听队列
* @param observerListener
*/
@Override
public void add(MusicObserverListener observerListener) {
list.add(observerListener);
}
/**
* 通知观察者刷新数据
* @param content
*/
@Override
public void notifyObserver(int content) {
for (MusicObserverListener observerListener : list) {
observerListener.observerUpData(content);
}
}
/**
* 监听队列中移除
* @param observerListener
*/
@Override
public void remove(MusicObserverListener observerListener) {
if (list.contains(observerListener)) {
list.remove(observerListener);
}
}
}
在需要被通知的类,即观察者类中,继承观察者接口;
然后实现观察者接口中的observerUpData方法,在其中书写更新的逻辑;
同时需要在onCreate方法中将该观察者对象添加进观察者对象,在该Fragment/Activity销毁的时候,将该观察者移除。
public class LrcFragment extends Fragment implements MusicObserverListener {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//添加进观察者队列
MusicObserverManager.getInstance().add(this);
}
/**
* MusicPosition观察者刷新数据类
* @param content
*/
@Override
public void observerUpData(int content) {
switch (content) {
case MediaStateCode.MUSIC_POSITION_CHANGED:
//书写自己的逻辑
DclTimerTask.getInstance().destroyed();
init();
break;
case MediaStateCode.PLAY_START:
case MediaStateCode.PLAY_CONTINUE:
//书写自己的逻辑
DclTimerTask.getInstance().start();
break;
case MediaStateCode.PLAY_STOP:
case MediaStateCode.PLAY_PAUSE:
//书写自己的逻辑
DclTimerTask.getInstance().destroyed();
break;
default:
Log.i(TAG, "observerUpData->观察者类数据已刷新");
break;
}
}
@Override
public void onDestroy() {
super.onDestroy();
//从观察者队列中移除
MusicObserverManager.getInstance().remove(this);
}
}
在被观察者类中,
在需要发送消息的时候即状态发生改变时,触发观察者管理类的notifyObserver方法,通知观察者队列中的所有观察者更新数据
/*问题播放结束时没有监听,修改播放器的状态*/
public class MediaUtils {
//开始
public static void start() {
if (getMediaPlayer() != null) {
getMediaPlayer().start();
MediaUtils.currentState = MediaStateCode.PLAY_START;
}
//被观察者发生变化->PLAY_START
MusicObserverManager.getInstance().notifyObserver(MediaStateCode.PLAY_START);
}
//暂停
public static void pause() {
if (getMediaPlayer() != null && getMediaPlayer().isPlaying()) {
getMediaPlayer().pause();
MediaUtils.currentState = MediaStateCode.PLAY_PAUSE;
}
//被观察者发生变化->PLAY_PAUSE
MusicObserverManager.getInstance().notifyObserver(MediaStateCode.PLAY_PAUSE);
}
}
好啦,就是这样啦,具体的应用在我的GitHub上,如果有兴趣可以看看:
GitHub - stoneWangL/StoneMusic
不感兴趣就算啦,哈哈^_^