zoukankan      html  css  js  c++  java
  • 观察者模式(Observer)

    什么是观察者模式

    它定义对象间的一种一对多的依赖关系,可以在一个对象的状态/事件发生改变时,通知多个 “观察” 该对象的其他对象。

    这个应该很好理解,就像订阅机制一样。当订阅的内容更新后,会推送给所有订阅者了。

    注:观察者模式是一种行为模式(这类模式负责对象间的高效沟通和职责委派。)。

    主要角色

    抽象主题(Subject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。

    具体主题(Concrete Subject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。

    抽象观察者(Observer):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。

    具体观察者(Concrete Observer):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

    注:java中已提供相关支持类,java.util.Observable 和 java.util.Observer。
    Observable相关于抽象目标(Subject)的功能,Observer就是抽象观察者。查看下面的示例,再看下这两个类的源码就能很清楚。

    优缺点

    优点
    降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
    目标与观察者之间建立了一套触发机制。

    缺点
    当目标有很多直接或间接观察者时,通知所有观察者会花费很多时间,影响程序的效率。
    如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用(目标与观察者之间的依赖关系并没有完全解除),可能导致系统崩溃。

    实例demo

    目标即被观察者:保存所有观察者,当变化发生后通知所有观察者。

    //抽象目标类
    public abstract class Subscription {
        protected List<Subscriber> subscribers = new ArrayList<Subscriber>();
        public void addSubscriber(Subscriber subscriber) {
            subscribers.add(subscriber);
        }
        
        public void deleSubscriber(Subscriber subscriber) {
            subscribers.remove(subscriber);
        }
        
        public abstract void subscriptionUpdate(String content);
    }
    
    //具体目标类
    public class SubscriptionBlog extends Subscription {
        @Override
        public void subscriptionUpdate(String content) {
            for (Subscriber subscriber : subscribers) {
    			subscriber.receiveNotification(content);
    		}
        }
    }
    

    观察者:获得目标变化的通知,并处理。

    //抽象观察者
    public interface Subscriber {
        void receiveNotification(String notification);
    }
    
    //3个具体观察者
    public class Subscriber1 implements Subscriber {
        @Override
        public void receiveNotification(String notification) {
            System.out.println("Subscriber1 收到通知:"+notification);
        }
    }
    
    public class Subscriber2 implements Subscriber {
        @Override
        public void receiveNotification(String notification) {
            System.out.println("Subscriber2 收到通知:"+notification);
        }
    }
    
    public class Subscriber3 implements Subscriber {
        @Override
        public void receiveNotification(String notification) {
            System.out.println("Subscriber3 收到通知:"+notification);
        }
    }
    

    客户端调用:这里目标有3次变化,每次变化观察者也是变化的,可以注意下。

    public class ObserverTest {
        public static void main(String[] args) {
            Subscription subscription = new SubscriptionBlog();
            Subscriber subscriber1 = new Subscriber1();
            Subscriber subscriber2 = new Subscriber2();
            Subscriber subscriber3 = new Subscriber3();
            
            subscription.addSubscriber(subscriber1);
            subscription.addSubscriber(subscriber2);
            System.out.println("-----目标变化-----");
            subscription.subscriptionUpdate("xxx新增了一篇博客A。");
            System.out.println();
            
            subscription.addSubscriber(subscriber3);
            System.out.println("-----目标变化-----");
            subscription.subscriptionUpdate("xxx更新了一篇博客A。");
            System.out.println();
            
            subscription.deleSubscriber(subscriber2);
            System.out.println("-----目标变化-----");
            subscription.subscriptionUpdate("xxx新增了一篇博客B。");
        }
    }
    

    实例结果:

    -----目标变化-----
    Subscriber1 收到通知:xxx新增了一篇博客A。
    Subscriber2 收到通知:xxx新增了一篇博客A。
    
    -----目标变化-----
    Subscriber1 收到通知:xxx更新了一篇博客A。
    Subscriber2 收到通知:xxx更新了一篇博客A。
    Subscriber3 收到通知:xxx更新了一篇博客A。
    
    -----目标变化-----
    Subscriber1 收到通知:xxx新增了一篇博客B。
    Subscriber3 收到通知:xxx新增了一篇博客B。
    
  • 相关阅读:
    .htaccess 文件不起作用?| (Apache Rewrite)
    Putty 如何解决中文乱码(笔记)
    如何删除鼠标右键“发送到”的多余项
    开发环境搭建笔记
    Javascript String 包
    第十五章:使用canvas绘图
    慕课css3 2章边框和3章颜色相关
    第5章引用类型
    第一章 JavaScript简介
    第五章引用类型(Object类型、Array类型)
  • 原文地址:https://www.cnblogs.com/fanglongxiang/p/13233258.html
Copyright © 2011-2022 走看看