设计模式学习笔记:观察者模式

Posted 滴滴哒滴哒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式学习笔记:观察者模式相关的知识,希望对你有一定的参考价值。

上一篇的观察者模式的笔记中提到的例子,只是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了。


以上是关于设计模式学习笔记:观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习笔记-观察者模式

观察者模式——学习笔记

Java学习笔记——设计模式之十.观察者模式

学习笔记ABAP OOD设计模式 - 观察者模式

设计模式之观察者模式学习笔记

设计模式之观察者模式学习笔记