0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Observerパターンについて調べたのでFlutterでサンプルを作ってみた

Last updated at Posted at 2023-05-07

Observerパターンについて軽く

Observer は観測者という意味だが、どちらかというと観測される側(Subject)から観測者へ、どう通知するかについてまとめられたパターン。
通知側(Subject)で観測対象の事象が発生したら、観測側(Observer)へ通知(notifyObservers())し、観測側の処理を開始する(update())。
通知側と観測側を分離することによって、事象の発生とその事象に対してどう振る舞うか、が分離されるのがメリット。

サンプルとして何を作ったか

新しくFlutterプロジェクトを作成するときに自動生成されるカウンターアプリを元に、カウントがインクリメントされたらファイル書き込みとDB書き込みするように変更し、その通知をObserverパターンを用いて行う。
(サンプルコードとしてはファイル書き込み、DB書き込みを行った、というていのログのみ記載)

クラス図

コード

GitHub に完全版があります。

observer.dart
abstract class Observer {
  void update(int counter);
}
subject.dart
import 'package:flutter_observer/utils/observer.dart';

abstract class Subject {
  void addObserver(Observer observer);
  void removeObserver(Observer observer);
  void notifyObservers();
}
file_writer.dart
import 'package:flutter_observer/utils/observer.dart';

class FileWriter implements Observer {
  @override
  void update(counter) {
    // とりあえずログ記載のみ行う
    print('$counter をファイルに書き込み');
  }
}
db_writer.dart
import 'package:flutter_observer/utils/observer.dart';

class DbWriter implements Observer {
  @override
  void update(counter) {
    // とりあえずログ記載のみ行う
    print('$counter をDBに書き込み');
  }
}
my_home_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_observer/utils/db_writer.dart';
import 'package:flutter_observer/utils/file_writer.dart';
import 'package:flutter_observer/utils/observer.dart';
import 'package:flutter_observer/utils/subject.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> implements Subject {
  int _counter = 0;
  final List<Observer> _observers = [];

  @override
  void addObserver(Observer observer) {
    _observers.add(observer);
  }

  @override
  void removeObserver(Observer observer) {
    _observers.remove(observer);
  }

  @override
  void notifyObservers() {
    for (final observer in _observers) {
      observer.update(_counter);
    }
  }

  @override
  void initState() {
    addObserver(FileWriter());
    addObserver(DbWriter());

    super.initState();
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
      notifyObservers();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?