观察者模式定义了对象之间一对多的关系, 当一个对象(被观察者)的状态改变时, 依赖它的对象都会收到通知。可以应用到发布——订阅, 变化——更新这种业务场景中。观察者和被观察者之间用松耦合的方式, 被观察者不知道观察者的细节, 只知道观察者实现了接口。事件驱动模型更加灵活,但也是付出了系统的复杂性作为代价的,因为我们要为每一个事件源定制一个监听器以及事件,这会增加系统的负担。
观察者模式的核心是先分清角色、定位好观察者和被观察者、他们是多对一的关系。实现的关键是要建立观察者和被观察者之间的联系、比如在被观察者类中有个集合是用于存放观察者的、当被检测的东西发生改变的时候就要通知所有观察者。在观察者的构造方法中将被观察者传入、同时将本身注册到被观察者拥有的观察者名单中、即observers这个list中。
(1)抽象主题只依赖于抽象观察者(2)观察者模式支持广播通信(3)观察者模式使信息产生层和响应层分离
(1)如一个主题被大量观察者注册,则通知所有观察者会花费较高代价(2)如果某些观察者的响应方法被阻塞,整个通知过程即被阻塞,其它观察者不能及时被通知
关于动态计时器,这里的功能就是可以轻松添加一个或是移除一个计时器。实例里模拟的是倒计时。
我们可以让其存在一个永远不变的量,那就是真实的时间。这个真实的时间T_S可以是使用System.currentTimeMillis()获得时间戳,也可以是一个相对的时间(时间戳本身就是相对时间)。我们把这个“真实”的,永远存在着的时间看成是一个主题(被观察者),可以被不同的观察者进行订阅。而这里的观察者就是我们所说的计时器T_O。
我们可以让T_S在每隔一个时间单位就发布一个消息,即向其所有的订阅者(观察者)说明此时时间已经改变了。订阅者们就可以做出相应的更新操作。我们可以从图-2中看到这个过程。
主题模块我们的主题对象需要有2个基本操作,注册新的观察者、更新通知。这里我增加了一个新的操作,那就是当我们的计时器倒数结束时,我们就把这个观察者计时器从主题的观察者列表中移除。
接口实现如下(TimerSubject.java):
public interface TimerSubject { /** * 为新的观察者实现注册服务 * * @param o * 观察者 */ public void registerObserver(TimerObserver o); /** * 移除某一个观察者对象 * * @param o * 观察者 */ public void removeObserver(TimerObserver o); /** * 更新通知所有的观察者主题状态已经改变 */ public void notifyObservers();}主题类(NagaTimer.java)代码如下:public class NagaTimer implements TimerSubject { private long mCurrentStamp = 0L; private List<TimerObserver> mObservers = null; public NagaTimer() { if (mObservers == null) { mObservers = new ArrayList<>(); } } @Override public void registerObserver(TimerObserver o) { if (mObservers != null) { mObservers.add(o); } } @Override public void removeObserver(TimerObserver o) { if (mObservers == null) { return; } mObservers.remove(o); } /** * 更新通知所有的观察者 */ @Override public void notifyObservers() { if (mObservers == null || mObservers.size() == 0) { return; } for (int i = 0; i < mObservers.size(); i++) { CountDownTimer countDownTimer = (CountDownTimer)mObservers.get(i); if (countDownTimer.isDone()) { removeObserver(mObservers.get(i)); } else { countDownTimer.update(mCurrentStamp); } } } private void measurementsChanged() { notifyObservers(); } public void setMeasurements(long currentStamp) { mCurrentStamp = currentStamp; measurementsChanged(); }}观察者模块 作为观察者,它可以去根据主题的改变进行一些合理的更新操作。本实例中是时间上的倒数。所以需要有一个更新操作和展示操作。
接口实现(TimerObserver.java):
public interface TimerObserver { /** * 主题对象只做一件事情,就是更新当前时间 * * @param stamp */ public void update(long stamp);}接口实现(TimerDisplayable.java):public interface TimerDisplayable { public void display();}观察者(CountDownTimer.java):public class CountDownTimer implements TimerObserver, TimerDisplayable { private String mName; private long mStartStamp; private long mCountdownStamp; private long mCurrentStamp = 0L; public CountDownTimer(String name, long countdown) { this.mStartStamp = System.currentTimeMillis(); this.mName = name; this.mCountdownStamp = countdown; } @Override public void display() { if (mCurrentStamp - mStartStamp <= mCountdownStamp) { System.out.println(getName() + "还剩" + ((mCountdownStamp - (mCurrentStamp - mStartStamp)) / 1000) + "s"); } } @Override public void update(long stamp) { mCurrentStamp = stamp; display(); } public boolean isDone() { if (mCurrentStamp - mStartStamp >= mCountdownStamp) { return true; } return false; } public String getName() { return mName; }}
运行结果如下:
GitHub源码下载:https://github.com/William-Hai/DesignPatternCollections
转载于:https://www.cnblogs.com/minglongzhu/p/9836302.html
相关资源:JAVA上百实例源码以及开源项目