Flutter/Dart

【Flutter/Dart】Observerパターン

asoacasio

Observerパターンは、観察対象のオブジェクトに変更が発生した場合に、依存する他のオブジェクトに通知を行うデザインパターンです。

  • 観察対象(Subject):状態が変わると観察者に通知します。
  • 観察者(Observer):観察対象の状態変化を監視します。変化が起きた時に、その通知を受け取り必要な行動を起こします。

メリット

  • 依存関係の分離:観察対象と観察者の依存関係を最低限に抑え、疎結合(モジュールやクラス等の各コンポーネント間の依存度が最小限になる設計のこと)な構造を作ります。これによって一方が変更されても他方への影響を与えにくい構造になっています。
  • オープン・クローズド原則の実現:観察対象は新たな観察者が追加されても変更する必要がありません。また、新たな観察者を追加する際も既存のコードを変更する必要がないため、拡張に対して開いており変更に対して閉じているというオープン・クローズド原則を満たすことができます。
  • 更新の自動化:観察対象の状態が変わった場合、観察者は自動的にそれを認識して反応することができます。
  • ブロードキャスト通信:観察対象が一度に複数の観察者に対して通知を行うことができます。

効果的に利用できるシナリオ

株価の監視

株価情報の追跡ツールで効果的に利用できます。株価が一定のしきい値を上回ったり下回ったりした際に通知を送ることができます。

GUI

GUIでは、ボタンを押したりテキストに入力したりするユーザ操作がアプリの状態を変化させ、その結果を画面に反映させる必要があります。

Observerパターンはこのような状態の変化とそれに伴う表示の更新の間で連携を取るのに役立ちます。

サンプルコード

チャットメッセージの投稿通知を例にして、サンプルコードを書きます。

新しい投稿があった場合にすぐにチャットスクリーン通知センターに知らせて表示をさせます。

今回の例ではチャットスクリーンと通知センターが観察者です。

チャットメッセージが観察対象になります。

import 'dart:developer';

/// 観察者
abstract class Observer {
  void update(String message);
}

/// チャットスクリーン
class ChatScreen implements Observer {
  @override
  void update(String message) {
    log('CHAT: $message');
  }
}

/// 通知センター
class NotificationCenter implements Observer {
  @override
  void update(String message) {
    log('NOTIFICATION: $message');
  }
}

/// チャットメッセージ
class ChatMessage {
  final List<Observer> _observers = [];

  /// 観察者を追加する
  void addObserver(Observer observer) {
    _observers.add(observer);
  }

  /// 観察者を削除する
  void removeObserver(Observer observer) {
    _observers.remove(observer);
  }

  /// 観察者に通知する
  void notifyObservers(String message) {
    for (var observer in _observers) {
      observer.update(message);
    }
  }

  /// メッセージを送信する
  void sendMessage(String message) {
    notifyObservers(message);
  }
}

クライアントコードです。

  1. チャットスクリーンと通知センターにチャットメッセージが表示できる設定にしていました。
  2. 「おはよう!」とメッセージを送ります。
  3. 通知センターの表示設定だけ解除しました。
  4. 「こんにちは!」とメッセージを送ります。
void main() {
  // チャットメッセージを作成します。
  ChatMessage chatMessage = ChatMessage();

  // チャットスクリーンと通知センターを作成します。
  ChatScreen chatScreen = ChatScreen();
  NotificationCenter notificationCenter = NotificationCenter();

  // チャットメッセージに観察者を追加します。
  chatMessage.addObserver(chatScreen);
  chatMessage.addObserver(notificationCenter);

  // チャットメッセージを送信します。
  chatMessage.sendMessage('おはよう!');

  // 通知センターへの表示設定をOFFにしたとします。
  log('通知センターへの表示設定をOFFにしました。');
  // チャットメッセージから観察者を削除します。
  chatMessage.removeObserver(notificationCenter);

  // チャットメッセージを送信します。
  chatMessage.sendMessage('こんにちは!');
}

続いて、ログを見てみます。

[log] CHAT: おはよう!
[log] NOTIFICATION: おはよう!
[log] 通知センターへの表示設定をOFFにしました。
[log] CHAT: こんにちは!

1回目のメッセージ「おはよう!」では、チャットスクリーンと通知センターへ変更情報が伝わっているのが分かります。

2回目のメッセージ「こんにちは!」では、観察者から通知センターを外したのでチャットスクリーンにのみ変更情報が伝わっているのが分かります。

メリットであるオープン・クローズド原則が実現されています。

ABOUT ME
なっとう
なっとう
Fluttter開発 プログラマー
噛み砕いて説明できるようになれば、プログラマーとしての質が上がるのではないかと思い、ブログを始めました。 このノウハウが誰かのお役に立てば嬉しいです。
記事URLをコピーしました