I've recently came across a small challenge of implementing a decorator pattern in a Flutter project.
My project uses the get_it package for the service locator implementation. We didn't find direct/explicit support for decoration for that package (as opposed to Scrutor that we used in our .NET projects).
The second interrogation was which constructs to use to implement each part of the pattern? I know that in C#, I would use an interface
for the abstraction and class
for the implementations. In Dart, the constructs are slightly more confusing.
An important part of the solution is setting allowReassignment = true
on the GetIt
container.
This allows to override a registration with another, which is required in our case so that the decorator replaces the original registration.
For the constructs, we can use abstract interface class
for the abstraction and class
(or in this sample final class
) for the implementations.
Here's a full code example:
abstract interface class Service {
int getNumber();
}
final class ServiceImplementation implements Service {
@override
int getNumber(){
return 1;
}
}
final class ServiceDecorator implements Service {
final Service _service;
ServiceDecorator(this._service);
@override
int getNumber(){
return _service.getNumber() * 2;
}
}
GetIt.I.allowReassignment = true;
GetIt.I.registerSingleton<Service>(ServiceImplementation());
GetIt.I.registerSingleton<Service>(ServiceDecorator(GetIt.I.get<Service>()));
var number = GetIt.I.get<Service>().getNumber();
print(number); // Shows 2, not 1.
With this approach, both the end consumer and the decorator only use the Service
abstraction which keeps low class coupling and favors SOLID principles.