sponsored links

观察者模式 Observer Pattern

父博文地址:设计模式 - Design Patterns


一、是什么

  1. 定义:

    观察者模式定义了对象之间的「一对多依赖」,当一的对象改变时,它所有的依赖者都能够收到通知。

  2. 行为:

    一对多依赖中,「一」的一方保存所有「多」的一方的实例。

    观察者模式 Observer Pattern

二、实例

1. 类图的实现

  1. SubjectConcreteSubject

    public interface Subject {
        void registerObserver(Observer observer);
        void removeObserver(Observer observer);
        void notifyObservers();
    }
    
    public class ConcreteSubject implements Subject {
        private List<Observer> list = new ArrayList<>();    
        private Object data;
    
        @Override
        public void registerObserver(Observer observer) {
            if (!list.contains(observer)) {
                list.add(observer);
            }
        }
    
        @Override
        public void removeObserver(Observer observer) {
            list.remove(observer);
        }
    
        @Override
        public void notifyObservers() {
            for (Observer observer : list) {
                observer.update(data);
            }
        }
    
        public void setData(Object data) {
            this.data = data;
            notifyObservers();
        }
    }
  2. ObserverConcreteObserver

    public interface Observer {
        void update(Object object);
    }
    
    public class ConcreteObserver implements Observer {
        @Override
        public void update(Object data) {
            System.out.println("收到数据");
            // 收到数据,do something...
        }
    }
  3. 使用场景

    public class MainTest {
        public static void main(String[] args) {
            // 主题
            final ConcreteSubject concreteSubject = new ConcreteSubject();
            // 观察者
            final Observer observer1 = new ConcreteObserver();
            final Observer observer2 = new ConcreteObserver();
            // 注册
            concreteSubject.registerObserver(observer1);
            concreteSubject.registerObserver(observer2);
    
            // 主题状态改变
            concreteSubject.setData("模拟数据1");
    
            // 移除一个观察者后,再次改变主题状态
            concreteSubject.removeObserver(observer1);
            concreteSubject.setData("模拟数据2");
        }
    }

2. Java API内置的观察者支持

  1. 主题java.util.Observable,和我们的一个实现类

    public interface Observer {
        void update(Observable o, Object arg);
    }
    
    /**
     * 不需要我们写“注册”、“删除”、“通知”方法的实现了。
     */
    public class OneSubject extends Observable {
        private Integer data;
    
        public void setData(Integer data) {
            this.data = data;
            // 1. 需要更改一下标志位,说明主题状态改变了
            setChanged();
    
            // 2. 超类的“通知”方法:使用这个方法表明我们要让对方从主题“拉-pull”数据
            notifyObservers();
            // 超类的另一个重载:使用它表明我们要“推-push”数据到观察者
            // notifyObservers(data);
        }
    
        /**
         * 使用“pull”模式时,提供若干方法供调用者获取数据
         */
        public Integer getData() {
            return data;
        }
    }
  2. 观察者java.util.Observer,和我们的一个具体观察者

    public class ConcreteObserver implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            if (o instanceof OneSubject) {
                final Integer data = ((OneSubject) o).getData();
                System.out.println("收到数据:" + data);
                // 收到数据,do something...
            }
        }
    }
  3. 使用场景

    public class MainTest {
        public static void main(String[] args) {
            // 主题
            final OneSubject oneSubject = new OneSubject();
    
            // 观察者
            final ConcreteObserver concreteObserver1 = new ConcreteObserver();
            final ConcreteObserver concreteObserver2 = new ConcreteObserver();
    
            // 注册
            oneSubject.addObserver(concreteObserver1);
            oneSubject.addObserver(concreteObserver2);
    
            // 主题状态改变
            oneSubject.setData(1);
        }
    
    }
  4. Java内置主题java.util.Observable不方便的地方

    主题java.util.Observable是实现类而不是接口,这意味着:

    • 具体类不能再有超类了,毕竟Java 只能单继承。
    • 你无法将主题用于“组合”了,因为它的setChanged()protected的。想要使用它就必须使用“继承”。
Tags: