Реализовать шаблон Observer в Dart

Я хотел бы внедрить шаблон наблюдателя в Dart, но я не уверен, как это сделать.

Допустим, у меня есть класс:

class MyClass {

  String observed_field;

}

Теперь, когда бы я ни менял поле, я хотел бы напечатать в консоли строку "наблюдаемое поле изменилось". Довольно просто сделать с помощью пользовательского сеттера:

class MyClass {

  String _observed_field;

  get observed_field    => _observed_field;
  set observed_field(v) {
    _observed_field = v;
    print("observed_field changed");
  }

}

Теперь, конечно, если бы у меня было не одно, а много таких полей, я бы не хотел создавать все эти методы получения и установки. Очевидное теоретическое решение состоит в том, чтобы динамически добавлять их в класс с помощью чего-то вроде этого (не рабочий код, просто пример того, как я хотел бы, чтобы это выглядело):

class MyClass

  String  _observeable_field;
  String  _observeable_field_2;

  observe(#observeable_field, #observeable_field_2);

end

Это вообще возможно? Кроме того, было бы здорово, если бы эти поля не были определены выше observe() позвоните, а лучше напишите что-то вроде:

observe(String: #_observeable_field, String: #_observeable_field_2);

Так что эти поля объявляются автоматически.

1 ответ

Решение

Вот способ сделать это с помощью пакета Observe. Пример взят из комментариев кода в этом пакете (и адаптирован к вашему примеру выше). По сути, вы аннотируете поля, которые вы хотите наблюдать с помощью @observable аннотации, а затем прослушать изменения (которые вы вызываете при вызове Observable.dirtyCheck();

Во-первых, добавьте наблюдаемый пакет в ваш pubspec.yaml

dependencies:
  observe: any

Затем создайте программу быстрого тестирования...

import 'package:observe/observe.dart';

class MyClass extends Object with Observable {
  @observable String observedField = "Hello";

  toString() => observedField.toString(); 
}

main() {
  var obj = new MyClass();

  // anonymous function that executes when there are changes
  obj.changes.listen((records) {
    print('Changes to $obj were: $records');
  });


  obj.observedField = "Hello World";

  // No changes are delivered until we check for them
  Observable.dirtyCheck();

  print('done!');
}

Это дает следующий вывод:

Changes to Hello World were: [#<PropertyChangeRecord Symbol("observedField") from: Hello to: Hello World>]
done!

Обновление в ответ на комментарии... Обновление примера, чтобы опустить Observable.dirtyCheck() Вы можете использовать сеттер и notifyPropertyChangedс классом вместо того, чтобы смешаться в ChangeNotifier

class MyClass2 extends Object with ChangeNotifier {

  String _observedField = "Hello";

  @reflectable get observedField    => _observedField;
  @reflectable set observedField(v) {
    _observedField = notifyPropertyChange(#observedField, _observedField, v);    
  }

  toString() => observedField;

}
Другие вопросы по тегам