美文网首页
设计模式 -- 观察者模式

设计模式 -- 观察者模式

作者: tom_xin | 来源:发表于2018-11-18 16:14 被阅读0次

    什么是观察者模式

        定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。


    使用场景

    1. 解耦:当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
    2. 可扩展性:当一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
    3. 当一个对象必须通知其他对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合。

    观察者模式的结构

        


    image.png

    Subject(目标)
    当它的状态发生改变时,向它的各个观察者发出通知。
    Observer(观察者)
    实现Observer的更新接口以使自身状态与目标状态一致。


    观察者模式的优缺点

    优点

    1. 目标和观察者的抽象耦合:一个目标所知道仅仅是它有一系列观察者,每个都符合抽象的Observer类的简单接口。
    2. 支持广播通信:目标对象并不关心到底有多少对象对自己感兴趣,它唯一的职责就是通知它的各观察者。
      缺点:
    3. 意外更新:如果依赖准则的定义和维护不当,常常会引起错误的更新,这种错误通常很难捕获。

    观察者模式的实现

    先来看一个典型的实例:

    /**
     * 定义抽象的目标类
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public interface Subject {
    
        /**
         * 发送消息
         */
        void publish(String message);
    }
    
    /**
     * 定义一个具体的目标类
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class ConcreteSubject implements Subject {
    
        List<Observer> observerList = new ArrayList<>();
    
        /**
         * 添加观察者
         * 
         * @param observer
         */
        public void addObserver(Observer observer) {
            observerList.add(observer);
        }
    
        /**
         * 发送消息
         *  
         * @param message
         */
        @Override
        public void publish(String message) {
            for (Observer observer : observerList) {
                observer.handler(message);
            }
        }
    }
    
    
    /**
     * 自定义观察者
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.1.0
     */
    public interface Observer {
    
        /**
         * 处理消息
         *
         * @param message
         */
        void handler(String message);
    }
    
    
    /**
     * 创建实例观察者
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class ConcreteObserver implements Observer {
    
        /**
         * 处理消息
         *
         * @param message
         */
        @Override
        public void handler(String message) {
            System.out.println(this.getClass());
            System.out.println(message);
        }
    }
    
    
    /**
     * 创建实例观察者
     * 
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class ConcreteObserver1 implements Observer {
    
        /**
         * 处理消息类
         *
         * @param message
         */
        @Override
        public void handler(String message) {
            System.out.println(this.getClass() + ",message : " + message);
        }
    }
    
    
    /**
     * Main函数
     * 
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class ObserverMain {
    
        public static void main(String[] args) {
            // 实例化目标类
            Subject subject = new ConcreteSubject();
            // 定义观察者
            Observer observer1 = new ConcreteObserver();
            Observer observer2 = new ConcreteObserver1();
    
            ((ConcreteSubject) subject).addObserver(observer1);
            ((ConcreteSubject) subject).addObserver(observer2);
            // 发送消息
            subject.publish("notify message");
        }
    }
    

    Observer + Mediator 模式结合实现观察者模式,实现Observer与Mediator解耦。

    /**
     * 观察者接口
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public interface MediatorObserver {
    
        /**
         * 处理消息的接口
         *
         * @param message
         */
        void handler(String message);
    }
    
    
    /**
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class ObserverInstance implements MediatorObserver {
    
        public ObserverInstance() {
            // 在构造函数中
            MediatorInstance.register(this);
        }
    
        /**
         * 处理消息
         *
         * @param message
         */
        @Override
        public void handler(String message) {
            System.out.println(message);
        }
    }
    
    
    /**
     * 定义目标类
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class MediatorSubject {
    
        /**
         * 消息通知
         *
         * @param message
         */
        public void notify(String message) {
            MediatorInstance.publish(message);
        }
    }
    
    
    /**
     * 中介者实体类
     *
     * @author tomxin
     * @date 2018-11-18
     * @since v1.0.0
     */
    public class MediatorInstance {
    
        /**
         * 观察者列表
         */
        private static Set<Object> observerList = new HashSet<>(16);
    
        /**
         * 注册观察者
         *
         * @param observer
         */
        public static void register(Object observer) {
            observerList.add(observer);
        }
    
        /**
         * 发送消息
         *
         * @param message
         */
        public static void publish(String message) {
            try {
                for (Object observer : observerList) {
                    Class<?> observerClazz = observer.getClass();
                    Class[] classes = new Class[1];
                    classes[0] = String.class;
                    Method method = observerClazz.getMethod("handler", classes);
                    Object result = method.invoke(observer, message);
                }
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    
    /**
     * Main方法
     *
     * @author tomxin
     * @date 2018-11-17
     * @since v1.0.0
     */
    public class MediatorObserverMain {
    
        public static void main(String[] args) {
            // 实例化观察者
            ObserverInstance observerInstance = new ObserverInstance();
            // 实例化目标类
            MediatorSubject mediatorSubject = new MediatorSubject();
            // 发送消息通知
            mediatorSubject.notify("message");
        }
    }
    
    

    有兴趣的同学,可以看一下Guava中EventBus的实现。

    相关文章

      网友评论

          本文标题:设计模式 -- 观察者模式

          本文链接:https://www.haomeiwen.com/subject/frggxqtx.html