Реализовать шаблон 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;
}