Delphi の Observer パターンは、基本的な Observer パターンを拡張します。オブザーバー モードの詳細については、[Gam+、293 ~ 303 ページ] を参照してください。
オブジェクト間の 1 対多の依存関係を定義します。オブジェクトの状態が変化すると、そのオブジェクトに依存するすべてのオブジェクトが通知され、自動的に更新されます。
システムを一連の連携クラスに分割すると、関連するオブジェクト間の一貫性を保護する必要があるという、特定の副作用が生じます。次元の一貫性を保つために型を密結合することは望ましくありません。再利用性が低下するからです。 [Gam+、p293]。
Delphi のイベント(実際のメソッド アドレス)を使用すると、これらの問題を処理するための適切な構造を構築でき、たとえば、イベント TButton.OnClick をディスパッチして関連作業を完了できます。ただし、クラスはイベント ハンドラーへの参照を保存しません。オブザーバーパターンでは、イベントを送出するクラスを対象オブジェクト(サブジェクト)、イベントを制御するクラスをオブザーバー(オブザーバー)と呼びます。
Delphi のイベントでは、クラスの結合をより適切に排除できます。複数のイベントを制御してオブザーバー モードを参照する場合は、1 対多の通知メカニズムを確立できます。ターゲットには任意の数のオブザーバーを含めることができます。ターゲットの状態が変化すると、すべてのオブザーバーが通知を受け取ります。オブザーバーは通知を受信すると、ターゲット オブジェクトとの同期を維持するためにターゲット オブジェクトにただちにクエリを実行します。
この対話はパブリッシュ/サブスクライブとも呼ばれ、ターゲットは通知の発行者です。通知を発見したときに、そのオブザーバーが誰であるかを知る必要はありません。任意の数のオブザーバーがサブスクライブして通知を受信できます。
このオブザーバー モード アプリケーションは、クラス結合の処理において Delphi イベント メカニズムの利点をもたらします。 1 対多の構造では、登録と登録解除を通じてオブザーバーを登録します。 1 対多のメカニズムは実際には反復子に基づいて適用されます。
意味のある動作を定義する Tsubject クラスがあるとします。まずオブザーバー モードのデモ コードを見てみましょう。
タイプ
TSubject = クラス (TObject)
プライベート
FObserver: TList;
公共
プロシージャ RegisterObserver(オブザーバー: TSubjectObserver);
プロシージャ UnregisterObserver(オブザーバ: TSubjectObserver);
終わり;
TSubjectObserver = クラス (TComponent)
プライベート
FEnabled: ブール値。
出版された
プロパティ Enabled: ブール値読み取り FEnabled 書き込み FEnabled。デフォルトは True。
終わり;
上記のインターフェイスの中には次のものがあります。
? Tsubject のオブザーバーを登録するための登録メカニズム。
� FObservers: TList; 登録されたオブザーバーを保管します。
¨ RegisterObserver(..) は、オブザーバーを登録し、それらを Fobserver に追加するために使用されます。
¨ UnregisterObserver(..) は、オブザーバーの登録を解除し、Fobserver から関連オブジェクトを削除するために使用されます。
?オブザーバー モードでも、新しいクラス TsubjectObserver を作成する必要があります。
¨ このクラスは Tcomponent の子孫です。
Enabled プロパティは、監視をオンまたはオフに設定します。 。
次のオブザーバー モードの実際のアプリケーション:
プロシージャ TSubject.RegisterObserver(オブザーバー: TSubjectObserver);
始める
FObservers.IndexOf(Observer) = -1 の場合
FObservers.Add(オブザーバー);
終わり;
プロシージャ TSubject.UnregisterObserver(オブザーバー: TSubjectObserver);
始める
FObservers.Remove(オブザーバー);
終わり;
Shanguan の実装は、オブザーバーの登録部分をサポートしています。 1 対多の通知メカニズムはどこにありますか?実際の 1 対多の通知アプリケーションの場合、Tsubject の Change メソッドを定義して登録されたオブザーバーに通知することができ、オブザーバーはスケジュールを処理するために OnChange イベント属性を定義できます。コードは次のとおりです。
タイプ
TSubject = クラス (TObject)
プライベート
FObserver: TList;
保護された
» プロシージャ 変更 {このメソッドを呼び出して通知を送信します}
公共
プロシージャ RegisterObserver(オブザーバー: TSubjectObserver);
プロシージャ UnregisterObserver(オブザーバ: TSubjectObserver);
終わり;
TSubjectObserver = クラス (TComponent)
プライベート
FEnabled: ブール値。
» FOnChange: TNotifyEvent;
保護された
» 手順の変更;
出版された
プロパティ Enabled: ブール値読み取り FEnabled 書き込み FEnabled;
» プロパティ OnChange: TNotifyEvent 読み取り FOnChange 書き込み FOnChange;
終わり;
実装
プロシージャTSubject.Change;
変数
» 観測: TSubjectObserver;
» I: 整数。
始める
» for I := 0 から FObservers.Count - 1 へ
" 始める
» Obs := FObservers[I];
» Obs.Enabled の場合は Obs.Change;
" 終わり;
終わり;
プロシージャ TSubject.RegisterObserver(オブザーバー: TSubjectObserver);
始める
FObservers.IndexOf(Observer) = -1 の場合
FObservers.Add(オブザーバー);
終わり;
プロシージャ TSubject.UnregisterObserver(オブザーバー: TSubjectObserver);
始める
FObservers.Remove(オブザーバー);
終わり;
プロシージャTSubjectObserver.Change;
始める
» if Assigned(FOnChange) then FOnChange(Self);
終わり;
上記の実装コードでは次のようになります。
? Tsubject の Change メソッドは、登録されているすべてのオブザーバーを反復処理し、各オブザーバーの Change メソッド (1 対多の通知の実装) を呼び出します。
? オブザーバーの Enabled プロパティは、通知を受信するかどうかを決定します。
? TsubjectObserver の OnChange イベントは、実際に同期やその他の操作を処理します。
整理する
//「デザインパターン」からの抜粋多数