描述
- 一对多的依赖关系,多个观察者监听某一个主题对象。
- 主题对象发送变更时,会通知所有观察者对象,观察者就会去更新自己。
- 比如:微信公众号,公众号有消息,关注微信公众号的用户就会收到消息。
角色
- 抽象主题角色:被观察的主题对象,保存观察者对象在集合中,可添加删除观察者对象。
- 具体主题角色:具体的主题对象。发送变化时,会通知观察者对象。
- 抽象观察者角色:观察者的抽象类,定义接收消息的接口。
- 具体观察者角色:具体的观察者对象,接收到主题消息时,回去更新自己。
实现
public class Test {
public static void main(String[] args) {
HaHaOfficialAccount officialAccount = new HaHaOfficialAccount();
officialAccount.subscribe(new WeiXinUser("华为"));
officialAccount.subscribe(new WeiXinUser("小米"));
officialAccount.subscribe(new WeiXinUser("苹果"));
officialAccount.push("下班了!!!");
}
}
// 抽象主题角色 (公众号)
interface OfficialAccount {
// 订阅
void subscribe(User user);
// 取消订阅
void cancel(User user);
// 消息推送
void push(String message);
}
// 具体主题角色
class HaHaOfficialAccount implements OfficialAccount {
// 订阅者
private List<User> userList = new ArrayList<>();
@Override
public void subscribe(User user) {
userList.add(user);
}
@Override
public void cancel(User user) {
userList.remove(user);
}
@Override
public void push(String message) {
userList.forEach(item -> {
item.receive(message);
});
}
}
// 抽象观察者角色 用户
interface User {
// 消息接收
void receive(String message);
}
// 具体观察者角色
class WeiXinUser implements User {
private String userName;
public WeiXinUser(String userName) {
this.userName = userName;
}
@Override
public void receive(String message) {
System.out.println(userName + "接收到推送的消息:" + message);
}
}
优点
- 主题对象和观察者对象的耦合度降低。
- 主题对象发送通知,所有观察者对象都接收到消息,可以实现广播机制。
缺点
- 观察者对象比较多时,最后一个观察者对象接收比较慢。
- 主题对象有循环依赖时,主题角色发送消息会使观察者对象循环调用,会导致OOM。
使用场景
- 对象之间存在一对多关系,一的一方状态发生改变,会影响其它对象时,可以使用观察者模式。
- 当一个抽象模型依赖另一个抽象模型时,可以使用观察者模式。
JDK中的应用
- JDK提供好了的观察者模式:Observable,Observer
- 抽象主题角色:Observable
- 抽象观察者角色:Observer
添加观察者:addObserver
发布消息:notifyObservers
标明发生变化了,调用后为true,notifyObservers才会通知观察者:setChanged
抽象观察者角色监听变化:update
JDK提供的Observable,Observer实现
public class Test {
public static void main(String[] args) {
HaHaOfficialAccount haHaOfficialAccount = new HaHaOfficialAccount();
haHaOfficialAccount.addObserver(new WeiXinUser());
haHaOfficialAccount.push("你好啊");
}
}
// 具体主题角色
class HaHaOfficialAccount extends Observable {
public void push(String message) {
super.setChanged(); // 标识
super.notifyObservers(message); //通知
}
@Override
public String toString() {
return "我是具体主题角色";
}
}
// 具体观察者
class WeiXinUser implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println(o);
System.out.println(arg);
}
}