Java设计模式 -- 观察者设计模式

本文深入探讨了观察者设计模式的概念、结构、优缺点及应用案例。通过拼多多9.9抢购活动的具体实例,详细讲解了如何使用观察者模式实现订阅和通知功能,包括主题、观察者等关键组件的实现。

观察者设计模式

概念

观察者模式(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. 不足

用户一次只能订阅一个商品,不能订阅多个,否则最后一个覆盖前面的,只能接收到最后一个商品的通知。

可以将用户中也设计一个集合,用来存放订阅的商品。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值