一、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. Message;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       */    public void update(Observable observable,    ) {        //这里采用 Message的数据形式,为了更好的传输对象数据         Message  Message = ( Message)  ;        onMessage( Message);    }    /**     * 消息处理,需要具体实现     * @param  Message     */    public abstract void onMessage( Message  Message);

}

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

package com.pinnet.observable;import javax.jms. Message;import java.util.Observable;/** * 被观察者 * 用来发送消息,这里不直接应用,采用消息中心模式在处理 */public class MessageObservable extends Observable {    /**     * 发送消息在center中使用     * @param  Message     */    public void sendMessage( Message  Message) {        //设置改变点        setChanged();        //发给观察者        notifyObservers( Message);    }}

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

package com.pinnet.center;import com.pinnet.observable.MessageObservable;import org.apache.activemq.command.ActiveMQ Message;import javax.jms.JMSException;import javax.jms. Message;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中实现类,当然可以自己实现 Message也可以                 Message  Message = new ActiveMQ Message();                 Message.set (serializable);                //被观察者发送给每个观察者                messageObservable.sendMessage( Message);            } catch (JMSException e) {                e.printStackTrace();            }        }    }    /**     * 枚举类的目的是更好的控制数据发送     */    public enum MessageType {        PUB,SUB    }}

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

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

package com.pinnet.observer.impl;import com.pinnet.observable.MessageObservable;import com.pinnet.observer.MessageObserver;import javax.jms.JMSException;import javax.jms. Message;/** * 消息监听 */public class PUBMessageListener extends MessageObserver {    /**     * 目的是在操作观察者的时候就加入到对应的被观察者中     *     * @param messageObservable     */    public PUBMessageListener(MessageObservable messageObservable) {        super(messageObservable);    }    /**     * 消息处理     * @param  Message     */    public void onMessage( Message  Message) {        try {            System.out.println( Message.get ());        } 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. Message;public class SUBMessageListener extends MessageObserver {    /**     * 目的是在操作观察者的时候就加入到对应的被观察者中     *     * @param messageObservable     */    public SUBMessageListener(MessageObservable messageObservable) {        super(messageObservable);    }    /**     * 消息处理     * @param  Message     */    public void onMessage( Message  Message) {        try {            System.out.println( Message.get ());        } 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

收藏 打印