观察者模式的Java实现及应用
来源:互联网 发布:淘宝宝贝图片多大 编辑:程序博客网 时间:2024/05/21 11:05
观察者模式定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
关键字
- Observable
即被观察者,也可以被叫做主题(Subject)是被观察的对象。通常有注册方法(register),取消注册方法(remove)和通知方法(notify)。 - Observer
即观察者,可以接收到主题的更新。当对某个主题感兴趣的时候需要注册自己,在不需要接收更新时进行注销操作。
例子与应用
举一个生活中的例子:比如用户从报社订阅报纸,报社和用户之间是一对多依赖,用户可以在报社订阅(register)报纸,报社可以把最新的报纸发给用户(notify),用户自动收到更新。在用户不需要的时候还可以取消注册(remove)。
再比如Android中的EventBus,Rxjava的实现都是基于观察者模式的思想。再比如回调函数:Android中对Button的点击监听等等。
观察者模式可以用来解耦
自己用代码实现一个观察者模式
现在我们用代码来实现上面订阅报纸的例子:
NewProvider作为对于报社的抽象,每隔两秒钟向用户发送报纸;User作为用户的抽象,可以收到报纸。NewsModel作为对报纸本身的抽象。
/** * 被观察者接口定义 */public interface MyObserverable { void register(MyObserver myObserver); void remove(MyObserver myObserver); void send(NewsModel model);}
/** * 观察者接口定义 */public interface MyObserver { void receive(NewsModel model);}
/** * 对于报社的抽象,实现了被观察者接口,每隔2s发送一次报纸 */public class NewsProvider implements MyObserverable { private static final long DELAY = 2 * 1000; private List<MyObserver> mObservers; //我们用一个List来维护所有的观察者对象 public NewsProvider() { mObservers = new ArrayList<>(); generateNews(); } /** * 模拟产生新闻,每个2s发送一次 */ private void generateNews() { Timer timer = new Timer(); timer.schedule(new TimerTask() { int titleCount = 1; int contentCount = 1; @Override public void run() { send(new NewsModel("title:" + titleCount++, "content:" + contentCount++)); } }, DELAY, 1000); } @Override public void register(MyObserver myObserver) { if (myObserver == null) return; synchronized (this) { if (!mObservers.contains(myObserver)) mObservers.add(myObserver); } } @Override public synchronized void remove(MyObserver myObserver) { mObservers.remove(myObserver); } @Override public void send(NewsModel model) { for (MyObserver observer : mObservers) { observer.receiveNews(model); } }}
/** * 对于用户的抽象 */public class User implements MyObserver { private String mName; public User(String name) { mName = name; } @Override public void receive(NewsModel model) { System.out.println(mName + " receive news:" + model.getTitle() + " " + model.getContent()); }}
/** * 测试类 */public class Test { public static void main(String[] args) { NewsProvider provider = new NewsProvider(); User user; for (int i = 0; i < 10; i++) { user = new User("user:"+i); provider.register(user); } }}
运行结果如下:
这样我们就自己动手完成了一个简单的观察者模式。
其实在JDK的util包内Java为我们提供了一套观察者模式的实现,在使用的时候我们只需要继承Observable和Observer类即可,其实观察者模式十分简单,推荐阅读JDK的实现代码真心没有几行。此外在JDK的实现中还增加了一个布尔类型的changed域,通过设置这个变量来确定是否通知观察者。
下面我们用JDK的类来实现一遍我们的观察者模式:
public class NewsProvider extends Observable { private static final long DELAY = 2 * 1000; public NewsProvider() { Timer timer = new Timer(); timer.schedule(new TimerTask() { private int titleCount = 1; private int contentCount = 1; @Override public void run() { setChanged(); //调用setChagned方法,将changed域设置为true,这样才能通知到观察者们 notifyObservers(new NewsModel("title:" + titleCount++, "content:" + contentCount++)); } }, DELAY, 1000); }}
public class User implements Observer { private String mName; public User(String name) { mName = name; } @Override public void update(Observable observable, Object data) { NewsModel model = (NewsModel) data; System.out.println(mName + " receive news:" + model.getTitle() + " " + model.getContent()); }}
非常简单有木有
回调函数与观察者模式
关于回调函数的定义在知乎上看到过一个很赞的解释:
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。
在Android中我们有一个常用的回调:对与View点击事件的监听。现在我们就来分析一下对于View的监听。
通常在我们使用的时候是这样的:
xxxView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // do something } });
这样我们就注册好了一个回调函数。
我们可以在View的源码里发现这个接口:
/** * Interface definition for a callback to be invoked when a view is clicked. */ public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ void onClick(View v); }
当你setClickListener的时候在View的源码中可以看到对本地OnClickListener的初始化
/** * Register a callback to be invoked when this view is clicked. If this view is not * clickable, it becomes clickable. * * @param l The callback that will run * * @see #setClickable(boolean) */ public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; }
当你的点击到一个View后Android系统经过一系列的调用最后到了View的performClick方法中:
/** * Call this view's OnClickListener, if it is defined. Performs all normal * actions associated with clicking: reporting accessibility event, playing * a sound, etc. * * @return True there was an assigned OnClickListener that was called, false * otherwise is returned. */ public boolean performClick() { final boolean result; final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this); result = true; } else { result = false; } sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); return result; }
就在这里,触发了你的onClick方法,然后执行方法体。
这里我们的被观察者就是View,他的注册方法(register)就是setOnClickListener(),通知方法就是performClick;而OnClickListener就是观察者。只不过这里的只能注册一个观察对象而已。
- 观察者模式的Java实现及应用
- 观察者模式的Java实现及应用
- 观察者模式的应用场景及实现方式
- 观察者模式的java实现
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- java观察者模式及实现例子
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- 观察者模式及Java实现例子
- 观察者模式-气象台的实现与应用
- Java设计模式之《观察者模式》及应用场景
- 使用观察者模式实现Java应用程序设计MVC模式
- 观察者模式及应用场景
- Win7,64位,Python2.7.2下的opencv配置
- atexit函数和粘制位问题及file
- OpenCV中SVM参数选择
- Bootstrap3.3 动态添加和关闭 tab的方案
- DoKuWiki知识库的搭建
- 观察者模式的Java实现及应用
- 工作流activiti表结构
- Bootstrap WPF Style,Bootstrap风格的WPF样式
- iOS中的多线程
- 动态添加行(二)
- JavaScript 高程
- css清除浮动的方法
- 原生js实现复制内容到剪切板(解决jquery实现不了的问题)
- 122. Best Time to Buy and Sell Stock II