Kit
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
Real-world example
To create a kingdom we need objects with a common theme. The Elven Kingdom needs Elven King, Elven Castle, and Elven Army, whereas The Orcish Kingdom needs an Orcish King, Orcish Castle, and Orcish Army. There is a dependency between the objects in the kingdom.
In plain words
A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.
Wikipedia says
The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes
Programmatic Example
Translating the kingdom example above. First of all, we have some interfaces and implementation for the objects in the kingdom.
1public interface Castle {
2 String getDescription();
3}
4
5public interface King {
6 String getDescription();
7}
8
9public interface Army {
10 String getDescription();
11}
12
13// Elven implementations ->
14public class ElfCastle implements Castle {
15 static final String DESCRIPTION = "This is the elven castle!";
16 @Override
17 public String getDescription() {
18 return DESCRIPTION;
19 }
20}
21public class ElfKing implements King {
22 static final String DESCRIPTION = "This is the elven king!";
23 @Override
24 public String getDescription() {
25 return DESCRIPTION;
26 }
27}
28public class ElfArmy implements Army {
29 static final String DESCRIPTION = "This is the elven Army!";
30 @Override
31 public String getDescription() {
32 return DESCRIPTION;
33 }
34}
35
36// Orcish implementations similarly -> ...
Then we have the abstraction and implementations for the kingdom factory.
1public interface KingdomFactory {
2 Castle createCastle();
3 King createKing();
4 Army createArmy();
5}
6
7public class ElfKingdomFactory implements KingdomFactory {
8
9 @Override
10 public Castle createCastle() {
11 return new ElfCastle();
12 }
13
14 @Override
15 public King createKing() {
16 return new ElfKing();
17 }
18
19 @Override
20 public Army createArmy() {
21 return new ElfArmy();
22 }
23}
24
25public class OrcKingdomFactory implements KingdomFactory {
26
27 @Override
28 public Castle createCastle() {
29 return new OrcCastle();
30 }
31
32 @Override
33 public King createKing() {
34 return new OrcKing();
35 }
36
37 @Override
38 public Army createArmy() {
39 return new OrcArmy();
40 }
41}
Now we have the abstract factory that lets us make a family of related objects i.e. elven kingdom factory creates elven castle, king and army, etc.
1var factory = new ElfKingdomFactory();
2var castle = factory.createCastle();
3var king = factory.createKing();
4var army = factory.createArmy();
5
6castle.getDescription();
7king.getDescription();
8army.getDescription();
Program output:
1This is the elven castle!
2This is the elven king!
3This is the elven Army!
Now, we can design a factory for our different kingdom factories. In this example, we created FactoryMaker
, responsible for returning an instance of either ElfKingdomFactory
or OrcKingdomFactory
.
The client can use FactoryMaker
to create the desired concrete factory which, in turn, will produce different concrete objects (derived from Army
, King
, Castle
).
In this example, we also used an enum to parameterize which type of kingdom factory the client will ask for.
1public static class FactoryMaker {
2
3 public enum KingdomType {
4 ELF, ORC
5 }
6
7 public static KingdomFactory makeFactory(KingdomType type) {
8 return switch (type) {
9 case ELF -> new ElfKingdomFactory();
10 case ORC -> new OrcKingdomFactory();
11 default -> throw new IllegalArgumentException("KingdomType not supported.");
12 };
13 }
14}
15
16 public static void main(String[] args) {
17 var app = new App();
18
19 LOGGER.info("Elf Kingdom");
20 app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
21 LOGGER.info(app.getArmy().getDescription());
22 LOGGER.info(app.getCastle().getDescription());
23 LOGGER.info(app.getKing().getDescription());
24
25 LOGGER.info("Orc Kingdom");
26 app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
27 --similar use of the orc factory
28 }
Use the Abstract Factory pattern when
Example use cases