Skip to content

Commit 4359e00

Browse files
committed
feat: add factory enum
1 parent ede37bd commit 4359e00

File tree

13 files changed

+536
-0
lines changed

13 files changed

+536
-0
lines changed

factory-enum/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
---
2+
title: "Factory Enum Pattern in Java: Simplifying Object Access"
3+
shortTitle: Factory Enum
4+
description: "Learn the Factory Enum Pattern in Java using practical examples. Understand how to use enums to manage object instantiation in a clean, scalable, and singleton-safe way."
5+
category: Creational
6+
language: en
7+
tag:
8+
- Abstraction
9+
- Enum Singleton
10+
- Gang of Four
11+
- Factory Pattern
12+
- Object Instantiation
13+
---
14+
15+
## Intent of Factory Enum Pattern
16+
17+
The **Factory Enum Pattern** is a creational pattern that leverages Java's `enum` type to manage object instantiation. It provides a centralized, type-safe, and singleton-friendly way to access various implementations of a common interface.
18+
19+
This pattern is ideal when the set of possible objects is known and fixed (e.g., file processors, coin types, document types).
20+
21+
## Real-World Analogy
22+
23+
> Imagine a toolbox where each tool has a fixed slot. You don’t create a new tool each time — you just access the correct one from the right compartment. Similarly, with Factory Enum, each `enum` constant maps to a specific object instance that can be reused or constructed once.
24+
25+
## Programmatic Example Using FileProcessor
26+
27+
In this example, we want to process different file types: Excel and PDF. Each processor implements the `FileProcessor` interface.
28+
29+
### FileProcessor Interface
30+
31+
```java
32+
public interface FileProcessor {
33+
String getDescription();
34+
}
35+
```
36+
Implementations
37+
```java
38+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
39+
public class ExcelProcessor implements FileProcessor {
40+
41+
static final String DESCRIPTION = "This is an Excel processor.";
42+
43+
@Override
44+
public String getDescription() {
45+
return DESCRIPTION;
46+
}
47+
48+
public static class InstanceHolder {
49+
public static final ExcelProcessor INSTANCE = new ExcelProcessor();
50+
}
51+
}
52+
```
53+
```java
54+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
55+
public class PDFProcessor implements FileProcessor {
56+
57+
static final String DESCRIPTION = "This is a PDF processor.";
58+
59+
@Override
60+
public String getDescription() {
61+
return DESCRIPTION;
62+
}
63+
64+
public static class InstanceHolder {
65+
public static final PDFProcessor INSTANCE = new PDFProcessor();
66+
}
67+
}
68+
```
69+
Factory Enum: FileProcessorType
70+
```java
71+
@RequiredArgsConstructor
72+
@Getter
73+
public enum FileProcessorType {
74+
EXCEL(ExcelProcessor.InstanceHolder.INSTANCE),
75+
PDF(PDFProcessor.InstanceHolder.INSTANCE);
76+
77+
private final FileProcessor instance;
78+
}
79+
```
80+
Client Code
81+
```java
82+
public static void main(String[] args) {
83+
LOGGER.info("Start processing files.");
84+
var excel = FileProcessorType.EXCEL.getInstance();
85+
var pdf = FileProcessorType.PDF.getInstance();
86+
LOGGER.info(excel.getDescription());
87+
LOGGER.info(pdf.getDescription());
88+
}
89+
```
90+
Output
91+
```
92+
INFO: Start processing files.
93+
INFO: This is an Excel processor.
94+
INFO: This is a PDF processor.
95+
```
96+
## When to Use the Factory Enum Pattern
97+
98+
* When object types are known in advance and won't change frequently.
99+
100+
* When you want singleton instances per type.
101+
102+
* To avoid traditional factory classes and keep the logic self-contained within an enum.
103+
104+
* When readability and simplicity are preferred over extensibility.
105+
106+
## Benefits
107+
* Type-safe and readable – enum provides compiler-checked safety.
108+
* Singleton-friendly – each instance is created once and reused.
109+
* No need for external factory class – the enum holds both the type and instance.
110+
* Thread-safe by nature of enum and static holders.
111+
112+
## Trade-offs
113+
* Not suitable for dynamic or extensible object types.
114+
* Violates the Open/Closed Principle if new types are added frequently.
115+
* Slightly unconventional compared to traditional Factory pattern.
116+
117+
## Related Patterns
118+
* [Traditional Factory Method](https://java-design-patterns.com/patterns/factory/): Separates creation logic into a factory class.
119+
* [Enum Singleton](https://www.baeldung.com/java-singleton#enum-singleton): Ensures one instance per type via enum.
120+
* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): Can be considered a kind of Factory that works with groups of products.
121+
* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): If you combine enum with lookup behavior.
122+
123+
## References and Credits
124+
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0Rk5y)
125+
* [Effective Java](https://amzn.to/4cGk2Jz)
126+
* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/3UpTLrG)
28.8 KB
Loading

factory-enum/etc/factory.urm.png

43.8 KB
Loading

factory-enum/etc/factory.urm.puml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
@startuml
2+
package com.iluwatar.factory {
3+
4+
class App {
5+
- LOGGER : Logger {static}
6+
+ App()
7+
+ main(args : String[]) {static}
8+
}
9+
10+
interface FileProcessor {
11+
+ getDescription() : String {abstract}
12+
}
13+
14+
enum FileProcessorType {
15+
+ EXCEL {static}
16+
+ PDF {static}
17+
- instance : FileProcessor
18+
+ getInstance() : FileProcessor
19+
+ valueOf(name : String) : FileProcessorType {static}
20+
+ values() : FileProcessorType[] {static}
21+
}
22+
23+
class ExcelProcessor {
24+
~ DESCRIPTION : String {static}
25+
+ ExcelProcessor()
26+
+ getDescription() : String
27+
}
28+
29+
class PDFProcessor {
30+
~ DESCRIPTION : String {static}
31+
+ PDFProcessor()
32+
+ getDescription() : String
33+
}
34+
}
35+
36+
ExcelProcessor ..|> FileProcessor
37+
PDFProcessor ..|> FileProcessor
38+
@enduml

factory-enum/pom.xml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
5+
6+
The MIT License
7+
Copyright © 2014-2022 Ilkka Seppälä
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
-->
28+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
29+
<modelVersion>4.0.0</modelVersion>
30+
<parent>
31+
<groupId>com.iluwatar</groupId>
32+
<artifactId>java-design-patterns</artifactId>
33+
<version>1.26.0-SNAPSHOT</version>
34+
</parent>
35+
<artifactId>factory-enum</artifactId>
36+
<dependencies>
37+
<dependency>
38+
<groupId>org.slf4j</groupId>
39+
<artifactId>slf4j-api</artifactId>
40+
</dependency>
41+
<dependency>
42+
<groupId>ch.qos.logback</groupId>
43+
<artifactId>logback-classic</artifactId>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.junit.jupiter</groupId>
47+
<artifactId>junit-jupiter-engine</artifactId>
48+
<scope>test</scope>
49+
</dependency>
50+
</dependencies>
51+
<build>
52+
<plugins>
53+
<!-- Maven assembly plugin is invoked with default setting which we have
54+
in parent pom and specifying the class having main method -->
55+
<plugin>
56+
<groupId>org.apache.maven.plugins</groupId>
57+
<artifactId>maven-assembly-plugin</artifactId>
58+
<executions>
59+
<execution>
60+
<configuration>
61+
<archive>
62+
<manifest>
63+
<mainClass>com.iluwatar.factory.App</mainClass>
64+
</manifest>
65+
</archive>
66+
</configuration>
67+
</execution>
68+
</executions>
69+
</plugin>
70+
</plugins>
71+
</build>
72+
</project>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3+
*
4+
* The MIT License
5+
* Copyright © 2014-2022 Ilkka Seppälä
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package com.iluwatar.factory;
26+
27+
import lombok.extern.slf4j.Slf4j;
28+
29+
/**
30+
* The Factory Enum Pattern is a creational design pattern that leverages Java enums to encapsulate
31+
* the creation logic of different object types. It promotes cleaner code by removing the need for
32+
* separate factory classes and centralizing instantiation within type-safe enum constants.
33+
*
34+
* <p>In this example, different file processors (Excel, PDF) implement the same interface. The
35+
* FileProcessorType enum holds the corresponding instance for each processor, allowing the client
36+
* code to retrieve them in a clean and consistent way.
37+
*/
38+
@Slf4j
39+
public class App {
40+
41+
/** Program main entry point. */
42+
public static void main(String[] args) {
43+
LOGGER.info("The alchemist begins his work.");
44+
var excelProcessor = FileProcessorType.EXCEL.getInstance();
45+
var pdfProcessor = FileProcessorType.PDF.getInstance();
46+
LOGGER.info(excelProcessor.getDescription());
47+
LOGGER.info(pdfProcessor.getDescription());
48+
}
49+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3+
*
4+
* The MIT License
5+
* Copyright © 2014-2022 Ilkka Seppälä
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package com.iluwatar.factory;
26+
27+
import lombok.AccessLevel;
28+
import lombok.NoArgsConstructor;
29+
30+
/** ExcelProcessor implementation. */
31+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
32+
public class ExcelProcessor implements FileProcessor {
33+
34+
static final String DESCRIPTION = "This is a excel processor.";
35+
36+
@Override
37+
public String getDescription() {
38+
return DESCRIPTION;
39+
}
40+
41+
public static class InstanceHolder {
42+
public static final ExcelProcessor INSTANCE = new ExcelProcessor();
43+
}
44+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3+
*
4+
* The MIT License
5+
* Copyright © 2014-2022 Ilkka Seppälä
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package com.iluwatar.factory;
26+
27+
/** FileProcessor interface. */
28+
public interface FileProcessor {
29+
30+
String getDescription();
31+
}

0 commit comments

Comments
 (0)