サーチ…


備考

ここに画像の説明を入力

その意図は何ですか?

  • 懸念の分離の原則を採用する。
  • サブジェクトとオブザーバの間に分離を作成します。
  • 複数のオブザーバーが反応して1つのサブジェクトを変更できるようにする。

構造は何ですか?

  • サブジェクトは登録、登録解除、通知の方法を提供します。
  • オブザーバーは更新方法を提供します。

オブザーバー/ Java

オブザーバーパターンは、クラスのユーザーが、このクラスがデータなどを処理するときに発生するイベントをサブスクライブし、これらのイベントが発生したときに通知を受けることを可能にします。次の例では、処理クラスとオブザーバークラスを作成します。このクラスは、5文字より長い単語を見つけると、フレーズの処理中に通知されます。

LongWordsObserverインターフェースはオブザーバーを定義します。オブザーバーをイベントに登録するには、このインターフェースを実装します。

// an observe that can be registered and receive notifications
public interface LongWordsObserver {
    void notify(WordEvent event);
}

WordEventクラスは、特定のイベントが発生するとオブザーバークラスに送信されるイベントです(この場合、長い単語が見つかりました)

// An event class which contains the long word that was found
public class WordEvent {

    private String word;

    public WordEvent(String word) {
        this.word = word;
    }

    public String getWord() {
        return word;
    }
}

PhraseProcessorクラスは、指定されたフレーズを処理するクラスです。 addObserverメソッドを使用してオブザーバを登録することができます。長い単語が見つかると、これらのオブザーバはWordEventクラスのインスタンスを使用して呼び出されます。

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

public class PhraseProcessor {

    // the list of observers
    private List<LongWordsObserver> observers = new ArrayList<>();

    // register an observer
    public void addObserver(LongWordsObserver observer) {
        observers.add(observer);
    }

    // inform all the observers that a long word was found
    private void informObservers(String word) {
        observers.forEach(o -> o.notify(new WordEvent(word)));
    }

    // the main method - process a phrase and look for long words. If such are found,
    // notify all the observers
    public void process(String phrase) {
        for (String word : phrase.split(" ")) {
            if (word.length() > 5) {
                informObservers(word);
            }
        }
    }
}

LongWordsExampleクラスは、オブザーバーの登録、 processメソッドの呼び出し、長い単語が見つかったときのアラートの受信方法を示します。

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

public class LongWordsExample {

    public static void main(String[] args) {

        // create a list of words to be filled when long words were found
        List<String> longWords = new ArrayList<>();

        // create the PhraseProcessor class
        PhraseProcessor processor = new PhraseProcessor();

        // register an observer and specify what it should do when it receives events,
        // namely to append long words in the longwords list
        processor.addObserver(event -> longWords.add(event.getWord()));

        // call the process method 
        processor.process("Lorem ipsum dolor sit amet, consectetuer adipiscing elit");

        // show the list of long words after the processing is done
        System.out.println(String.join(", ", longWords));
        // consectetuer, adipiscing
    }
}

IObservableとIObserverを使用するオブザーバ(C#)

IObserver<T>およびIObservable<T>インターフェイスは、.NETでオブザーバパターンを実装するために使用できます。

  • IObservable<T>インターフェイスは、通知を送信するクラスを表します。
  • IObserver<T>インターフェイスは、それらを受け取るクラスを表します
public class Stock {
  private string Symbol { get; set; }
  private decimal Price { get; set; }
}

public class Investor : IObserver<Stock> {
  public IDisposable unsubscriber;
  public virtual void Subscribe(IObservable<Stock> provider) {
    if(provider != null) {
      unsubscriber = provider.Subscribe(this);
    }
  }
  public virtual void OnCompleted() {
    unsubscriber.Dispose();
  }
  public virtual void OnError(Exception e) {
  }
  public virtual void OnNext(Stock stock) {
  }
}

public class StockTrader : IObservable<Stock> {
  public StockTrader() {
    observers = new List<IObserver<Stock>>();
  }
  private IList<IObserver<Stock>> observers;
  public IDisposable Subscribe(IObserver<Stock> observer) {
    if(!observers.Contains(observer)) {
      observers.Add(observer);
    }
    return new Unsubscriber(observers, observer);
  }
  public class Unsubscriber : IDisposable {
    private IList<IObserver<Stock>> _observers;
    private IObserver<Stock> _observer;

    public Unsubscriber(IList<IObserver<Stock>> observers, IObserver<Stock> observer) {
      _observers = observers;
      _observer = observer;
    }

    public void Dispose() {
      Dispose(true);
    }
    private bool _disposed = false;
    protected virtual void Dispose(bool disposing) {
      if(_disposed) {
        return;
      }
      if(disposing) {
        if(_observer != null && _observers.Contains(_observer)) {
          _observers.Remove(_observer);
        }
      }
      _disposed = true;
    }
  }
  public void Trade(Stock stock) {
    foreach(var observer in observers) {
      if(stock== null) {
        observer.OnError(new ArgumentNullException());
      }
      observer.OnNext(stock);
    }
  }
  public void End() {
    foreach(var observer in observers.ToArray()) {
      observer.OnCompleted();
    }
    observers.Clear();
  }
}

使用法

...
var provider = new StockTrader();
var i1 = new Investor();
i1.Subscribe(provider);
var i2 = new Investor();
i2.Subscribe(provider);

provider.Trade(new Stock());
provider.Trade(new Stock());
provider.Trade(null);
provider.End();
...

REF: .NETにおけるデザインパターンと実践:オブザーバーパターン



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow