Search code examples
flutterdartdependency-injection

How to implement a decorator pattern in Dart/Flutter using the GetIt package


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.


Solution

  • 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:

    Interface and Implementations

    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;
      }
    }
    

    Usage

    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.