一位面试官问我:

什么是观察者和可观察对象,什么时候应该使用它们?

我不知道这些术语,所以当我回到家,开始在谷歌上搜索关于观察者和Observable的信息时,我从不同的资源中找到了一些观点:

1) Observable是一个类,Observer是一个接口。 2) Observable类维护了一个观察者列表。 3)当一个Observable对象被更新时,它会调用它的每个观察者的update()方法来通知它被更改了。

我找到了这个例子:

import java.util.Observable;
import java.util.Observer;

class MessageBoard extends Observable
{
    public void changeMessage(String message) 
    {
        setChanged();
        notifyObservers(message);
    }
}

class Student implements Observer 
{
    @Override
    public void update(Observable o, Object arg) 
    {
        System.out.println("Message board changed: " + arg);
    }
}

public class MessageBoardTest 
{
    public static void main(String[] args) 
    {
        MessageBoard board = new MessageBoard();
        Student bob = new Student();
        Student joe = new Student();
        board.addObserver(bob);
        board.addObserver(joe);
        board.changeMessage("More Homework!");
    }
}

但我不明白为什么我们需要观察者和可观察对象?setChanged()和notifyObservers(message)方法是干什么用的?


当前回答

观察者也就是回调被注册在Observable中。

它被用来告知例如在某个时间点发生的事件。它被广泛应用于Swing、Ajax、GWT中,用于对UI事件(按钮点击、文本字段更改等)进行调度操作。

在Swing中你可以找到addXXXListener(Listener l)这样的方法,在GWT中你有(Async)回调。

由于观察者列表是动态的,观察者可以在运行时注册和注销。当使用接口时,这也是一种将可观察对象与观察者分离的好方法。

其他回答

你有一个学生和留言板的具体例子。Student通过将自己添加到观察者列表来注册,观察者希望在消息发布到MessageBoard时得到通知。当消息被添加到MessageBoard时,它将遍历其观察者列表,并通知他们发生了事件。

认为Twitter。当你说你想关注某人时,Twitter会把你添加到他们的关注者列表中。当他们发送一条新的推文时,你会在输入中看到它。在这种情况下,你的Twitter账户是观察者,你关注的人是可观察对象。

这个类比可能并不完美,因为Twitter更可能是一个Mediator。但它说明了这一点。

观察者模式用于对象之间存在一对多关系时,例如如果一个对象被修改,它的依赖对象将被自动通知。

如果面试官要求在不使用观察者类和接口的情况下实现观察者设计模式,您可以使用下面的简单示例!

MyObserver作为观察者接口

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable作为Observable类

class MyObservable
{
    ArrayList<MyObserver> myObserverList = new ArrayList<MyObserver>();

    boolean changeFlag = false;

    public void notifyObservers(Object o)
    {
        if (hasChanged())
        {
            for(MyObserver mo : myObserverList) {
                mo.update(this, o);
            }
            clearChanged();
        }
    }


    public void addObserver(MyObserver o) {
        myObserverList.add(o);        
    }

    public void setChanged() {
        changeFlag = true;
    }

    public boolean hasChanged() {
        return changeFlag;
    }

    protected void clearChanged() {
        changeFlag = false;
    }

    // ...
}

你的MyObserver和MyObservable的例子!

class MessageBoard extends MyObservable {
  private String message;

  public String getMessage() {
    return message;
  }

  public void changeMessage(String message) {
    this.message = message;
    setChanged();
    notifyObservers(message);
  }

  public static void main(String[] args) {
    MessageBoard board = new MessageBoard();
    Student bob = new Student();
    Student joe = new Student();
    board.addObserver(bob);
    board.addObserver(joe);
    board.changeMessage("More Homework!");
  }
}

class Student implements MyObserver {

  @Override
  public void update(MyObservable o, Object arg) {
    System.out.println("Message board changed: " + arg);
  }

}

我在这里写了一个关于观察者模式的简短描述:http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

文章摘录如下:

观察者模式:它本质上是在对象之间建立一对多的关系,并且在相互依赖的对象之间采用松散耦合设计。

教科书定义:观察者模式定义了对象之间的一对多依赖关系,这样当一个对象改变状态时,它的所有依赖项都会被自动通知和更新。

例如,考虑一个提要通知服务。订阅模型是理解观察者模式的最佳方法。

它们是Observer设计模式的一部分。 通常,一个或多个观察者会被通知一个可观察对象的变化。它是“某事”发生的通知,作为程序员的你可以定义“某事”的含义。

当使用此模式时,您可以将这两个实体彼此分离—观察者变得可插入。