オブザーバーとオブザーバブルはいつ使用すべきですか?


200

面接官は私に尋ねました:

ObserverObservable、いつ使うべきですか?

私は、これらの用語を認識していなかったので、私は戻って家を得たときは約グーグルで始めたObserverObservable私は別の資源からいくつかのポイントを見つけ、:

1)ObservableはクラスでObserverあり、インターフェースです。

2)ObservableクラスはObserversのリストを保持します。

3)Observableオブジェクトが更新されると、オブジェクトupdate()の各のメソッドが呼び出され、Observer変更されたことが通知されます。

私はこの例を見つけました:

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)するための方法が?


リンクが機能していません。@Androider更新されたリンクを提供できますか?
prateek

Java 6以降を使用している場合は、このdzone.com/articles/java-ee6-events-lightweightを
Uddin

1
この本を読み、デザインパターンをよく理解することを強くお勧めします。ばかげていますが、優れた学習ツールです。
countofmontecristo 2016

1
皆さんご注意ください。:オブザーバー/観測は、Java 9代替で廃止され stackoverflow.com/questions/46380073/...
eren130

回答:


265

学生とメッセージボードの具体的な例があります。Studentは、新しいメッセージがMessageBoardに投稿されたときに通知を受けるオブザーバーのリストに自分自身を追加することで登録します。メッセージがメッセージボードに追加されると、オブザーバーのリストを反復処理して、イベントが発生したことを通知します。

Twitterを考えてください。誰かをフォローしたい場合、Twitterはあなたをフォロワーリストに追加します。彼らが新しいつぶやきを送ったとき、あなたはあなたの入力にそれを見る。その場合、あなたのTwitterアカウントはオブザーバーであり、あなたがフォローしている人はオブザーバブルです。

Twitterはメディエーターである可能性が高いため、類推は完全ではない可能性があります。しかし、それは要点を示しています。


57

非常に単純な言葉で(他の回答はとにかく公式の設計パターンすべてを参照しているため、詳細についてはそれらを見てください):

プログラムのエコシステム内の他のクラスによって監視されるクラスが必要な場合は、クラスを監視可能にする必要があると言います。つまり、プログラムの残りの部分にブロードキャストしたい状態にいくつかの変更がある可能性があります。

これを行うには、なんらかのメソッドを呼び出す必要があります。Observableクラスを、それを監視することに関心のあるクラスと密に結合したくない。特定の基準を満たしている限り、それは誰でもかまいません。(それがラジオ局だと想像してください。FMラジオが周波数でチューニングされている限り、誰が聞いているかは関係ありません)。そのためには、オブザーバーと呼ばれるインターフェイスを使用します。

したがって、Observableクラスには、オブザーバー(つまり、ユーザーが持つ可能性があるObserverインターフェースメソッドを実装するインスタンス)のリストが含まれます。それが何かをブロードキャストしたいときはいつでも、それはすべてのオブザーバーで次々にメソッドを呼び出すだけです。

パズルを閉じる最後のことは、Observableクラスが誰が興味を持っているかをどのようにして知るかです。したがって、Observableクラスは、オブザーバーが関心を登録できるようにするための何らかのメカニズムを提供する必要があります。addObserver(Observer o)Observerをオブザーバーのリストに内部的に追加するなどのメソッドは、何か重要なことが発生した場合にリストをループし、リスト内の各インスタンスのObserverインターフェースのそれぞれの通知メソッドを呼び出します。

インタビューで、彼らがあなたに、java.util.Observerそしてjava.util.Observable一般的な概念について明示的に尋ねなかったのかもしれません。コンセプトは設計パターンであり、Javaはすぐにすぐに使用できるようにサポートを提供して、必要なときにすばやく実装できるようにします。したがって、実際のメソッド/クラス(必要なときに参照できる)ではなく、概念を理解することをお勧めします。

更新

あなたのコメントに応えて、実際のjava.util.Observableクラスは以下の機能を提供します:

  1. java.util.Observerインスタンスのリストを維持します。通知を受けることに関心のある新しいインスタンスはaddObserver(Observer o)、を介して追加および削除できdeleteObserver(Observer o)ます。

  2. 内部状態を維持し、オブザーバーへの最後の通知以降にオブジェクトが変更されたかどうかを指定します。これは、Observableが変更されたと言う部分と、変更を通知する部分を分離するので便利です。(たとえば、複数の変更が発生していて、小さなステップごとではなくプロセスの最後に通知したい場合に便利です)。これはを介して行われますsetChanged()。したがって、何かをに変更したときにそれを呼び出しObservable、残りのObserversが最終的にそれについて知ってほしいと思っています。

  3. 特定のObservable状態が変化したことをすべてのオブザーバーに通知します。これはを介して行われますnotifyObservers()。これはsetChanged()、通知を続行する前に、オブジェクトが実際に変更されたかどうか(つまり、呼び出しが行われたかどうか)をチェックします。2つのバージョンがあり、1つは引数なし、もう1つは引数Object付きで、通知で追加情報を渡したい場合に備えています。内部的には、Observerインスタンスのリストを繰り返し処理し、インスタンスupdate(Observable o, Object arg)ごとにメソッドを呼び出すだけです。これは、Observer変更されたObservableオブジェクト(複数を監視している可能性があります)と、Object arg潜在的にいくつかの追加情報を運ぶための追加(を介して渡される)を示しnotifyObservers()ます。


37

定義

オブザーバーパターンは、1つのオブジェクトが変更された場合、その依存オブジェクトが自動的に通知され、対応する変更がすべての依存オブジェクトに対して行われる場合など、オブジェクト間に1対多の関係がある場合に使用されます。

  1. 仮の住所が変更され、パスポート機関とパンカード機関に通知する必要があるとします。したがって、ここではパスポート機関とパンカード機関がオブザーバーであり、あなたが主体です。

  2. Facebookでも、誰かを購読すると、新しい更新が発生するたびに通知されます。

いつ使用するか:

  1. 1つのオブジェクトがその状態を変更すると、他のすべての依存オブジェクトは、一貫性を維持するためにそれらの状態を自動的に変更する必要があります

  2. 対象者が持っているオブザーバーの数を知らない場合。

  3. オブジェクトが誰であるかを知らなくても、オブジェクトが他のオブジェクトに通知できる必要がある場合。

ステップ1

Subjectクラスを作成します。

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クラスを作成します。

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

Subjectおよび具象オブザーバーオブジェクトを使用します。

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

16進ストリング:F

8進ストリング:17

バイナリ文字列:1111

2番目の状態変化:10

16進文字列:A

8進ストリング:12

バイナリ文字列:1010


うまく説明された:)
roottraveller

3
「Defination」はタイプミスだと思います。私はそれがタイプミスであることを願っています。
JohnJohn

10

これらはObserver設計パターンの一部です。通常、1人以上のオブザーバーが1つのオブザーバブルの変更について通知を受けます。「何か」が発生したという通知であり、プログラマーは「何か」の意味を定義できます。

このパターンを使用する場合、両方のエンティティを互いに分離します-オブザーバーはプラグ可能になります。


私は感謝board.changeMessage("More Homework!");します、あなたの答えに説明を追加すると、changeMessage("More Homework!");呼び出されたときに何が起こるかを意味します。
ラビ

9

オブザーバー、つまりコールバックがObservableに登録されています。

たとえば、ある時点で発生したイベントについて通知するために使用されます。Swing、Ajax、GWTなどで、UIイベント(ボタンのクリック、テキストフィールドの変更など)に対する操作をディスパッチするために広く使用されています。

SwingにはaddXXXListener(Listener l)などのメソッドがあり、GWTには(非同期)コールバックがあります。

オブザーバーのリストは動的であるため、オブザーバーは実行時に登録および登録解除できます。また、インターフェースが使用されているため、オブザーバブルをオブザーバーから分離するための良い方法でもあります。


9

インタビュアーがオブザーバークラスとインターフェイスを使用せずにオブザーバーデザインパターンを実装するように依頼した場合、次の簡単な例を使用できます。

オブザーバーインターフェイスとしてのMyObserver

interface MyObserver {

    void update(MyObservable o, Object arg);
}

Observableクラスとしての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);
  }

}

5

「なぜオブザーバーとオブザーバブルが必要なのかを理解しようとした」

以前の回答がすでに述べたように、それらはオブザーバーの自動通知を受け取るためにオブザーバーをサブスクライブする手段を提供します。

これが役立つアプリケーションの例として、データバインディングがあります。たとえば、一部のデータを編集するUIがあり、データが更新されたときにUIを反応させ、データを監視可能にして、UIコンポーネントをサブスクライブすることができます。データ

Knockout.jsはMVVM javascriptフレームワークであり、優れた入門チュートリアルがあり、実際に観察可能なオブザーバブルをさらに表示するために、チュートリアルを実行することをお勧めします。http://learn.knockoutjs.com/

この記事はVisual Studio 2008のスタートページにもありました(オブザーバーパターンはモデルビューコントローラー(MVC)開発の基盤ですhttp://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx


3

ここにオブザーバーパターンの短い説明を書きました:http : //www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

投稿の抜粋:

オブザーバーパターン:基本的に、オブジェクト間の1対多の関係を確立し、相互に依存するオブジェクト間で疎結合の設計を行います。

TextBookの定義:オブザーバーパターンは、オブジェクト間の1対多の依存関係を定義するため、1つのオブジェクトの状態が変化すると、その依存関係のすべてが自動的に通知および更新されます。

たとえば、フィード通知サービスについて考えてみましょう。サブスクリプションモデルは、オブザーバーパターンを理解するのに最適です。


0

オブザーバーパターンは、オブジェクト間に1対多の関係がある場合に使用されます。たとえば、1つのオブジェクトが変更された場合、その依存オブジェクトは自動的に通知されます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.