观察者模式

在对象之间定义一个一对多的关系,因此当一个对象状态改变,其它的关联对象(依赖它的)都被通知并且可以自动更新

概念

在这个模式中,存在很多观察者,它们在观察着同一个主题(对象)。当这个主题发生了改变,这些观察者希望被通知。因此,它们将自己注册到被观察的主题上,当它们不再对这个主题感兴趣,只要解除注册即可(也叫广播-接收模式)

例子

现实:粉丝和偶像之间的关系(粉丝是观察者,偶像是被关注的主题)
编程世界:UI和数据库的关系,数据库发生了数据变更之后,UI应该显示新的数据(自动更新)

展示

这里存在一个Observer,一个Subject,当subject的flag改变,observer会被通知,当observer不再关注这个主题,那么flag改变不会通知observer

Code

public class ObserverPattern {
    public static void main(String[] args) {
        Observer o1 = new Observer();
        Subject sub1 = new Subject();
        sub1.register(o1);
        System.out.println("Setting Flag = 5 ");
        sub1.setFlag(5);
        System.out.println("Setting Flag = 25 ");
        sub1.setFlag(25);
        sub1.unregister(o1);
//No notification this time to o1 .Since it is unregistered.
        System.out.println("Setting Flag = 50 ");
        sub1.setFlag(50);
    }
}

class Observer {
    public void update() {
        System.out.println("flag modified!");
    }
}

interface ISubject {
    void register(Observer observer);
    void unregister(Observer observer);
    void notifyAllObservers();
}

class Subject implements ISubject {

    private List<Observer> observerList = new ArrayList<>(16);
    private int flag;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
        notifyAllObservers();
    }

    @Override
    public void register(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void unregister(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyAllObservers() {
        for (Observer o: observerList) {
            o.update();
        }
    }
}

改进

  1. 存在很多不同类的观察者
  2. 观察者想知道到底是什么发生了改变

UML图

代码改动

List<Observer> observerList = new ArrayList<Observer>();
// 接口来保证能接收不同类型的观察者
List<IObserver> observersList=new ArrayList<IObserver>();

全部代码:

public class ObserverPattern {
    public static void main(String[] args) {
        System.out.println("*** Modified Observer Pattern Demo***\n");
        Subject sub = new Subject();
        Observer1 ob1 = new Observer1();
        Observer2 ob2 = new Observer2();
        sub.register(ob1);
        sub.register(ob2);
        sub.setFlag(5);
        System.out.println();
        sub.setFlag(25);
        System.out.println();
//unregister ob1 only
        sub.unregister(ob1);
//Now only ob2 will observe the change
        sub.setFlag(100);
    }
}

class Observer1 implements IObserver {

    @Override
    public void update(int i) {
        System.out.println("Observer1: myValue in Subject is now: "+i);
    }
}

class Observer2 implements IObserver {

    @Override
    public void update(int i) {
        System.out.println("Observer2: observes ->myValue is changed in Subject to :"+i);
    }
}

interface ISubject {
    void register(IObserver observer);
    void unregister(IObserver observer);
    void notifyAllObservers(int i);
}

interface IObserver {
    void update(int i);
}

class Subject implements ISubject {

    private List<IObserver> observerList = new ArrayList<>(16);
    private int flag;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
        notifyAllObservers(this.flag);
    }

    @Override
    public void register(IObserver observer) {
        observerList.add(observer);
    }

    @Override
    public void unregister(IObserver observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyAllObservers(int i) {
        for (IObserver o: observerList) {
            o.update(flag);
        }
    }
}

实现多个主题和多个观察者

自己做的:

思路:观察者模式的核心在于保有一个观察者列表,并且每个主题(类)的被关注值改变时通知列表中的所有观察者(对象)

假设:有三个观察者,两个主题

代码

public class ObserverPattern {
    public static void main(String[] args) {
        System.out.println("*** Modified Observer Pattern Demo***\n");
        Subject1 sub1 = new Subject1();
        SubJect2 sub2 = new SubJect2();
        Observer1 ob1 = new Observer1();
        Observer2 ob2 = new Observer2();
        Observer2 ob3 = new Observer2();
        sub1.register(ob1);
        sub1.register(ob2);
        sub2.register(ob1);
        sub2.register(ob2);
        sub2.register(ob3);

        sub1.setFlag(5);
        System.out.println();
        sub1.setFlag(25);
        System.out.println();
//unregister ob1 only
        sub1.unregister(ob1);
//Now only ob2 will observe the change
        System.out.println();
        sub1.setFlag(100);
        sub2.setFlag(4);
        System.out.println();
        sub2.setFlag(6);
    }
}

class Observer1 implements IObserver {

    @Override
    public void update(int i) {
        System.out.println("Observer1: myValue in Subject is now: "+i);
    }
}

class Observer2 implements IObserver {

    @Override
    public void update(int i) {
        System.out.println("Observer2: observes ->myValue is changed in Subject to :"+i);
    }
}

interface ISubject {
    void register(IObserver observer);
    void unregister(IObserver observer);
    void notifyAllObservers(int i);
}

interface IObserver {
    void update(int i);
}

class Subject1 implements ISubject {

    private List<IObserver> observerList = new ArrayList<>(16);
    private int flag;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
        notifyAllObservers(this.flag);
    }

    @Override
    public void register(IObserver observer) {
        observerList.add(observer);
    }

    @Override
    public void unregister(IObserver observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyAllObservers(int i) {
        for (IObserver o: observerList) {
            o.update(flag);
        }
    }
}

class SubJect2 implements ISubject {
    private List<IObserver> observerList = new ArrayList<>(16);
    private int flag;

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
        notifyAllObservers(this.flag);
    }

    @Override
    public void register(IObserver observer) {
        observerList.add(observer);
    }

    @Override
    public void unregister(IObserver observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyAllObservers(int i) {
        for (IObserver o: observerList) {
            o.update(flag);
        }
    }
}

代码很多都是重复的,只要把核心点掌握还是好写的

总结

观察者模式是天然实现广播功能的,如果一个对象的动作被多个对象监听,那么可以使用此设计模式。一般过程:

  1. 设计主题接口和观察者接口
  2. 具体实现类
  3. 在主题类的被监听属性的设置方法中要调用接口中声明的通知方法
  4. 如果观察者需要知道被改变的值,那么在观察者接口的update方法中设置参数

其它:观察者接口中的update是观察者模式中体现主题改变的方法,即这个模式一般是观察者(对象)(可变化的)随主题(对象)的变化而变化

posted on 2020-11-23 18:33  老鼠不上树  阅读(83)  评论(0)    收藏  举报