mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-11 12:19:03 +00:00
docs: collecting parameter docs + formatting
This commit is contained in:
1 parent
ea7bc2a4eb
commit
f80cc468b2
23 files changed
+1191
-794
No files matched your search
+65
-45
@@ -3,9 +3,9 @@ title: Abstract Factory
|
||||
category: Creational
|
||||
language: en
|
||||
tag:
|
||||
- Abstraction
|
||||
- Decoupling
|
||||
- Gang of Four
|
||||
- Abstraction
|
||||
- Decoupling
|
||||
- Gang of Four
|
||||
---
|
||||
|
||||
## Also known as
|
||||
@@ -14,25 +14,32 @@ Kit
|
||||
|
||||
## Intent
|
||||
|
||||
The Abstract Factory design pattern provides a way to create families of related objects without specifying their concrete classes. This allows for code that is independent of the specific classes of objects it uses, promoting flexibility and maintainability.
|
||||
The Abstract Factory design pattern provides a way to create families of related objects without specifying their
|
||||
concrete classes. This allows for code that is independent of the specific classes of objects it uses, promoting
|
||||
flexibility and maintainability.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real-world example
|
||||
|
||||
> To create a kingdom we need objects with a common theme. The elven kingdom needs an 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.
|
||||
> To create a kingdom we need objects with a common theme. The elven kingdom needs an 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.
|
||||
> 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
|
||||
> 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.
|
||||
Translating the kingdom example above. First of all, we have some interfaces and implementation for the objects in the
|
||||
kingdom.
|
||||
|
||||
```java
|
||||
public interface Castle {
|
||||
@@ -50,20 +57,25 @@ public interface Army {
|
||||
// Elven implementations ->
|
||||
public class ElfCastle implements Castle {
|
||||
static final String DESCRIPTION = "This is the elven castle!";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
}
|
||||
}
|
||||
|
||||
public class ElfKing implements King {
|
||||
static final String DESCRIPTION = "This is the elven king!";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
}
|
||||
}
|
||||
|
||||
public class ElfArmy implements Army {
|
||||
static final String DESCRIPTION = "This is the elven Army!";
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return DESCRIPTION;
|
||||
@@ -79,7 +91,9 @@ Then we have the abstraction and implementations for the kingdom factory.
|
||||
```java
|
||||
public interface KingdomFactory {
|
||||
Castle createCastle();
|
||||
|
||||
King createKing();
|
||||
|
||||
Army createArmy();
|
||||
}
|
||||
|
||||
@@ -112,7 +126,7 @@ public class OrcKingdomFactory implements KingdomFactory {
|
||||
public King createKing() {
|
||||
return new OrcKing();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Army createArmy() {
|
||||
return new OrcArmy();
|
||||
@@ -120,64 +134,68 @@ public class OrcKingdomFactory implements KingdomFactory {
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```java
|
||||
var factory = new ElfKingdomFactory();
|
||||
var castle = factory.createCastle();
|
||||
var king = factory.createKing();
|
||||
var army = factory.createArmy();
|
||||
var factory=new ElfKingdomFactory();
|
||||
var castle=factory.createCastle();
|
||||
var king=factory.createKing();
|
||||
var army=factory.createArmy();
|
||||
|
||||
castle.getDescription();
|
||||
king.getDescription();
|
||||
army.getDescription();
|
||||
castle.getDescription();
|
||||
king.getDescription();
|
||||
army.getDescription();
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```java
|
||||
This is the elven castle!
|
||||
This is the elven king!
|
||||
This is the elven Army!
|
||||
This is the elven king!
|
||||
This 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.
|
||||
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.
|
||||
|
||||
```java
|
||||
public static class FactoryMaker {
|
||||
|
||||
public enum KingdomType {
|
||||
ELF, ORC
|
||||
}
|
||||
public enum KingdomType {
|
||||
ELF, ORC
|
||||
}
|
||||
|
||||
public static KingdomFactory makeFactory(KingdomType type) {
|
||||
return switch (type) {
|
||||
case ELF -> new ElfKingdomFactory();
|
||||
case ORC -> new OrcKingdomFactory();
|
||||
};
|
||||
}
|
||||
public static KingdomFactory makeFactory(KingdomType type) {
|
||||
return switch (type) {
|
||||
case ELF -> new ElfKingdomFactory();
|
||||
case ORC -> new OrcKingdomFactory();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
var app = new App();
|
||||
public static void main(String[] args) {
|
||||
var app = new App();
|
||||
|
||||
LOGGER.info("Elf Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||
LOGGER.info(app.getArmy().getDescription());
|
||||
LOGGER.info(app.getCastle().getDescription());
|
||||
LOGGER.info(app.getKing().getDescription());
|
||||
LOGGER.info("Elf Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ELF));
|
||||
LOGGER.info(app.getArmy().getDescription());
|
||||
LOGGER.info(app.getCastle().getDescription());
|
||||
LOGGER.info(app.getKing().getDescription());
|
||||
|
||||
LOGGER.info("Orc Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||
--similar use of the orc factory
|
||||
}
|
||||
LOGGER.info("Orc Kingdom");
|
||||
app.createKingdom(FactoryMaker.makeFactory(KingdomType.ORC));
|
||||
--similar use of the orc factory
|
||||
}
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Abstract Factory pattern when
|
||||
@@ -185,7 +203,8 @@ Use the Abstract Factory pattern when
|
||||
* The system should be independent of how its products are created, composed, and represented
|
||||
* The system should be configured with one of the multiple families of products
|
||||
* The family of related product objects is designed to be used together, and you need to enforce this constraint
|
||||
* You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations
|
||||
* You want to provide a class library of products, and you want to reveal just their interfaces, not their
|
||||
implementations
|
||||
* The lifetime of the dependency is conceptually shorter than the lifetime of the consumer.
|
||||
* You need a run-time value to construct a particular dependency
|
||||
* You want to decide which product to call from a family at runtime.
|
||||
@@ -193,9 +212,10 @@ Use the Abstract Factory pattern when
|
||||
* When you need consistency among products
|
||||
* You don’t want to change existing code when adding new products or families of products to the program.
|
||||
|
||||
Example use cases
|
||||
Example use cases
|
||||
|
||||
* Selecting to call to the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or NetworkAcmeService at runtime.
|
||||
* Selecting to call to the appropriate implementation of FileSystemAcmeService or DatabaseAcmeService or
|
||||
NetworkAcmeService at runtime.
|
||||
* Unit test case writing becomes much easier
|
||||
* UI tools for different OS
|
||||
|
||||
@@ -219,7 +239,7 @@ Trade-offs
|
||||
|
||||
## Tutorials
|
||||
|
||||
* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java)
|
||||
* [Abstract Factory Pattern Tutorial](https://www.journaldev.com/1418/abstract-factory-design-pattern-in-java)
|
||||
* [Refactoring Guru - Abstract Factory](https://refactoring.guru/design-patterns/abstract-factory)
|
||||
|
||||
## Known uses
|
||||
|
||||
Reference in new issue
Block a user