Light logo

Factories

Learn the basics behind factories in ReArch.

Factories

Factories (sometimes called factory capsules) are not unique to ReArch at all; in fact, ReArch just borrows the concept from OOP! From Wikipedia:

In object-oriented programming, a factory is an object for creating other objects; formally, it is a function or method that returns objects of a varying prototype or class

In ReArch, factories are just capsules that create objects on the fly and can consume some additional non-capsule parameters. Although factories may seem complex at first, they actually just boil down to some very straight forward syntactic sugar.

An Example

Example Factory Capsule
int dependency1Capsule(CapsuleHandle _) => 0;
String dependency2Capsule(CapsuleHandle _) => 'hello world!';

MyObject Function(String, int) myObjectFactory(CapsuleHandle use) {
  // Notice how we only call `use` *before returning the factory closure*;
  // this is important, as you cannot call `use` across an asynchronous gap.
  // In other words, *DO NOT CALL USE WITHIN THE FACTORY BODY ITSELF*.
  final dep1 = use(dependency1Capsule);
  final dep2 = use(dependency2Capsule);
  return (dep3, dep4) => MyObject(dep1, dep2, dep3, dep4);
}

void usesFactoryCapsule(CapsuleHandle use) {
  final MyObject obj = use(myObjectFactory)('some string', 1234);
  obj.doSomething();
}

Caching Created Objects

If you need to:

  • Cache a factory-created object (perhaps until the factory instance changes)
  • Dispose old factory-created objects to prevent leaks (perhaps when a new object is created)

Then take a look at the following snippet.

If you are familiar with React or flutter_hooks, this will feel exceedingly natural to you. See the dedicated documentation page on side effects for more.

dart
Caching objects created with factories
MyCustomObject defaultParamMyCustomObjCapsule(CapsuleHandle use) {
  // Our factory capsule:
  final objFactory = use(objFactoryCapsule);

  // Some arbitrary capsule that may cause a rebuild
  // even when objFactory itself doesn't change:
  final someString = use(someCapsule);

  // Only recreate myObj when objFactory or someString change
  final myObj = use.memo(() {
    return objFactory(someString);
  }, [objFactory, someString]);

  // Whenever myObj changes, register the new object for disposal
  use.effect(() => myObj.dispose, [myObj]);

  return myObj;
}

This combination of memo and effect is very common, especially when handling FooBarControllers, so it is best to learn how to use them early on.