Abstract-Factory
Define a factory of immutable content with separated builder and factory interfaces.
Real-world example
Imagine a magical weapon factory that can create any type of weapon wished for. When the factory is unboxed, the master recites the weapon types needed to prepare it. After that, any of those weapon types can be summoned in an instant.
In plain words
Factory kit is a configurable object builder, a factory to create factories.
Programmatic Example
Let’s first define the simple Weapon
hierarchy.
1public interface Weapon {
2}
3
4public enum WeaponType {
5 SWORD,
6 AXE,
7 BOW,
8 SPEAR
9}
10
11public class Sword implements Weapon {
12 @Override
13 public String toString() {
14 return "Sword";
15 }
16}
17
18// Axe, Bow, and Spear are defined similarly
Next, we define a functional interface that allows adding a builder with a name to the factory.
1public interface Builder {
2 void add(WeaponType name, Supplier<Weapon> supplier);
3}
The meat of the example is the WeaponFactory
interface that effectively implements the factory
kit pattern. The method #factory
is used to configure the factory with the classes it needs to
be able to construct. The method #create
is then used to create object instances.
1public interface WeaponFactory {
2
3 static WeaponFactory factory(Consumer<Builder> consumer) {
4 var map = new HashMap<WeaponType, Supplier<Weapon>>();
5 consumer.accept(map::put);
6 return name -> map.get(name).get();
7 }
8
9 Weapon create(WeaponType name);
10}
Now, we can show how WeaponFactory
can be used.
1var factory = WeaponFactory.factory(builder -> {
2 builder.add(WeaponType.SWORD, Sword::new);
3 builder.add(WeaponType.AXE, Axe::new);
4 builder.add(WeaponType.SPEAR, Spear::new);
5 builder.add(WeaponType.BOW, Bow::new);
6});
7var list = new ArrayList<Weapon>();
8list.add(factory.create(WeaponType.AXE));
9list.add(factory.create(WeaponType.SPEAR));
10list.add(factory.create(WeaponType.SWORD));
11list.add(factory.create(WeaponType.BOW));
12list.stream().forEach(weapon -> LOGGER.info("{}", weapon.toString()));
Here is the console output when the example is run.
21:15:49.709 [main] INFO com.iluwatar.factorykit.App - Axe
21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Spear
21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Sword
21:15:49.713 [main] INFO com.iluwatar.factorykit.App - Bow
Use the Factory Kit pattern when