观察者设计模式
概念
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
应用场景
相信很多人都用过拼多多,最近拼多多一直推送9.9抢购商品。当我们点击订阅后,在开始抢购的前10分钟,拼多多就会提醒你去抢购。你也可以点击取消订阅,那么拼多多将不会提醒你。
这种场景我们就可以用到观察者设计模式。
结构
- Subject抽象主题类:它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象。
- Observer抽象观察者类:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
- ConcreteSubject具体主题类:将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知。
- ConcreteObserver具体观察者类:实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。
优点和缺点
优点:
- 观察者和被观察者都是抽象耦合的
- 建立了一套触发机制
缺点:
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
- 如果观察者和观察目标间有循环依赖,可能导致系统崩溃
- 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的
观察者设计模式实例
1. 创建Subject
/**
* @Auther: wdd
* @Date: 2020-04-18 16:35
* @Description: 抽象类秒杀产品主题
*/
public interface ProductSubject {
// 注册观察者
void registerUserObserver(UserObserver userObserver);
// 移除观察者
void removeUserObserver(UserObserver userObserver);
// 通知观察者
void notifyUserObserver();
}
2. 创建ConcreteSubject
import java.util.ArrayList;
import java.util.List;
/**
* @Auther: wdd
* @Date: 2020-04-18 16:50
* @Description: 秒杀产品具体实现
*/
public class ProductSubjectImpl implements ProductSubject{
// 集合, 存放订阅的用户
private List<UserObserver> observers;
// 产品名称
private String productName;
// 添加订阅的用户
public void registerUserObserver(UserObserver userObserver) {
observers.add(userObserver);
}
// 删除取消订阅的用户
public void removeUserObserver(UserObserver userObserver) {
observers.remove(userObserver);
}
// 给订阅的用户发送消息
public void notifyUserObserver() {
for (UserObserver userObserver : observers) {
userObserver.update();
}
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public ProductSubjectImpl(String productName) {
this.productName = productName;
this.observers = new ArrayList<UserObserver>();
}
}
3. 创建Observer
/**
* @Auther: wdd
* @Date: 2020-04-18 16:44
* @Description: 用户观察者
*/
public interface UserObserver {
// 接收消息
void update();
// 订阅
void register(ProductSubjectImpl productSubject);
// 取消订阅
void remove(ProductSubjectImpl productSubject);
}
4. 创建ConcreteObserver
/**
* @Auther: wdd
* @Date: 2020-04-18 16:53
* @Description: 具体实现用户
*/
public class UserObserverImpl implements UserObserver{
private String username;
private ProductSubjectImpl productSubjectImpl;
public UserObserverImpl(String username) {
this.username = username;
}
public void update() {
System.out.println("尊贵的" + username + "用户, " + productSubjectImpl.getProductName() + "还有10分钟就开始抢购了!");
}
// 用户订阅产品
@Override
public void register(ProductSubjectImpl productSubject) {
productSubject.registerUserObserver(this);
this.productSubjectImpl = productSubject;
}
// 用户取消订阅产品
@Override
public void remove(ProductSubjectImpl productSubject) {
productSubject.removeUserObserver(this);
}
}
5. 测试
/**
* @Auther: wdd
* @Date: 2020-04-18 17:06
* @Description:
*/
public class Client {
public static void main(String[] args) {
// 秒杀商品主题
ProductSubjectImpl mi = new ProductSubjectImpl("小米10");
// 用户
UserObserver zs = new UserObserverImpl("张三");
UserObserver ls = new UserObserverImpl("李四");
// 用户订阅
zs.register(mi);
ls.register(mi);
// 发布通知
mi.notifyUserObserver();
}
}
尊贵的张三用户, 小米10还有10分钟就开始抢购了!
尊贵的李四用户, 小米10还有10分钟就开始抢购了!
6. 不足
用户一次只能订阅一个商品,不能订阅多个,否则最后一个覆盖前面的,只能接收到最后一个商品的通知。
可以将用户中也设计一个集合,用来存放订阅的商品。
本文深入探讨了观察者设计模式的概念、结构、优缺点及应用案例。通过拼多多9.9抢购活动的具体实例,详细讲解了如何使用观察者模式实现订阅和通知功能,包括主题、观察者等关键组件的实现。
1380

被折叠的 条评论
为什么被折叠?



