观察者模式
-
定义:又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
-
优点:观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。这样,增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类Newspaper不会修改代码,遵守了OCP原则。
-
缺点:在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。
-
博客:https://hanchao.blog.csdn.net/article/details/97149607、https://www.cnblogs.com/adamjwh/p/10913660.html
-
实例:报纸订阅场景:用户可以订阅报纸,也可以取消订阅报纸。可以将报纸发布给所有订阅它的用户。
-
类图:
-
代码:
/**
* 抽象观察者
*/
public interface Observer {
/**
* 消息更新
*
* @param message
*/
public void update(String message);
}
/**
* 具体观察者:订阅报纸的用户
*/
public class User implements Observer {
private Integer id;
private String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
/**
* 接收报纸
*
* @param message
*/
@Override
public void update(String message) {
System.out.println(this.name + " 接收报纸信息: " + message);
}
}
/**
* 主题抽象
*/
public interface Subject {
/**
* 注册
*/
void register(Observer observer);
/**
* 取消注册
*/
void remove(Observer observer);
/**
* 通知观察者们
*/
void notifyObservers();
}
/**
* 主题实现
*/
public class Newspaper implements Subject {
/**
* 订阅者列表
*/
private List<Observer> observerList;
/**
* 报纸信息
*/
private String message;
public void setMessage(String message) {
this.message = message;
}
public Newspaper() {
this.observerList = new ArrayList<>();
}
/**
* 订阅
*
* @param observer
*/
@Override
public void register(Observer observer) {
this.observerList.add(observer);
}
/**
* 取消订阅
*
* @param observer
*/
@Override
public void remove(Observer observer) {
this.observerList.remove(observer);
}
/**
* 向所有订阅者邮寄报纸
*/
@Override
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update(message);
}
}
}
/**
* 测试观察者模式
*/
public class TestObserver {
public static void main(String[] args) {
//Lily,Jack订阅报纸
Newspaper newspaper = new Newspaper();
User lily = new User(1, "Lily");
User jack = new User(2, "Jack");
newspaper.register(lily);
newspaper.register(jack);
//邮寄报纸
newspaper.setMessage("中国青年报");
newspaper.notifyObservers();
System.out.println("--------------------------------------");
//jack取消了订阅报纸
newspaper.remove(jack);
//邮寄报纸
newspaper.setMessage("环球时报");
newspaper.notifyObservers();
}
}