When requesting dependencies, the implementations may differ for various contexts. DiVine lets you specify factories, which have the purpose of creating instances based on the given parameters.
You can bind a factory for a service directly.
@Service(factory = MyFactory.class)
class MyService { ... }
You can define your factory somewhere.
class MyFactory implements Factory<MyService, MyProperty> { ... }
The factory properties may differ depending on your use case.
class MyFactory implements Factory<MyService, String> { ... }
class MyFactory implements Factory<MyService, MyEnum> { ... }
... and so on.
When requesting a dependency for a service, you must also pass in the properties, as specified by the service.
class CoolFactory implements Factory<AmazingService, String> { ... }
void requestDependency() {
AmazingService service = Container.get(AmazingService, "EXAMPLE_PARAMETER");
}
Note that parameter arguments are checked at runtime, so factory types are guaranteed inside the factory class.
The following code showcases a simple way of requesting different implementations for a service.
@Service(
// use the `CarFactory` class to create new instances for the `Car` type
factory = CarFactory.class,
// use `TRANSIENT` scope, to create a new car instance, each time a car
// is requested
scope = ServiceScope.TRANSIENT
)
interface Car {
void drive();
}
enum CarType {
MERCEDES,
BMW,
FERRARI
}
class CarFactory implements Factory<
Car,
CarType // you may specify any arbitrary factoryparameter type
> {
@Override
public @NotNull Car create(
@NotNull Service descriptor, @NotNull Class<? extends Car> type,
@NotNull Class<?> context, @Nullable CarType carType
) {
return switch (carType) {
case MERCEDES -> new MercedesCar();
case BMW -> new BMWCar();
case FERRARI -> new FerrariCar();
};
}
}
@Service
class CarDealership() {
public Car orderCar(CarType type) {
return Container.get(Car.class, type);
}
}
void orderCars() {
CarDealership dealership = Container.get(CarDealership.class);
assert dealership.orderCar(CarType.MERCEDES) instanceof MercedesCar;
assert dealership.orderCar(CarType.BMW) instanceof BMWCar;
assert dealership.orderCar(CarType.FERRARY) instanceof FerraryCar;
}