Dynamic Singleton initialization (depending on parameter)

Viewed 142

I am using dart singleton like this:

class MyHandler {
  static final MyHandler _singleton = MyHandler._internal();
  Database database;

  factory MyHandler({bool initDb}) {
    return _singleton;
  }

  MyHandler._internal() {
    initialize();
  }

  void initialize() async {
    // initializing database here
  }
}

now my problem is, that when calling initialize on first creation in _internal() a database is instantiated. In my tests I can't access this database so I would like to only execute the initialize()-method when running my app normally but not when doing tests.

That is why I tried to pass a (bool)-parameter on the singleton creation to decide if initialize() should be called or not. Is this possible? I did not find a way to do that. Is there some other solution? Thanks!

1 Answers

Can it be done? Yes, but I would not recommend doing it as you have proposed. Here is an implementation for reference.

// emphasis - this is not great design
class Handler {
  static final Handler _singleton = Handler._internal();
  static bool _initialized = false;
  
  factory Handler({bool initDb = true}){
    if(initDb && !_initialized){
      Handler._singleton._initializeDb();
      Handler._initialized = true;
    }
    return _singleton;
  }
  
  Handler._internal();
 
  void _initializeDb(){
    // ...
  }
}

What happens if a Handler is requested first with initDb = false, and then subsequently initDb = true? or vice-versa true then false? These could lead to confusing and opaque problems down the line.

There are several alternative ways to approach this problem, but utilizing dependency injection is a good approach. Once you have DI implemented, you can provide a mock Database object. Another might be connecting to a test database instead of a production one.

Related