设计模式学习笔记(3):观察者模式(2)

       上一篇的观察者模式的笔记中提到的例子,只是Subject把自身状态“推”给Observer的方式。
    //通知观察者信息发生改变了
    @Override
    public void notifyObservers() {
        for (int i = 0;i < observers.size();i++){
            Observer observer = (Observer) observers.get(i);
            observer.update(travelerNum,terminal,information);
        }
    }

    //更新旅行信息
    public void setTravelInformation(int travelerNum,String terminal,String information){
        this.travelerNum = travelerNum;
        this.information = information;
        this.terminal = terminal;
        notifyObservers();
    }

      从代码中可以看出,只要Subject发生改变,Observer就会被动接受全部信息,并且不得不接受。

      这种模式的优势在于:Observer不用调用多次,才收集全所有需要的消息。

      同时这种模式会造成一定的麻烦:

      1、Observer可能并不需要所有的消息;

      2、在Subject需要扩展时,需要更新每一个发送给Observer的消息  。

     这时我们可以在Subject中提供一些公开的getter方法,让Observer自己索取所需要的信息。

     在这里我们还是选取旅行者的例子。

     Subject/Observable接口:

public interface Observable {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}
    Observer接口:
public interface PrepareTravel {
    void doPrepare();
}

    用来展示的接口PrepareTravel():

public interface PrepareTravel {
    void doPrepare();
}

    Organizer去实现Obserable接口:

public class Organizer implements Observable {
    //标记Subject状态是否发生改变
    private boolean changed;
    //旅行者人数
    private int travelerNum;
    //目的地
    private String terminal;
    //相关信息
    private String information;
    //用于存放observers的数组
    private ArrayList observers;

    //构造器
    public Organizer(){
        //初始化observers,否则会报空指针
        observers = new ArrayList();
        //标记默认为false,未发生改变
        changed = false;
    }

    //注册observer
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    //删除observer
    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0){
            observers.remove(i);
        }
    }

    //通知observer
    @Override
    public void notifyObservers() {
        if (changed){
            for (int i = 0;i < observers.size();i++){
                Observer observer = (Observer) observers.get(i);
                observer.update(this);
            }
            changed = false;
        }
    }

    //改变发生
    public void setInformationChanged(int travelerNum,String terminal,String information){
        changed = true;
        this.travelerNum = travelerNum;
        this.terminal = terminal;
        this.information = information;
        notifyObservers();
    }

    //公共的getter方法供observer去“拉”所需要的信息
    public int getTravelerNum() {
        return travelerNum;
    }

    public String getTerminal() {
        return terminal;
    }

    public String getInformation() {
        return information;
    }
}

在这里我们引进了changed标记,使得更新观察者时,拥有更多的弹性。在这个场景中,我们并不想每加一个人都通知观察者Traveler,我们想变更达到10人才通知观察者Traveler。我们可以添加条件:

    //改变发生
    public void setInformationChanged(int travelerNum,String terminal,String information){
        if (travelerNum - this.travelerNum >= 10){
            changed = true;
            this.travelerNum = travelerNum;
            this.terminal = terminal;
            this.information = information;
            notifyObservers();
        }
    }

Traveler去实现Observer接口:

public class Traveler implements Observer,PrepareTravel {
    //Subject
    Observable observable;
    //旅客人数
    private int travelerNum;
    //目的地
    private String terminal;
    //相关信息
    private String information;

    //构造器
    public Traveler(Observable observable){
        this.observable = observable;
        //注册
        observable.registerObserver(this);
    }

    //更新自己所需要的信息
    @Override
    public void update(Observable o) {
        if (o instanceof Organizer){
            Organizer organizer = (Organizer) o;
            //可以“拉”自身所需要的信息
            this.travelerNum = organizer.getTravelerNum();
            this.terminal = organizer.getTerminal();
            this.information = organizer.getInformation();
            doPrepare();
        }
    }

    //展示
    @Override
    public void doPrepare() {
        System.out.println("我已知悉这次旅行有"+travelerNum+"人,前往"+terminal+",其他相关信息有"+information);
    }
}

模拟旅行:

public class TravelSimulator {
    public static void main(String[] args) {
        Organizer organizer = new Organizer();
        Traveler traveler = new Traveler(organizer);

        organizer.setInformationChanged(10,"九华山","安徽");
        organizer.setInformationChanged(11,"黄山","安徽");
        organizer.setInformationChanged(30,"峨眉山","四川");
    }
}

添加changed条件前结果:

添加changed条件后结果:

《HeadFirst》中,推的方式被认为更正确(请教了大佬):
有些实现中,会需要将改变前和改变后的值都放在通知里,这就没法用get了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值