See the Medium article here!
Implementing the dao factory pattern in Flutter.
Demonstrates the design pattern utilising Factory method and Singleton, with Provider, in order to build an architecture which decouples the DAO implementation details away from application code, allowing the implementation to be easily switched with minimal refactoring at compile or runtime.
Although Singleton is arguably an anti-pattern, it appears to be a useful solution within this use case.
Easily switch between 3 different persistence DAO implementations with minimal changes to application layer code.
- You may want to use different persistence providers depending on the state of the app, or the platform. I.e. suppose there was a situation where:
- You had to use Hive for Web platform, and ObjectBox for Android/Ios/Desktop.
- You had to use Hive if a User was not signed in, but once they were signed in, you would rather use Firestore.
- You want to future-proof your application and do not want to tie yourself to any one particular implementation. For example, you may have started off with
sqflite
but realised later on you want your application to support Web, whichsqflite
does not support at the time of writing. Using this pattern, you can easily plug in a web-supported persistence implementation, such ashive
with minimal refactoring.
- Rather than scattering conditionals throughout your code, we can separate the implementation details of our persistence layer away from the application code using the Factory pattern.
- For ease of demonstration, this example uses 2 local storage implementations - Hive & ObjectBox, for the purposes of persisting a User object.
- If you wanted to switch out the DAO implementation for unit testing, this would then become as simple as creating a new DAOImpl that implments the
UserDAO
interface, and then wiring up a switch inUserDAOFactory
to return a mockDAO, i.e.if (isTest == true) return UserDAOMockImpl();
- Create a DAOFactory class.
- This class will contain a getDAO method which returns the appropriate DAO implementation class based on some input.
public static DAO getDAO(String type) {
if (type == 'hive') {
return DAOHiveImpl();
} else {
return DAOObjectBoxImpl();
}
}
- Create a DAO interface. (Abstract class in Dart).
- Create your DAO implementation classes as Singletons, i.e. one for Hive & one for ObjectBox, which implement the DAO interface, ensuring they have the same guaranteed functionalities.
- From the application code, we can make an implementation-agnostic call to the persistence layer, letting the
UserDAOFactory
object decide which DAO implementation to use.:
UserDAOFactory.getUserDAO().addUser();
- Ensure the generators are installed as dev dependencies, i.e.
build_runner
, andhive_generator
for Hive andobjectbox_generator
for ObjectBox
flutter pub run build_runner build
https://refactoring.guru/design-patterns/factory-method https://medium.com/flutter-community/flutter-design-patterns-10-factory-method-c53ad11d863f https://stackoverflow.com/questions/6401543/what-is-dao-factory-pattern https://medium.com/flutter-community/flutter-design-patterns-1-singleton-437f04e923ce
Please feel free to comment any better solutions or feedback. We are always open for new ideas!