みなさん、こんにちは。まだforループのプログラミングをしていますか?
他に誰がオブザーバーパターンを使用できないのですか?
この記事は「オブザーバーモード」の理論と実際の戦闘をもたらします〜
オブザーバーパターンとは何ですか?
Observer Patternは、オブジェクト間の1対多の依存関係を定義します。これにより、オブジェクトの状態が変化する限り、依存するすべての関連オブジェクトが通知され、自動的に更新されます。
オブザーバーモードでは、変更されるオブジェクトをオブザーバーと呼び、更新を通知されるオブジェクトをオブザーバーと呼びます。1つのオブザーバーターゲットは複数のオブザーバーに対応します。オブザーバーは通常、動的に追加できるリストコレクションです。必要に応じて削除します。簡単に拡張できます。
オブザーバーパターンを使用する利点は、観測ターゲットとオブザーバーの間に抽象的な緩い結合関係があり、2つの間の結合関係が減少することです。
パブリッシュ/サブスクライブモデル
オブザーバーモードは、多くの場所でパブリッシュ/サブスクライブモード(パブリッシュ/サブスクライブ)とも呼ばれます。実際、このように理解できますが、両者の間にはまだわずかな違いがあります。
オブザーバーモードのオブザーバーは、オブザーバーモードに直接バインドされており、オブザーバーターゲットはオブザーバーリストのセットを維持する必要があります。この2つは、インターフェイスに基づいて依存関係が組み合わされているため、オブザーバーモードは緩く結合されていますが、完全に分離されていません。
パブリッシュ/サブスクライブモデルでは、パブリッシャーとサブスクライバーの間に接続はありません。パブリッシャーはミドルパーティを介してトピック(トピック)をパブリッシュし、サブスクライバーはミドルパーティ(スケジューリングセンター)を介してトピック(トピック)をサブスクライブします。サブスクライブの変更はサブスクライバーに直接通知されませんが、仲介者を介して通知されるか、サブスクライバーが自分で仲介者からプルするため、パブリッシュ/サブスクライブモデルは完全に分離されます。
彼らの関係を理解するための写真:
オブザーバーパターンとサブスクリプション発行パターンの違い
写真からは違いがあり、どちらもオブザーバーモードと呼ばれ、問題はありません。
オブザーバーモードホイール
オブザーバーモードが広く使用されているため、JDKツールキットにはバージョン1.0からのオブザーバーモードテンプレートセットが付属しています。そのテンプレートに従ってオブザーバーモードを簡単に実装でき、ホイールを繰り返す必要はありません。
オブザーバーターゲットクラス:
java.util.Observable
最も重要な2つの変数は次のとおりです。
- 変更:ターゲットの状態が変更されたかどうかを確認します。デフォルトは次のとおりです。false;
- obs:オブザーバーリスト(オブザーバー)、スレッドセーフリストコレクション:Vector、デフォルトは空のコレクションです。
その中の重要な方法は、すべて観測対象と観測者の状態に関係しているので、一目でわかるのでここでは紹介しません。
オブザーバーインターフェース:
java.util.Observable
public interface Observer {
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
void update(Observable o, Object arg);
}
オブザーバーインターフェイスには更新メソッドが1つだけあります。これは、オブザーバーに自分自身を更新するように通知するために使用されます。
動作中のオブザーバーモード
OK、JDKにはこれら2つの機能が付属していることを知っているので、簡単なオブザーバーモードのアプリケーションシナリオを実装して、パブリックアカウントでの記事のプッシュをシミュレートしましょう。監視対象は私、ウェブマスター、オブザーバーはすべてです。パブリックではありません。Javaテクノロジースタックが記事をプッシュすると、すべてのユーザーが更新通知を受信して読むことができます。
新しい観測対象クラス:
import lombok.Getter;
import java.util.Observable;
/**
* 观察目标:栈长
* 来源微信公众号:Java技术栈
*/
@Getter
public class JavaStackObservable extends Observable {
private String article;
/**
* 发表文章
* @param article
*/
public void publish(String article){
// 发表文章
this.article = article;
// 改变状态
this.setChanged();
// 通知所有观察者
this.notifyObservers();
}
}
オブザベーションターゲットのロジックは、最初に記事を公開し、次にオブザベーションターゲットの状態を変更してから、すべてのオブザーバーに通知することです。
notifyObserversメソッドのソースコードに焦点を当てましょう。
最初に同期ロックを取得し、状態が更新されているかどうかを判断し、更新されている場合は、監視ターゲットの状態をクリアしてから、forループを使用してすべてのオブザーバーをトラバースし、オブザーバーのupdateメソッドを呼び出してオブザーバーに更新を通知します。
オブザーバークラスを追加します。
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.util.Observable;
import java.util.Observer;
/**
* 观察者:读者粉丝
* 来源微信公众号:Java技术栈
*/
@RequiredArgsConstructor
public class ReaderObserver implements Observer {
@NonNull
private String name;
private String article;
@Override
public void update(Observable o, Object arg) {
// 更新文章
updateArticle(o);
}
private void updateArticle(Observable o) {
JavaStackObservable javaStackObservable = (JavaStackObservable) o;
this.article = javaStackObservable.getArticle();
System.out.printf("我是读者:%s,文章已更新为:%s\n", this.name, this.article);
}
}
オブザーバーのロジックは、オブザーバーターゲットインスタンスオブジェクトを取得し、オブザーバーターゲットオブジェクトの記事情報を独自の記事情報に更新し、最後にその記事が更新されたことを出力することです。
オブザーバーは、呼び出し通知のターゲットを監視するために使用されるオブザーバーインターフェイスの更新メソッドを実装するだけで済みます。
このチュートリアルの実際のソースコードはすべて、次のリポジトリにアップロードされています:https://github.com/javastacks/javastack
観測対象と観測者クラスの構造図は次のとおりです。
新しい試験クラス:
/**
* 观察者:读者粉丝
* 来源微信公众号:Java技术栈
*/
public class ObserverTest {
public static void main(String[] args) {
// 创建一个观察目标
JavaStackObservable javaStackObservable = new JavaStackObservable();
// 添加观察者
javaStackObservable.addObserver(new ReaderObserver("小明"));
javaStackObservable.addObserver(new ReaderObserver("小张"));
javaStackObservable.addObserver(new ReaderObserver("小爱"));
// 发表文章
javaStackObservable.publish("什么是观察者模式?");
}
}
オブザーバーとオブザーバーを作成するためのシーケンス要件はありません。重要な点は、オブザーバーに通知する記事を公開する前に、オブザーバーリストにオブザーバーターゲットを追加する必要があるということです。
出力結果:
この簡単な記事のプッシュ練習を通じて、誰もがオブザーバーパターンの基本を理解している必要があります。実際の作業では、使用できるシナリオが多数あり、オブザーバーパターンは1対多の依存関係について考慮することができます。
要約する
簡単ではありませんが、次々と長時間働いた後、オブザーバーモードを習得しましたか?
オブザーバーパターンのメリットは、オブザーバーターゲットとオブザーバーを分離することであり、デメリットも明らかです。上記の例から、オブザーバーオブジェクトが多すぎると、メモリリークが発生する可能性があることがわかります。
さらに、パフォーマンスの観点から、すべてのオブザーバーの更新はループでキューに入れられるため、オブザーバーの更新操作は非同期スレッドと見なすことができ(またはスレッドプールを使用できます)、全体的な効率が向上します。
このチュートリアルの実際のソースコードはすべて、このリポジトリにアップロードされています。
https://github.com/javastacks/javastack