《设计模式》-- 观察者模式

观察者模式

参考:《JAVA与模式》之观察者模式

认识

观察者模式是对象的行为模式,定义了一种一对多的依赖关系,多个观察者对象同时监听一个主题对象,当主题对象状态发生改变时,会通知所有观察者对象更新。是一种发布-订阅模式。

思考

在观察者模式中,观察者和目标是单向依赖的,只有观察者依赖目标,观察者只能被动的去等到目标的通知,等待目标传值给它。

  • 推模型是假定目标知道观察者需要的数据;而拉模型是目标不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
  • 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是目标对象本身,观察者可以获取目标对象上的任何非私有属性。

实质:触发联动

使用场景

  1. 当一个对象的改变需要通知其他对象时选用观察者模式
  2. 当一个抽象模型有两个方面,一个方面的操作依赖另一个方面的状态变化时选用观察者模式

优缺点

  • 优点

    1. 实现了观察者和目标之间的解耦合
    2. 支持广播通知
  • 缺点

UML图

定义一个目标抽象类,在抽象类中维护一个观察者的list,通过准备阶段创建观察者add到list中,提供添加和删除观察者的方法,提供通知观察者的方法。

定义一个目标具体实现类,在该实现类中如果发生变化调用notifyObserves通知所有观察者

定义一个观察者接口和一系列观察者实现类对象,提供方法供目标回调

image

●  目标(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,提供目标更新时通知观察者的方法。

  ●  目标实现(ConcreteSubject)角色:具体目标实现,用来维护目标状态,当目标状态发生改变时通知已注册的所有观察者。

  ●  抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,定义目标对象通知观察者时的回调方法。

  ●  具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者接收通知进行后续处理。

  • 准备阶段

image

  • 运行阶段

image

代码实现

推模型

目标回调观察者时传入具体的值

//目标抽象类
public abstract class Subject {

    // 注册的观察者列表
    private List<Observer> observerList = new ArrayList<Observer>();

    // 注册观察者
    public void attach(Observer observer) {
        observerList.add(observer);
    }

    // 移除观察者
    public void detach(Observer observer) {
        observerList.remove(observer);
    }

    // 定义通知方法
    protected void nodifyObservers(String newState) {
        for(Observer observer:observerList){
            observer.update(newState);
        }
    }
}
//目标具体实现类
public class ConcreteSubject extends Subject {

    private String state;

    public String getState() {
        return state;
    }

    //目标更新时通知所有观察者
    public void change(String newState) {
        state = newState;
        System.out.println("主题状态为:" + state);
        // 状态发生改变,通知各个观察者
        this.nodifyObservers(state);
    }

}
//观察者接口
public interface Observer {

    //提供方法供目标回调通知并传入值
    public void update(String state);
}
//观察者具体实现类
public class ConcreteObserver implements Observer {

    //观察者的状态
    private String observerState;

    //通过目标回调获取目标传递给回来的值
    public void update(String state) {
        /**
         * 更新观察者的状态,使其与目标的状态保持一致
         */
        observerState = state;
        System.out.println("状态为:"+observerState);
    }
}
//客户端调用
public class Client {

    public static void main(String[] args) {
        //创建目标
        ConcreteSubject subject = new ConcreteSubject();
        //创建观察者
        Observer observer1 = new ConcreteObserver();
        Observer observer2 = new ConcreteObserver();
        //注册观察者
        subject.attach(observer1);
        subject.attach(observer2);
        //更新目标并通知所有观察者
        subject.change("new");
        subject.detach(observer2);
        subject.change("again");
    }
}

拉模型

目标回调观察者时将目标对象传递给观察者

//目标抽象类
public abstract class Subject {

    // 注册的观察者列表
    private List<Observer> observerList = new ArrayList<Observer>();

    // 注册观察者
    public void attach(Observer observer) {
        observerList.add(observer);
    }

    // 移除观察者
    public void detach(Observer observer) {
        observerList.remove(observer);
    }

    // 定义通知方法,直接将目标对象回调传递给观察者
    protected void nodifyObservers() {
        for(Observer observer:observerList){
            observer.update(this);
        }
    }
}
//目标具体实现类
public class ConcreteSubject extends Subject {

    private String state;

    public String getState() {
        return state;
    }

    //目标更新时通知所有观察者
    public void change(String newState) {
        state = newState;
        System.out.println("主题状态为:" + state);
        //将目标对象通过回调传递给每个观察者
        this.nodifyObservers();
    }
}
//观察者接口
public interface Observer {

    //提供方法供目标回调通知并传入值
    public void update(Subject subject);
}
//观察者具体实现类
public class ConcreteObserver implements Observer {

    //观察者的状态
    private String observerState;

    //通过目标回调获取目标对象
    @Override
    public void update(Subject subject) {
        //通过目标对象的引用获取目标对象中的值
        observerState = ((ConcreteSubject)subject).getState();
        System.out.println("状态为:"+observerState);
    }
}
//客户端调用
public class Client {

    public static void main(String[] args) {
        //创建目标
        ConcreteSubject subject = new ConcreteSubject();
        //创建观察者
        Observer observer1 = new ConcreteObserver();
        Observer observer2 = new ConcreteObserver();
        //注册观察者
        subject.attach(observer1);
        subject.attach(observer2);
        //更新目标并通知所有观察者
        subject.change("new");
        subject.detach(observer2);
        subject.change("again");
    }
}

jdk提供的接口

//目标对象继承Observable接口
public class Watched extends Observable接口{

    private String data = "";

    public String getData() {
        return data;
    }

    public void setData(String data) {

        if(!this.data.equals(data)){
            this.data = data;
            setChanged();
        }
        notifyObservers();
    }
}
//观察者实现Observer接口
public class Watcher implements Observer{

    public Watcher(Observable o){
        o.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {  
        System.out.println("状态发生改变:" + ((Watched)o).getData());
    }
}
public class Client {
    public static void main(String[] args) { 
        //创建被观察者对象
        Watched watched = new Watched();
        //创建观察者对象,并将被观察者对象登记
        Observer watcher = new Watcher(watched);
        //给被观察者状态赋值
        watched.setData("start");
        watched.setData("run");
        watched.setData("stop");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值