聊聊观察者模式

聊聊观察者模式

原理与应用场景

观察者模式(Observer Design Pattern)也被叫做发布订阅模式(Publish Subscribe Design Pattern)。

观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会自动收到通知。

一般情况下,被依赖的对象叫做被观察者(Observable),依赖对象的对象叫做观察者(Observer)。不过,在实际项目开发中,这两种对象的叫法都比较灵活,有各种不同的叫法,比如:Subject-Observe、Publiser-Subscrible、Producter-Consumer等等。无论叫什么,只要符合使用场景的,都可以被叫做观察者模式。

使用观察者模式,都是为了松耦合,让代码的灵活性更高。

既然如此,我们先给定一个场景,我希望用户都能去关注微信公众号,但也不白关注,只要一关注就给关注的用户发送奖励。

流程图

public interface WeChatSubject {
    /**
     * 注册观察者
     * @param o
     */
    void registerObserver(WeChatObserver o);

    /**
     * 移除观察者
     * @param o
     */
    void removeObserver(WeChatObserver o);

    /**
     * 通知观察者
     *
     * @param user 用户
     */
    void notifyObservers(String user);
}

public interface WeChatObserver {
    /**
     * 发送通知
     *
     * @param user 用户
     */
    void notify(String user);
}

public class WeChatFollowSubject implements WeChatSubject {
    private final List<WeChatObserver> weChatObservers = new CopyOnWriteArrayList<>();

    @Override
    public void registerObserver(WeChatObserver o) {
        weChatObservers.add(o);
    }

    @Override
    public void removeObserver(WeChatObserver o) {
        weChatObservers.remove(o);
    }

    @Override
    public void notifyObservers(String user) {
        weChatObservers.forEach(weChatObserver -> weChatObserver.notify(user));
    }
}

public class RewardObserver implements WeChatObserver {
    @Override
    public void notify(String user) {
        System.out.println("给" + user + " 发送关注奖励...");
        // 发送奖励处理...
    }
}

测试执行

...
public static void main(String[] args) {
    WeChatSubject weChatSubject = new WeChatFollowSubject();
    weChatSubject.registerObserver(new RewardObserver());

    // 新增关注用户
    weChatSubject.notifyObservers("ABC-123456");
}

... 执行结果

给ABC-123456 发送关注奖励...

这样,就完成了我们想要的功能,给新关注的用户发送奖励。

后来,又有新的需求,需要给新关注的用户初始化一个电子卡卷,用户可以用电子卡卷进行线下消费。

实现起来也非常简单,只需要新增一个观察者即可:

public class ElectronicCardObserver implements WeChatObserver {
    @Override
    public void notify(String user) {
        System.out.println("给" + user + " 生成电子卡卷信息...");
        // 电子卡卷生成...
    }
}

执行测试

public static void main(String[] args) {
    WeChatSubject weChatSubject = new WeChatFollowSubject();
    weChatSubject.registerObserver(new ElectronicCardObserver());
    weChatSubject.registerObserver(new RewardObserver());

    // 新增关注用户
    weChatSubject.notifyObservers("ABC-123456");
}
... 执行结果
给ABC-123456 生成电子卡卷信息...
给ABC-123456 发送关注奖励...

很轻松的就完成了,我们的需求。

在没使用观察者模式,可能更多的是,对公众号关注时,通过公众号那边主动发起,然后在代码里面调用各种的服务,代码耦合程度非常高。

观察者模式,帮我们做了一个解耦,只需要将观察者注册到主题,再通过公共号主动发起的请求,做通知,去做执行发送通知给每个观察者。

观察者模式,还可以用于很多场景,例如订阅技术主题的周报,只要周报一更新,订阅过这个周报的用户,也都可以接收到。不想接收了,就取消订阅。

这也是,我们经常使用的发布订阅模式。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×