Java设计模式之观察者模式练习

本文介绍如何使用观察者模式解决业务中常见的登录注册后的消息通知问题,通过实例演示如何设计观察者模式,包括被观察者、观察者接口及其实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

登录注册是非常典型的业务需求,以用户注册为场景,用户注册成功后,会给用户发送一条消息,又或者发一个email等,如

public static void register(User user) {
        int insert = insert(user);
        sendImMessage();
        sendMobileMessage();
        sendEmailMessage();
    }

这样写是正常的逻辑,那会有什么问题呢?
如果需求变了或增加了,如用户注册成功,需要再发送一条短信,于是有得改register方法了,是不是违反了开闭原则了。并且若是发送短信的方法失败了,是不是影响用用户注册了?
这时候若是有个异步方法给通知一下就好了,实际上,可以通过使用观察者模式进行优化,使代码变得更优雅。
观察者模式

观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并完成处理。
观察者模式属于行为模式,一个对象(被观察者)的状态发生改变,所有的依赖对象(观察者)都将得到通知,进行广播通知。
被观察者:目标对象,状态发生变化时,将通知所有的观察者;
观察者:接受被观察者的状态变化通知,执行预先定义的业务;
使用场景:完成某件事情后,异步通知的场景,如登录成功,发送消息等;

观察者模式的实现:

一个被观察者的类Observerable;
一个观察者接口Observer;
多个观察者的实现;
public class Observerable {

    private List<Observer> observers = new ArrayList<>();

    private int state;

    /**
     * 添加观察者
     */
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    /**
     * 移除观察者
     */
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    /**
     * 通知
     * @return
     */
    public void notifyAllObserver(int state) {
        if (state != 1) {
            System.out.println("非通知状态");
            return;
        }
        for (Observer observer : observers) {
            observer.doEvent();
        }
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        notifyAllObserver(state);
    }
}
public interface Observer {
    /**
     * 观察者事件
     */
    void doEvent();
}
public class EmailObserver implements Observer {
    @Override
    public void doEvent() {
        System.out.println("发送email消息");
    }
}
public class IMMessageObserver implements Observer {
    @Override
    public void doEvent() {
        System.out.println("发送IM消息");
    }
}
public class MobileNoObserver implements Observer {
    @Override
    public void doEvent() {
        System.out.println("发送短信消息");
    }
}

测试

public static void main(String[] args) {
        User user = new User(1, "caocao", 0);
        register(user);
    }

    public static void register(User user) {
//        int insert = insert(user);
//        sendImMessage();
//        sendMobileMessage();
//        sendEmailMessage();

        int insert = insert(user);
        Observerable observerable = new Observerable();
        observerable.addObserver(new IMMessageObserver());
        observerable.addObserver(new EmailObserver());
        observerable.addObserver(new MobileNoObserver());
        observerable.setState(insert);
    }

    private static void sendEmailMessage() {
    }

    private static void sendMobileMessage() {
    }

    private static void sendImMessage() {
    }

    private static int insert(User user) {
        System.out.println("insert success");
        return 1;
    }

Guava EventBus封装好了一套观察者模式,提供基于注解的事件总线,实例如下

public class EventBusCenter {

    private static EventBus eventBus = new EventBus();

    private EventBusCenter() {
    }

    //添加观察者
    public static void register(Object obj) {
        eventBus.register(obj);
    }

    //移除观察者
    public static void unregister(Object obj) {
        eventBus.unregister(obj);
    }

    //把消息推给观察者
    public static void post(Object obj) {
        eventBus.post(obj);
    }

    public static EventBus getInstance() {
        return eventBus;
    }
}
public class EmailEventListener {

    @Subscribe //加了订阅,这里标记这个方法是事件处理方法
    public void handle(NotifyEvent notifyEvent) {
        System.out.println("发送Email消息" + notifyEvent.getEmailNo());
    }
}
public class ImEventListener {

    @Subscribe //加了订阅,这里标记这个方法是事件处理方法
    public void handle(NotifyEvent notifyEvent) {
        System.out.println("发送IM消息" + notifyEvent.getImNo());
    }
}
public class MobileEventListener {

    @Subscribe //加了订阅,这里标记这个方法是事件处理方法
    public void handle(NotifyEvent notifyEvent) {
        System.out.println("发送短信消息" + notifyEvent.getMobileNo());
    }
}

通知对象

public class NotifyEvent  {

    private String mobileNo;

    private String emailNo;

    private String imNo;

    public NotifyEvent(String mobileNo, String emailNo, String imNo) {
        this.mobileNo = mobileNo;
        this.emailNo = emailNo;
        this.imNo = imNo;
    }

    public String getMobileNo() {
        return mobileNo;
    }

    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }

    public String getEmailNo() {
        return emailNo;
    }

    public void setEmailNo(String emailNo) {
        this.emailNo = emailNo;
    }

    public String getImNo() {
        return imNo;
    }

    public void setImNo(String imNo) {
        this.imNo = imNo;
    }
}

测试

public static void main(String[] args) {
//        EventListener eventListener = new EventListener();
//        EventBusCenter.register(eventListener);
//        EventBusCenter.post(new NotifyEvent("13372817283", "123@qq.com", "666"));

        ImEventListener imEventListener = new ImEventListener();
        MobileEventListener mobileEventListener = new MobileEventListener();
        EmailEventListener emailEventListener = new EmailEventListener();
        EventBusCenter.register(imEventListener);
        EventBusCenter.register(mobileEventListener);
        EventBusCenter.register(emailEventListener);
        EventBusCenter.unregister(imEventListener);
        EventBusCenter.post(new NotifyEvent("12345678901","123456","999"));
    }

不同的观察者实现可借助spring容器进行统一注入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值