zoukankan      html  css  js  c++  java
  • 设计模式之观察者模式

    观察者模式(observer)

    什么是观察者模式:因为面向对象程序的本质是对象之间的相互协作,所以其中一个对象发生变化,另外的某些对象也应该做出相应的动作。观察者模式就是为了应对该情况:对象间存在一种一对多(一对一)的依赖关系,当该对象发生变化时,所有依赖它的对象都得到通知并自动更新。

    适用性:对象间存在一种一对多(一对一)的依赖关系。

    观察者模式的主要组成: 抽象被观察者、具体被观察者(前两者有时候也可以合并)、抽象观察者、具体观察者。

    观察者模式的关键步骤:

    抽象被观察者:维护一个观察者容器;变化标志位,表明被观察者是否变化;通知方法,调用所有观察者的update()方法;

    具体被观察者:继承抽象被观察者;定义具体观察者变化的方法(包括判断是否变化、设置标志位、通知观察者);

    抽象观察者:update()方法;

    具体观察者:订阅被观察者;实现update()方法;

    观察者模式要点:

    抽象被观察者:维护观察者容器、变化标志位、提供注册和注销观察者的方法、通知方法;

    具体被观察者:继承抽象、实现对象变化需要通知观察者的方法setDate();

    抽象观察者:update()方法;

    具体观察者:继承抽象、订阅被观察者、实现update()方法;

    观察者模式基本代码:

    /*抽象被观察者*/
    
    public abstract class Subject {
        private Vector<Observer> observers; //保存所有观察者的容器
        private boolean changed = false;  //是否变化的标志位
    
        public Subject() {
            this.observers = new Vector<>();
        }
    
        public void addObserver(Observer obs){ //添加观察者,相当于注册观察者
            if(obs == null){
                throw new NullPointerException();
            }
            if(!observers.contains(obs)){
                observers.add(obs);
            }
        }
    
        public void deleteObserver(Observer obs){ //删除观察者,相当于注销观察者
            observers.removeElement(obs);
        }
    
    
        public void notifyObservers() {
            notifyObservers(null);
        }
    
        /**
         * 如果本对象有变化(那时hasChanged 方法会返回true)
         * 调用本方法通知所有登记的观察者,即调用它们的update()方法
         * 传入this和arg作为参数
         */
        public void notifyObservers(Object arg) {
            synchronized (this) {
                    if (!changed)
                        return;
            }
            for (Observer obs : observers)
                obs.update(this,arg);
        }
    
    
        public synchronized void deleteObservers() {
            observers.removeAllElements();
        }
    
        protected synchronized void setChanged() {
            changed = true;
        }
    
        protected synchronized void clearChanged() {
            changed = false;
        }
    
        public synchronized boolean hasChanged() {
            return changed;
        }
    
        public synchronized int countObservers() {
            return observers.size();
        }
    }
    /*观察者接口*/
    
    public interface Observer {
        //当被观察者发生变化时,会调用观察者的update方法
        void update(Subject o, Object arg);
    }
    /*具体被观察者*/
    public class ConcreteSubject extends Subject {
        private String data = "";
    
        public String getData() {
            return data;
        }
    
        public void setData(String data) {
    
            if (!this.data.equals(data)) {
                this.data = data;
                setChanged(); //设置改变标志
            }
            notifyObservers(); //通知观察者
        }
    }
    /*具体观察者*/
    public class ConcreteObserver implements Observer{
    
        public ConcreteObserver(Subject observed){ //订阅,将观察者注册到被观察者
            observed.addObserver(this);                                     
        }
    
        @Override
        public void update(Subject o,Object arg) {
            //观察者的行为
            System.out.println("观察者的行为");
        }
    }

    总结:

    1 独立改变被观察者和观察者

    2 观察者决定是否订阅

  • 相关阅读:
    C++闭包到C函数指针转化
    是否使用预编译头文件
    多线程模型一:只完成最新任务
    关于“函数针对入参判空并返回”
    C++函数参数的编写
    .Net Core(二) 下
    微信接口本地调试(IIS服务器)
    .Net Core 学习(二)上篇
    .Net Core学习(一)
    博客园的第一个博客
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11039751.html
Copyright © 2011-2022 走看看