zoukankan      html  css  js  c++  java
  • Java API 设计模式之观察者(Observer)

         这是一个行为型设计模式,是MVC体系结构的基础。    

         Java API 包含了运用观察器设计模式的类。类java.util.Observable代表一个主题。类Observable提供了方法addObserver,该方法带有一个java.util.Observer参数。接口Observer允许Observable对象在其发生状态改变时向Observer发出通知。这个Observer可以是任何一个实现接口Observer的类的实例。因为Observable对象调用在接口Observer中定义的方法,这些对象仍然保持松散耦合关系。如果开发人员改变了一个具体Observer响应Observable对象状态发生改变时的方式,他不必改变这个Observable对象。Observable对象仅仅通过接口Observer与它的Observer进行交互,这保证了松散耦合。

         Swing GUI 组件运用了观察者设计模式。GUI组件与它们的监听器进行协作,以响应用户交互。比如,一个ActionListener通过注册处理一个JButton(主题)的事件而观察JButton的状态变化。当按钮被用户按下后,这个JButton通知它的ActionListener对象(观察器),它的状态已经发生改变。

         假定我们希望设计一个用来查看银行账户信息的程序。此系统包括类BankStatementData(它存储银行结单的数据)以及用来显示这些数据的类TextDisplay,BarGrahpDisplay和PieChartDisplay。分别以文本,柱状图,饼图来显示数据。我们希望设计的系统是这样的,BankStatementData对象可以通知那些显示数组的对象,并且希望主题类与观察者类之间是松散耦合的。

         观察者设计模式提倡一个主题对象和观察者对象之间的松散耦合----当主题对象发生改变的时候,它通知观察器。当得到主题对象的通知时,观察器对象发生改变以响应主题对象的状态变化。在上面的例子中,BankStatementData对象是主题对象,显示数据的三个对象是观察器。一个主题对象可以通知若干个观察器。因此主题对象与观察器之间具有一对多的关系。

    意图:

         在对象之间定义一个一对多的依赖。当一个对象发生变化的时候,它会通知所有依赖它的对象,并且这些依赖它的对象自动更新。

    动机:

         这个模式中两个关键的对象是主题和观察者。一个主题可能有很多依赖它的观察者。当主题的状态发生变化时,必须通知所有的依赖它的观察者。所为回应,每个观察者都会通知主题以同步自己与主题的状态。

    实现:

         一个定义观察者接口的抽象类:

    class Subject;

    class Observer {

    public:

         virtual ~Observer();

         virtual void Update(Subject * theChangedSubject) = 0;

    protected:

         Observer();

    };

         一个定义主题接口的抽象类:

    class Subject {

    public:

         virtual ~Subject();

         virtual void Attach(Observer *);

         virtual void Detach(Observer *);

         virtual void Notify();

    protected:

         Subject();

    private:

         List<Observer *> *_observers;

    };

    void Subject::Attach(Observer *o) {

         _observers->Append(o);

    }

    void Subject::Detach(Observer *o){

         _observers->Remove(o);

    }

    void Subject::Notify(){   //当this发生变化时,它会通知所有依赖它的观察者

         ListIterator<Observer*> i(_observers);

         for(i.First(); !i.IsDone(); i.Next()){

              i.CurrentItem()->Update(this);

         }

    };

    一个具体的Subject类:

    class ClockTimer : public Subject {

    public:

         ClockTimer();

        

         virtual int GetHour();

         virtual int GetMinute();

         virtual int GetSecond();

         void Tick();   // updates the ClockTimer's internal state and calls Notify to inform observers of the change.

    };

    void ClockTimer::Tick() {

         //update internal time-keeping state

         //...

         Notify();

    }

    class DigitalClock : public Widget, public Observer {

    public:

         DigitalClock(ClockTimer*);

         virtual ~DigitalClock();

         virutal void Update(Subject*); //overrides Observer operation

         virtual void Draw(); // overrides Widgets Operation, defines how to draw the digital clock

    private:

         ClockTimer *_subject;   //具体Observer类持有一个具体Subject类的对象

    };

    DigitalClock::DigitalClock(ClockTimer *s) {

         _subject = s;

         _subject->Attach(this);

    }

    DigitalClock::DigitalClock(ClockTimer *s) {

         _subject->Detach(this);

    }

    void DigitalClock::Update(Subject * theChangedSubject) {

         if(theChangedSubject == _subject){

              Draw();

         }

    }

    void DigitalClock::Draw() {

         //draw the digital clock

    }

    另一个Observer具体类的定义

    class AnalogClock : public Widget, public Observer {

    public:

         AnalogClock(ClockTimer *) ;  //用一个具体主题类的对象来构造具体观察者类

         virtual void Update(Subject*);

         virtual void Draw();

    private:

         ClockTimer * _subject;

    };

    主函数中的代码:

    创建两个不同的Observer具体类对象和一个Subject具体类对象。用来显示一致的时间。

    ClockTimer * timer = new ClockTimer();

    AnalogClock * analogClock = new AnalogClock(timer);

    DigitalClock* digitalClock = new DigitalClock(timer);

    这样, 当timer变化时,它的值会在analogClock和digitalClock上显示出来。

  • 相关阅读:
    打造基于CentOS7的xfce最简工作环境
    Linux下C程序的编辑,编译和运行以及调试
    修正 XE6 TListView 上方 SearchBok 右边的清除钮显示
    TabControl 显示彩色的图示 (XE6 Firemonkey)
    TSwitch 中文简繁显示支持(XE6 Android)
    改变 TMemo 的背景颜色 (Firemonkey)
    修正 XE5 Android 键盘三个问题
    Delphi 收藏
    展示 Popup 的使用方法
    ListView 下拉更新 (支持 Android)
  • 原文地址:https://www.cnblogs.com/afreethinker/p/3274563.html
Copyright © 2011-2022 走看看