设计模式--观察者模式

241 阅读2分钟

什么是观察者模式

观察者模式又称作发布-订阅模式,定义了一对多的依赖关系,让多个者对象同时监听某一个主题对象。这个主题对象发生变化时,会通知所有的观察者对象,使他们能够自动更新自己;

简单解释

声明一个被观察者(发布),由其它被观察者注册到被观察者中,当被观察者状态发生变化时,通知到所有的观察者,并由每个观察者做出的处理,从而达到解耦的目的;

UML类图

优点

1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。

缺点

1、如果一个被观察者的直接或间接的观察者对象有很多,那么将观察者通知完会花费很多时间;
2、如果观察者与观察者目标之间有相互依赖的话,观察者会触发它们之间的循环调用,会导致系统崩溃;
3、观察者模式没有机制让所有的观察者知道目标是如何发生变化的,仅仅知道目标发生了变化;

代码解释

以下雨天收衣服为例,妈妈发现下雨了,通知老大、老二、小明去收衣服、拖地、关窗户,但是未通知到小明,导致没有拖地;

  • 声明一个被观察者接口
/**
 * 定义一个抽象通知类
 * @author ws
 * @version 1.0
 */
public interface Subject {

    public void Add(Observer obj);

    public void Remove(Observer obj);

    public void Notify();

    public String SubjectState();
}

  • 声明一个老妈,观察是否下雨
import java.util.ArrayList;
import java.util.List;

public class LaoMaSubject implements Subject {

    List<Observer> observers=new ArrayList<>();

    @Override
    public void Add(Observer obj) {
        observers.add(obj);
    }

    @Override
    public void Remove(Observer obj) {
        observers.remove(obj);
    }

    @Override
    public void Notify() {
        for (Observer obj:observers) {
            obj.Update();
        }
    }

    @Override
    public String SubjectState() {
        return "下雨了";
    }
}

  • 声明一个观察者抽象类,定义更新方法
/**
 * 抽象观察者
 * @author ws
 * @version 1.0
 */
public abstract class Observer {

    protected String name;
    protected Subject sub;

    public Observer(String name,Subject sub){
        this.name=name;
        this.sub=sub;
    }

    public abstract void Update();

}
  • 声明相应的观察者实体类
public class GuanCHObj extends Observer {

    public GuanCHObj(String name, Subject sub) {
        super(name, sub);
    }

    @Override
    public void Update() {
        System.out.println(String.format("%s,%s去把窗户关了",sub.SubjectState(),name));
    }
}

public class ShouYiFuObj extends Observer {
    public ShouYiFuObj(String name, Subject sub) {
        super(name, sub);
    }

    @Override
    public void Update() {
        System.out.println(String.format("%s,%s去把衣服收了",sub.SubjectState(),name));
    }
}

public class TuoDiObj extends Observer {
    public TuoDiObj(String name, Subject sub) {
        super(name, sub);
    }

    @Override
    public void Update() {
        System.out.println(String.format("%s,%s去把衣服收了",sub.SubjectState(),name));
    }
}

  • 测试输出
public static void main(String[] args) {
    Subject laoma=new LaoMaSubject();
    Observer syf=new ShouYiFuObj("老大",laoma);
    Observer gch=new GuanCHObj("老二",laoma);
    Observer td=new TuoDiObj("小明",laoma);
    laoma.Add(syf);
    laoma.Add(gch);
    laoma.Add(td);
    laoma.Remove(td);
    laoma.Notify();
}

------输出结果--------
下雨了,老大去把衣服收了
下雨了,老二去把窗户关了