观察者模式
观察者模式又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
应用场景
-
一个对象的改变会导致一个或多个对象发生改变,而并不知道具体有多少对象将会发生改变,也不知道这些对象是谁
-
当一个抽象模型有两个方面,其中的一个方面依赖于另一个方面时,可将这两者封装在独立的对象中以使他们可以各自独立地改变和复用
-
需要在系统中创建一个触发链,使得事件拥有跨域通知(跨越两种观察者的类型)
观察者模式的优缺点
优点
观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。
缺点
在应用观察者模式时需要考虑一下开发小路问题,程序中包括一个被观察者和多个被观察者,开发和调试比较复杂,而且Java中的消息的通知默认是顺序执行的,一个观察者的卡顿会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。
观察者模式结构
观察者模式中有如下角色:
-
Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
-
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
-
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
-
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
观察者模式具体实现
Subject:抽象主题(抽象被观察者)
public interface Subject {
void registerObserver(Observer o);
void removeObserve(Observer o);
void notiyObserver();
}
ConcreteSubject:具体主题(具体被观察者)
public class WechatServer implements Subject{
private List<Observer> list;
private String message;
public WechatServer() {
list = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserve(Observer o) {
if (!list.isEmpty()) {
list.remove(o);
}
}
@Override
public void notiyObserver() {
for (Observer o:list){
o.update(message);
}
}
public void setInfomation(String s){
this.message = s;
System.out.println("微信服务更新消息:"+s);
// 消息更新 通知所有观察者
notiyObserver();
}
}
Observer:抽象观察者
public interface Observer {
void update(String message);
}
ConcrereObserver:具体观察者
public class User implements Observer{
private String name;
private String message;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read(){
System.out.println(name + "收到推送消息"+message);
}
}
测试
public class MainTest {
public static void main(String[] args) {
WechatServer server = new WechatServer();
Observer userZhang = new User("zhangSan");
Observer userLi = new User("LiSi");
Observer userWang = new User("WangWu");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("Go是世界上最好的语言");
System.out.println("------------------------");
server.registerObserver(userZhang);
server.setInfomation("JAVA是世界上最好的语言");
}
}