Design patterns
観察者
サーチ…
備考
その意図は何ですか?
- 懸念の分離の原則を採用する。
- サブジェクトとオブザーバの間に分離を作成します。
- 複数のオブザーバーが反応して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