我们什么时候应该使用观察员和可观?(When should we use Observer and

2019-06-21 16:32发布

面试官问我:

什么是ObserverObservable我们何时应该使用它们?

我不知道这些术语的,所以,当我回到家,开始对谷歌搜索ObserverObservable ,我发现来自不同资源的一些要点:

1) Observable是一个类和Observer是一个接口。

2) Observable类维护列表Observer秒。

3)当一个Observable对象被更新时,它调用update()的每一个其的方法Observer s到通知,它被改变。

我发现这个例子:

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!");
    }
}

但我不明白为什么我们需要ObserverObservable ? 什么是setChanged()notifyObservers(message)的方法是什么?

Answer 1:

你有一个学生和留言板的一个具体的例子。 当一个新的消息发布到留言板被通知通过添加自己想要观察员名单的学生注册。 当消息被添加到留言板,它遍历其观察名单,并通知他们所发生的事件。

认为Twitter的。 当你说你要跟随别人,微博将您添加到他们的跟踪器列表。 当他们收到新的鸣叫,你会看到它在你的输入。 在这种情况下,你的Twitter帐户是观察者和你下面的人是可观察的。

这个比喻可能不是完美的,因为Twitter是更可能是一个调解员。 但它说明了这一点。



Answer 2:

简单来说(因为其他答案反正指你所有正式的设计模式,所以看他们的其他细节):

如果你想拥有这是由其他类在你的程序的生态系统监测的类,你说你想要的类可观察到。 即可能有一些变化,它的状态,你会希望广播节目的其余部分。

现在,要做到这一点,我们必须调用某种方法。 我们不希望可观察的类进行紧密耦合与感兴趣观察它的类。 它不关心他是谁,只要它符合一定的标准。 (想象一下,这是一个广播电台,它并不关心,只要他们调整自己的频率FM收音机谁在听)。 为了实现这一目标,我们使用一个接口,简称为观察员。

因此,可观察类将有观察员的名单(即实现你可能有观察者接口方法的实例)。 每当它要播出的东西,它只是呼吁所有的观察者,一个接一个的方法。

最后要关闭的难题是如何将可观察类知道是谁感兴趣? 因此,可观察类必须提供一些机制,让观察员登记他们的兴趣。 如一种方法addObserver(Observer o)内部增加了观察员的观察员名单,这样,当一些重要的事情发生了,它遍历列表并调用每个实例的列表中的Observer接口的相应的通知方法。

这可能是在面试中他们没有问你明确地对java.util.Observerjava.util.Observable ,但对通用的概念。 这个概念是一种设计模式,它的Java恰好提供了直接支持开箱即用,帮助您快速实现它,当你需要它。 因此,我建议你理解的概念,而不是实际的方法/类(你可以看一下,当你需要他们)。

UPDATE

在回答您的意见,实际java.util.Observable类提供下列设施:

  1. 维护列表java.util.Observer实例。 您想得到新的实例可以通过添加addObserver(Observer o)并通过去除deleteObserver(Observer o)

  2. 保持内部状态,指定对象是否已自上次通知观察者改变。 因为它,你说,分离部分,这是有用Observable发生了变化,从那里你通知修改的部分。 (例如它的有用的,如果你有多个变化发生的事情,你只需要在过程的末尾,而不是在每个小步通知)。 这是通过做setChanged() 所以,你只需要调用它,当你改变一些东西到Observable和你想要的其余Observers ,最终了解它。

  3. 通知所有的观察者,具体的Observable状态发生了改变。 这是通过做notifyObservers() 这用来检查对象实际上有没有改变(即调用setChanged()制成)与通知继续之前。 有2个版本,一个不带参数和一个与Object的说法,如果你想通过与一些通知额外的信息。 内部发生的事情是,它只是通过列表迭代Observer的实例,并调用update(Observable o, Object arg)为他们每个人的方法。 这告诉Observer这是改变(你可以观察到一个以上的)可观察的对象,而额外的Object arg潜在携带一些额外的信息(通过传递notifyObservers()



Answer 3:

定义

当存在一个到对象,例如,如果一个对象被修改之间的许多关系用于观察者模式,其依赖对象将被自动通知和相应的变化完成对所有相关对象。

例子

  1. 比方说,你的永久地址被更改,那么你需要通知护照权威和泛卡权限。 所以在这里护照的权力和泛卡权限是观察员和你是一个主题。

  2. 在Facebook上也,如果你赞同别人那么只要有新的更新,然后发生,你将会收到通知。

当使用它:

  1. 当一个对象改变其状态,那么所有的人还有其他扶养对象必须自动地改变自己的状态,以保持一致性

  2. 当拍摄对象不知道它的观察员人数。

  3. 当一个对象应该能够在不知道对象是谁通知的其他对象。

步骤1

创建主题类。

Subject.java

  import java.util.ArrayList;
  import java.util.List;

  public class Subject {

  private List<Observer> observers 
        = new ArrayList<Observer>();
  private int state;

  public int getState() {
    return state;
  }

 public void setState(int state) {
   this.state = state;
   notifyAllObservers();
 }

   public void attach(Observer observer){
     observers.add(observer);       
   }

  public void notifyAllObservers(){
    for (Observer observer : observers) {
     observer.update();
  }
}   

}

第2步

创建观察类。

Observer.java

public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

第3步

创建具体的观察者类

BinaryObserver.java

public class BinaryObserver extends Observer{

  public BinaryObserver(Subject subject){
     this.subject = subject;
     this.subject.attach(this);
  }

  @Override
  public void update() {
     System.out.println( "Binary String: " 
     + Integer.toBinaryString( subject.getState() ) ); 
  }

}

OctalObserver.java

public class OctalObserver extends Observer{

   public OctalObserver(Subject subject){
     this.subject = subject;
    this.subject.attach(this);
 }

  @Override
  public void update() {
    System.out.println( "Octal String: " 
    + Integer.toOctalString( subject.getState() ) ); 
  }

}

HexaObserver.java

public class HexaObserver extends Observer{

  public HexaObserver(Subject subject){
    this.subject = subject;
    this.subject.attach(this);
 }

  @Override
  public void update() {
     System.out.println( "Hex String: " 
    + Integer.toHexString( subject.getState() ).toUpperCase() ); 
}

}

第4步

使用主题和具体的观测对象。

ObserverPatternDemo.java

 public class ObserverPatternDemo {
    public static void main(String[] args) {
       Subject subject = new Subject();

       new HexaObserver(subject);
       new OctalObserver(subject);
       new BinaryObserver(subject);

       System.out.println("First state change: 15");    
       subject.setState(15);
       System.out.println("Second state change: 10");   
       subject.setState(10);
 }

}

第5步

验证输出。

第一状态变化:15

十六进制字符串:F

八进制字符串:17

二进制字符串:1111

第二状态变化:10

十六进制的字符串:A

八进制字符串:12

二进制字符串:1010



Answer 4:

他们是部分Observer设计模式 。 通常是一个或多个obervers得到了解在一个可观察的变化。 这是一个notifcation那“东西”发生了,在那里你作为一个程序员可以定义什么“东西”的意思。

当使用这种模式,您解耦每个另一两个实体 - 观察者变成可插拔。



Answer 5:

观察又名回调在可观测的注册。

它用于通知例如关于发生在某个时间点的事件。 它广泛用于在Swing,AJAX,GWT派遣上如UI事件操作(点击按钮,文本框的改变等)。

在Swing你找到像addXXXListener(侦听器l),在GWT你有(异步)回调方法。

作为观察员的名单是动态的,观察员可以注册并运行时注销。 这也是不脱钩观察者观察到,作为接口使用的好办法。



Answer 6:

如果面试官问到实现观察者设计模式 ,而无需使用观察类和接口,你可以使用下面简单的例子!

MyObserver作为观察员接口

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable作为可观察类

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);
  }

}


Answer 7:

“我想弄清楚,到底为什么我们需要观察和可观察的”

由于以前的答案已经指出,他们提供订阅观察者接收可观测的自动通知的方式。

一个例子应用中,这可能是有用的数据绑定 ,让我们说你有一些用户界面,编辑一些数据,并希望用户界面反应,当数据被更新,可以使你的数据观察到,并订阅你的UI组件数据

Knockout.js是JavaScript框架,有一个伟大的入门教程,在行动中看到更多的观测我真的建议通过教程去一个MVVM。 http://learn.knockoutjs.com/

我还发现这篇文章在Visual Studio 2008起始页( 观察者模式是模型-视图-控制器(MVC)发展的基础 ) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx



Answer 8:

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

从后一个片段:

观察者模式:它实质上建立对象之间的一对多的关系,并且具有相互依存的对象之间的松耦合的设计。

课本定义:观察者模式定义了对象,以便当一个对象改变状态,其所有家属的通知,并自动更新之间的一个一对多的依赖。

考虑例如饲料通知服务。 订购模式是最好的理解观察者模式。



Answer 9:

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



Answer 10:

由于Java9,这两个接口已被弃用,这意味着你不应该再使用它们。 见观测是用Java 9不赞成我们应该使用的,而不是什么呢?

但是,你仍然可能会得到关于他们的面试问题...



文章来源: When should we use Observer and Observable?