设计模式学习之四观察者模式

2021-01-08

想象一棵树,子节点中某些属性依赖于父节点某个属性。
当父节点中这个属性改变时想让这些子节点随之改变,该怎么设计代码结构呢?

父节点 Subject
子节点 Observer(1,2,3)
我的第一想法是 创造一个第三方,初始化subject 后 创建 第三方关系类,再初始化observer1,2,3 并依次在关系类中维护他们的关系。
subject有更新时,再调用关系类中 对observer对象们的更新。
但是,不仅引入了一个第三方模块,而且初始化一个subject时还得多初始化一个关系类。

观察者模式:
subject中 创造一个观察者列表的属性,并且维护一个通知观察者的方法,当它的某些属性改变时,调用这个方法,这个方法再依次调用对应的观察者的更新方法。

优点:
1. 观察者和被观察者耦合
2. 触发机制
缺点:
1. 耦合多
2. 如果有循环依赖可能会导致系统崩溃

应用场景:

1. 温度计实时测温 ,当温度发生变化时通知空调、人进行相应的调节。

2. ....反正就是一对多的关系中,当这个一出现变化时去通知别的多进行相应的更新。

 

package designpatterns.ob;

public abstract class Observer {
    protected Subject subject;
    public abstract void handleChange();
}

 

package designpatterns.ob;

public class ObserverA extends Observer{
    public ObserverA(Subject subject) {
        subject.attachObserver(this);
    }

    public void handleChange(){
        System.out.println("A中:subject新的name是:"+subject.getName());
    }
}

 

package designpatterns.ob;

public class ObserverB extends Observer{
    public ObserverB(Subject subject) {
        subject.attachObserver(this);
    }
    public void handleChange(){
        System.out.println("B中:subject新的name是:"+subject.getName());
    }
}

 

package designpatterns.ob;

import java.util.LinkedList;
import java.util.List;

public class Subject {
    List<Observer> observers = new LinkedList<>();
    private String name;
    public String getName(){
        return this.name;
    }

    public void updateName(String name){
        this.name = name;
        //通知它的观察者 自己被修改了
        notifyObservers();
    }

    private void notifyObservers(){
        for (Observer observer:observers){
            //调用处理 此次改动
            observer.handleChange();
        }
    }
    public void attachObserver(Observer observer){
        this.observers.add(observer);
    }
}

 

package designpatterns.ob;

public class T {
    public static void main(String[] args) {
        Subject subject = new Subject();
        new ObserverA(subject);
        new ObserverB(subject);
        subject.updateName("fuck");
        subject.updateName("aaa");
    }
}