Java设计模式之观察者模式

一、什么是观察者模式?

在这个模式中,有观察者和被观察者两个角色,当被观察者的状态发生改变时,要让所有观察它的观察者知道这个改变。举个例子,Redis的某个key过期了,需要通知一些对象这个key过期了,需要做一些业务操作。其中redis就是被观察者,一些对象就是观察redis的key过期的观察者。

二、例子实现

接下来实现上面举的例子,更深刻的了解观察者模式。

【观察者】

定义一个观察者的抽象接口。只要实现这个接口就可以成为观察者,拥有观察者的行为。

 public interface RedisKeyExpiredObserver {

        /**
         * 处理逻辑
         *
         * @param key
         */
        void handleExpiredKey(String key);

    }

【被观察者】

定义一个监听Redis的key过期的监听器

  • 当redis的key过期时,会执行这个监听器的onMessage方法,并通知所有的观察者。

  • 定义一个集合,用于保存所有的观察者。

  • 实现BeanPostProcessor 接口,用于收集Ioc容器中实现RedisKeyExpiredObserver接口的观察者。

  • 也可以自定义新增和删除观察者。

@Component
public class RedisKeyExpiredListener extends KeyExpirationEventMessageListener implements BeanPostProcessor {

    // 观察key过期的所有观察者
    ArrayList<RedisKeyExpiredObserver> observers = new ArrayList<>();

    public RedisKeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {

        // 失效的key
        String key = message.toString();
        // 通知所有的观察者
        observers.forEach(observer -> observer.handleExpiredKey(key));

    }

     /**
     * 收集redisKey实现的观察者
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if (bean instanceof RedisKeyExpiredObserver) {

            observers.add((RedisKeyExpiredObserver) bean);
        }

        return bean;
    }

    public void addRedisKeyExpiredObserver(RedisKeyExpiredObserver observer) {  observers.add(observer); }

    public void removeRedisKeyExpiredObserver(RedisKeyExpiredObserver observer) {  observers.remove(observer); }
}

【观察者的具体实现】

比如判断是登录信息过时,需要做一些操作。

@Service
public class LoginService implements RedisKeyExpiredObserver {

      @Override
    public void handleExpiredKey(String key) {
    
         // 登录信息过时,需要做一些操作
    }
}

三、优缺点

优点:

  • 根据依赖倒置原则,观察者和被观察者之间是抽象耦合,耦合度低,扩展性高。
  • 根据单一职责原则,每一个类的职责都是单一的。

缺点:

  • 需要考虑开发和运行效率问题,通知观察者是单线程顺序执行的,如果某个观察者卡住阻塞了,会影响到后面的观察者收到信息。如果需要信息的实时性,可以考虑异步通知的方式。

四、注意事项

尽量的不要让观察者有双重身份,既是观察者,也是被观察者,一旦通知链产生,逻辑就会变得很复杂,可维护性也很差。即使需要,最好只有一个双重身份的,也就是通知的消息只转发一次。

观察者模式中链和责任链模式中的链最大区别是,责任链中的消息在传递的过程中是不可变的,改变的话也是在原有的基础上改变。

也要考虑观察者过多时产生的效率问题。

你可能感兴趣的:(设计模式,设计模式,观察者模式,java)