java设计模式-观察者模式
1.观察者模式
观察者模式(Observer),即多个观察者对象监听一个共同的主题对象,是一种一对多的依赖关系。当被观察的主题对象发生改变时,会通过回掉函数通知所有关注自己的观察者,观察者会主动根据接受到的通知消息更新自己。
观察者模式属于行为型模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图 (Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式在java中很常用,而且java jdk也对它做了实现,可见该设计模式的重要位置。为了实现视图和事件处理的分离,大多都采用了 Observer模式。
2.模式结构图
结构包括四个类,两个抽象类,两个具体类。
Observable**抽象主题-被观察者**,用于保存观察者对象的引用,可以添加注册和删除观察者,用于保存和删除对观察者的引用。
ConcreteSubject**具体主题-被观察者**,被观察者主题内部状态发生改变时,会对所有登记注册的观察者发出通知。
Observer**抽象观察者**,给所有的具体观察者定义一个借口,并定义一个更新自己的方法。
ConcreteObserver**具体观察者**,实现抽象观察者角色所需要的更新接口update
观察者(Observer)相当于事件监听者(监听器),被观察者(Observable)相当于事件源和事件,执行逻辑时通知observer即可触发oberver的update,同时可传被观察者和参数。简化了事件-监听模式的实现。
3.订阅微信公众号的示例
观察者模式,又叫发布订阅模式,这里使用“微信公众号发布信息,关注者收到信息通知”为例。
以下观察者模式的实现,类似于了jdk的实现方式。
定义1:抽象被观察者接口和抽象观察者接口
package observerDemo.business;
/** * @desc:抽象被观察者 */
public interface Observable {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
public void notifyObservers(Object obj);
}
/** * @desc:抽象观察者 */
public interface Observer { void update(Observable o, Object arg); }
定义2:实现类,定义具体被观察者(微信公众号)和观察者(微信用户)
package observerDemo.business.impl;
import observerDemo.business.Observable;
import observerDemo.business.Observer;
import java.util.Vector;
/**
* @desc: 微信公众号
*/
public class AccountOfficalSubject implements Observable {
private Vector obs; //存放观察者的数组
public AccountOfficalSubject() {
obs = new Vector();
}
/** * 添加观察者(线程安全) */
@Override
public synchronized void registerObserver(Observer o){
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/** * 删除观察者(线程安全) */
@Override
public synchronized void removeObserver(Observer o){
obs.removeElement(o);
}
/** * 唤醒(通知)观察者(线程安全) */
@Override
public void notifyObserver(){
//发生了业务,并将业务信息通知给订阅者
notifyObservers(null);
}
@Override
public void notifyObservers(Object arg){
Object[] arrLocal;
arrLocal = obs.toArray();
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
/** * 观察者(订阅者数量,关注人数) */
public synchronized int countObservers() {
return obs.size();
}
}
/**
* @desc: 微信个人账号
*/
public class WeChartObserver implements Observer {
private String ID;
public WeChartObserver(){}
public WeChartObserver(String ID){
this.ID=ID;
}
@Override
public void update(Observable o, Object arg){
System.out.println("微信号:"+ID);
if(arg!=null){
System.out.println("收到订阅信息:"+arg.toString());
}
}
}
定义3:定义一个微信公众号发布的信息实体类
package observerDemo.dto;
/**
* @desc: 公众号发布的动态短文
*/
public class ArticleDTO {
private String theme; //主题
private String author; //作者
private String content; //消息内容
private Long reading; //阅读量
public ArticleDTO(String theme, String author, String content, Long reading) {
this.theme = theme;
this.author = author;
this.content = content;
this.reading = reading;
}
@Override
public String toString() {
return "ArticleDTO{" +
"theme='" + theme + '\'' +
", author='" + author + '\'' +
", content='" + content + '\'' +
", reading=" + reading +
'}';
}
}
定义4:测试类,实例化两个微信用户Kate和Sam,并注册关注微信公众号,当微信公众号发布消息的时候,会通知所有的关注者。
public class Test {
public static void main(String[] args){
Observable obserable=new AccountOfficalSubject();
obserable.registerObserver(new WeChartObserver("Kate"));
obserable.registerObserver(new WeChartObserver("Sam"));
ArticleDTO articleDTO=new ArticleDTO("钱塘江大潮来袭","杭州之声","每年8月18,钱塘江大潮最壮观……",15L);
obserable.notifyObservers(articleDTO);
}
}
测试5.测试结果
4.总结-观察者模式特点及适用场景
观察者模式特点:
(1) 观察者和被观察者使用接口方式进行逻辑解耦,两者之间耦合度较低,分离了消息生成层(被观察者)和消息响应层(观察者),两方业务相互独立,无论哪一方有变化,都不会影响另一方,有利于进行扩展。
(2) 重点在于被观察者的实现,需要定义保存观察者引用的方法和通知观察者发布信息的方法。
(3) 观察者需要定义接收通知消息的方法update即可。
适用场景:
(1)消息的发布订阅,事件监听,广播通讯。
(2)对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
(3)对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
还没有评论,来说两句吧...