java之观察者模式

简介:   一、Observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。JDK里提供的observer设计模式的实现由java.util.Observable类和 java.util.Observer接口组成。

  一、Observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。JDK里提供的observer设计模式的实现由java.util.Observable类和 java.util.Observer接口组成。从名字上可以清楚的看出两者在Observer 设计模式中分别扮演的角色:Observer是观察者角色,Observable是被观察目标(subject)角色。

  二、观察者模式的优点:

    1、 Subject和Observer之间是松耦合的,分别可以各自独立改变。
    2、 Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
    3、 遵守大部分GRASP原则和常用设计原则,高内聚、低耦合。
  三、观察者模式的缺陷:
    1、 松耦合导致代码关系不明显,有时可能难以理解。(废话)
    2、 如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)
  四、结构图
    1)注册时:
    

    2)Subject触发时:

    

  五、这里写了一个实际开发中很有用的观察者模式的架构

  1)观察者实现,抽象类的目的在于开发者只需要处理onMessage中的数据即可,不需要处理更多数据

package com.pinnet.observer;

import com.pinnet.observable.MessageObservable;

import javax.jms.ObjectMessage;
import java.util.Observable;
import java.util.Observer;

/**
 * 观察者
 * 抽象类的目的是更好的简化开发,实际开发中很有必要
 */
public abstract class MessageObserver implements Observer {

    /**
     * 目的是在操作观察者的时候就加入到对应的被观察者中
     * @param messageObservable
     */
    public MessageObserver(MessageObservable messageObservable) {
        if (messageObservable == null) {
            return;
        }
        messageObservable.addObserver(this);
    }

    /**
     * 数据存在改变时触发,也是消息接收者
     * @param observable
     * @param object
     */
    public void update(Observable observable, Object object) {
        //这里采用ObjectMessage的数据形式,为了更好的传输对象数据
        ObjectMessage objectMessage = (ObjectMessage) object;
        onMessage(objectMessage);
    }

    /**
     * 消息处理,需要具体实现
     * @param objectMessage
     */
    public abstract void onMessage(ObjectMessage objectMessage);

}

  2)被观察者的继承,被观察者的方法基本都完善了,我们这里继承的目的是为了更好的理解

package com.pinnet.observable;

import javax.jms.ObjectMessage;
import java.util.Observable;

/**
 * 被观察者
 * 用来发送消息,这里不直接应用,采用消息中心模式在处理
 */
public class MessageObservable extends Observable {

    /**
     * 发送消息在center中使用
     * @param objectMessage
     */
    public void sendMessage(ObjectMessage objectMessage) {
        //设置改变点
        setChanged();
        //发给观察者
        notifyObservers(objectMessage);
    }
}

  3)消息处理中心,目的是为了提供更有用的工具

package com.pinnet.center;

import com.pinnet.observable.MessageObservable;
import org.apache.activemq.command.ActiveMQObjectMessage;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息处理中心,所有操作全部在这里
 */
public class MessageCenter {

    //用于保存具体被观察者,发送数据,注册等
    public static Map<MessageType, MessageObservable> messageMap = new ConcurrentHashMap<MessageType, MessageObservable>();

    /**
     * 获取被观察者,添加观察者
     * @param messageType
     * @return
     */
    public MessageObservable getMessageObservable(MessageType messageType) {
        if (messageMap.containsKey(messageType)) {
            return messageMap.get(messageType);
        } else {
            MessageObservable messageObservable = new MessageObservable();
            messageMap.put(messageType, messageObservable);
            return messageObservable;
        }
    }

    /**
     * 发送消息,统一入口
     * @param messageType
     * @param serializable
     */
    public void sendMessage(MessageType messageType, Serializable serializable) {
        if (messageMap.containsKey(messageType)) {
            try {
                MessageObservable messageObservable = messageMap.get(messageType);
                //这里采用的是ActiveMQ中实现类,当然可以自己实现ObjectMessage也可以
                ObjectMessage objectMessage = new ActiveMQObjectMessage();
                objectMessage.setObject(serializable);
                //被观察者发送给每个观察者
                messageObservable.sendMessage(objectMessage);
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 枚举类的目的是更好的控制数据发送
     */
    public enum MessageType {
        PUB,SUB
    }
}

  4)测试:简单实现一下即可,当然需要注册(注册部分可以写成xml,也可以自己写启动类)

  a、写了两个观察者的实现类

package com.pinnet.observer.impl;

import com.pinnet.observable.MessageObservable;
import com.pinnet.observer.MessageObserver;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;

/**
 * 消息监听
 */
public class PUBMessageListener extends MessageObserver {

    /**
     * 目的是在操作观察者的时候就加入到对应的被观察者中
     *
     * @param messageObservable
     */
    public PUBMessageListener(MessageObservable messageObservable) {
        super(messageObservable);
    }

    /**
     * 消息处理
     * @param objectMessage
     */
    public void onMessage(ObjectMessage objectMessage) {
        try {
            System.out.println(objectMessage.getObject());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

}
package com.pinnet.observer.impl;

import com.pinnet.observable.MessageObservable;
import com.pinnet.observer.MessageObserver;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;

public class SUBMessageListener extends MessageObserver {

    /**
     * 目的是在操作观察者的时候就加入到对应的被观察者中
     *
     * @param messageObservable
     */
    public SUBMessageListener(MessageObservable messageObservable) {
        super(messageObservable);
    }

    /**
     * 消息处理
     * @param objectMessage
     */
    public void onMessage(ObjectMessage objectMessage) {
        try {
            System.out.println(objectMessage.getObject());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

}

  b、注册:统一写在了MessageCenter中

/**
     * 注册
     */
    public static void init() {
        new PUBMessageListener(MessageCenter.getMessageObservable(MessageType.PUB));
        new PUBMessageListener(MessageCenter.getMessageObservable(MessageType.PUB));
        new SUBMessageListener(MessageCenter.getMessageObservable(MessageType.SUB));
    }

  c、测试:

package com.pinnet;

import com.pinnet.center.MessageCenter;

public class Test {

    public static void main(String[] args) {
        MessageCenter.init();
        MessageCenter.sendMessage(MessageCenter.MessageType.PUB, "pub");
        MessageCenter.sendMessage(MessageCenter.MessageType.SUB, "sub");
    }
}

  d、结果

  

  六、观察者模式应用还是很不错的,特别是在分发数据,socket推送过后的数据分发处理等。当然不会离开消息队列,下一个博客将写到jms的用法。

  七、源码参考:https://pan.baidu.com/s/1qBSIRXXRoMXsmHsi-yKehA

相关文章
|
4月前
|
设计模式 监控 Java
设计模式 - 观察者模式(Observer):Java中的战术与策略
【4月更文挑战第7天】观察者模式是构建可维护、可扩展系统的关键,它在Java中通过`Observable`和`Observer`实现对象间一对多的依赖关系,常用于事件处理、数据绑定和同步。该模式支持事件驱动架构、数据同步和实时系统,但需注意避免循环依赖、控制通知粒度,并关注性能和内存泄漏问题。通过明确角色、使用抽象和管理观察者注册,可最大化其效果。
99 2
|
1月前
|
设计模式 存储 前端开发
【十四】设计模式~~~行为型模式~~~观察者模式(Java)
文章详细介绍了观察者模式(Observer Pattern),这是一种对象行为型模式,用于建立对象之间的一对多依赖关系。当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。文中通过交通信号灯与汽车的案例以及多人联机对战游戏的设计方案,阐述了观察者模式的动机和应用场景。接着,文章介绍了观察者模式的结构、角色、优点、缺点以及适用情况,并通过代码示例展示了如何在Java中实现观察者模式。此外,还探讨了观察者模式在MVC架构中的应用以及Java中对观察者模式的支持。
【十四】设计模式~~~行为型模式~~~观察者模式(Java)
|
2月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
60 1
|
2月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
43 1
|
2月前
|
设计模式 Java
Java面试题:什么是观察者模式以及如何在Java中实现?
Java面试题:什么是观察者模式以及如何在Java中实现?
21 0
|
2月前
|
设计模式 Java
Java面试题:描述观察者模式的工作原理及其在Java中的应用。
Java面试题:描述观察者模式的工作原理及其在Java中的应用。
26 0
|
2月前
|
设计模式 SQL 安全
Java面试题:设计一个线程安全的内存管理器,使用观察者模式来通知所有线程内存使用情况的变化。如何确保在添加和移除内存块时的线程安全?如何确保任务的顺序执行和调度器的线程安全?
Java面试题:设计一个线程安全的内存管理器,使用观察者模式来通知所有线程内存使用情况的变化。如何确保在添加和移除内存块时的线程安全?如何确保任务的顺序执行和调度器的线程安全?
23 0
|
2月前
|
设计模式 存储 缓存
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
25 0
|
3月前
|
存储 Java 测试技术
技术经验解读:【Java】事件驱动模型和观察者模式
技术经验解读:【Java】事件驱动模型和观察者模式
|
3月前
|
设计模式 存储 Java
Java设计模式之观察者模式详解
Java设计模式之观察者模式详解