mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-14 12:58:37 +00:00
docs: update multiton
This commit is contained in:
+60
-61
@@ -3,34 +3,32 @@ title: Multiton
|
||||
category: Creational
|
||||
language: en
|
||||
tag:
|
||||
- Instantiation
|
||||
- Decoupling
|
||||
- Instantiation
|
||||
- Object composition
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
Registry
|
||||
* Registry of Singletons
|
||||
|
||||
## Intent
|
||||
|
||||
Ensure a class only has a limited number of instances and provide a global point of access to them.
|
||||
The Multiton pattern is a variation of the Singleton design pattern that manages a map of named instances as key-value pairs.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real-world example
|
||||
|
||||
> The Nazgûl, also called ringwraiths or the Nine Riders, are Sauron's most terrible servants. By
|
||||
> definition, there's always nine of them.
|
||||
> The Nazgûl, also called ringwraiths or the Nine Riders, are Sauron's most terrible servants. By definition, there's always nine of them.
|
||||
|
||||
In plain words
|
||||
|
||||
> Multiton pattern ensures there are a predefined amount of instances available globally.
|
||||
> Multiton pattern ensures there are a predefined amount of instances available globally.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> In software engineering, the multiton pattern is a design pattern which generalizes the singleton
|
||||
> pattern. Whereas the singleton allows only one instance of a class to be created, the multiton
|
||||
> pattern allows for the controlled creation of multiple instances, which it manages through the use
|
||||
> of a map.
|
||||
> In software engineering, the multiton pattern is a design pattern which generalizes the singleton pattern. Whereas the singleton allows only one instance of a class to be created, the multiton pattern allows for the controlled creation of multiple instances, which it manages through the use of a map.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
@@ -39,46 +37,42 @@ Wikipedia says
|
||||
```java
|
||||
public enum NazgulName {
|
||||
|
||||
KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA
|
||||
KHAMUL, MURAZOR, DWAR, JI_INDUR, AKHORAHIL, HOARMURATH, ADUNAPHEL, REN, UVATHA
|
||||
}
|
||||
|
||||
public final class Nazgul {
|
||||
|
||||
private static final Map<NazgulName, Nazgul> nazguls;
|
||||
private static final Map<NazgulName, Nazgul> nazguls;
|
||||
|
||||
private final NazgulName name;
|
||||
@Getter
|
||||
private final NazgulName name;
|
||||
|
||||
static {
|
||||
nazguls = new ConcurrentHashMap<>();
|
||||
nazguls.put(NazgulName.KHAMUL, new Nazgul(NazgulName.KHAMUL));
|
||||
nazguls.put(NazgulName.MURAZOR, new Nazgul(NazgulName.MURAZOR));
|
||||
nazguls.put(NazgulName.DWAR, new Nazgul(NazgulName.DWAR));
|
||||
nazguls.put(NazgulName.JI_INDUR, new Nazgul(NazgulName.JI_INDUR));
|
||||
nazguls.put(NazgulName.AKHORAHIL, new Nazgul(NazgulName.AKHORAHIL));
|
||||
nazguls.put(NazgulName.HOARMURATH, new Nazgul(NazgulName.HOARMURATH));
|
||||
nazguls.put(NazgulName.ADUNAPHEL, new Nazgul(NazgulName.ADUNAPHEL));
|
||||
nazguls.put(NazgulName.REN, new Nazgul(NazgulName.REN));
|
||||
nazguls.put(NazgulName.UVATHA, new Nazgul(NazgulName.UVATHA));
|
||||
}
|
||||
static {
|
||||
nazguls = new ConcurrentHashMap<>();
|
||||
nazguls.put(NazgulName.KHAMUL, new Nazgul(NazgulName.KHAMUL));
|
||||
nazguls.put(NazgulName.MURAZOR, new Nazgul(NazgulName.MURAZOR));
|
||||
nazguls.put(NazgulName.DWAR, new Nazgul(NazgulName.DWAR));
|
||||
nazguls.put(NazgulName.JI_INDUR, new Nazgul(NazgulName.JI_INDUR));
|
||||
nazguls.put(NazgulName.AKHORAHIL, new Nazgul(NazgulName.AKHORAHIL));
|
||||
nazguls.put(NazgulName.HOARMURATH, new Nazgul(NazgulName.HOARMURATH));
|
||||
nazguls.put(NazgulName.ADUNAPHEL, new Nazgul(NazgulName.ADUNAPHEL));
|
||||
nazguls.put(NazgulName.REN, new Nazgul(NazgulName.REN));
|
||||
nazguls.put(NazgulName.UVATHA, new Nazgul(NazgulName.UVATHA));
|
||||
}
|
||||
|
||||
private Nazgul(NazgulName name) {
|
||||
this.name = name;
|
||||
}
|
||||
private Nazgul(NazgulName name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static Nazgul getInstance(NazgulName name) {
|
||||
return nazguls.get(name);
|
||||
}
|
||||
|
||||
public NazgulName getName() {
|
||||
return name;
|
||||
}
|
||||
public static Nazgul getInstance(NazgulName name) {
|
||||
return nazguls.get(name);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And here's how we access the `Nazgul` instances.
|
||||
|
||||
```java
|
||||
// eagerly initialized multiton
|
||||
LOGGER.info("Printing out eagerly initialized multiton contents");
|
||||
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
|
||||
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
|
||||
@@ -89,18 +83,6 @@ LOGGER.info("HOARMURATH={}", Nazgul.getInstance(NazgulName.HOARMURATH));
|
||||
LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL));
|
||||
LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN));
|
||||
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
|
||||
|
||||
// enum multiton
|
||||
LOGGER.info("Printing out enum-based multiton contents");
|
||||
LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL);
|
||||
LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR);
|
||||
LOGGER.info("DWAR={}", NazgulEnum.DWAR);
|
||||
LOGGER.info("JI_INDUR={}", NazgulEnum.JI_INDUR);
|
||||
LOGGER.info("AKHORAHIL={}", NazgulEnum.AKHORAHIL);
|
||||
LOGGER.info("HOARMURATH={}", NazgulEnum.HOARMURATH);
|
||||
LOGGER.info("ADUNAPHEL={}", NazgulEnum.ADUNAPHEL);
|
||||
LOGGER.info("REN={}", NazgulEnum.REN);
|
||||
LOGGER.info("UVATHA={}", NazgulEnum.UVATHA);
|
||||
```
|
||||
|
||||
Program output:
|
||||
@@ -116,25 +98,42 @@ Program output:
|
||||
20:35:07.419 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=com.iluwatar.multiton.Nazgul@77556fd
|
||||
20:35:07.419 [main] INFO com.iluwatar.multiton.App - REN=com.iluwatar.multiton.Nazgul@368239c8
|
||||
20:35:07.420 [main] INFO com.iluwatar.multiton.App - UVATHA=com.iluwatar.multiton.Nazgul@9e89d68
|
||||
20:35:07.420 [main] INFO com.iluwatar.multiton.App - Printing out enum-based multiton contents
|
||||
20:35:07.420 [main] INFO com.iluwatar.multiton.App - KHAMUL=KHAMUL
|
||||
20:35:07.420 [main] INFO com.iluwatar.multiton.App - MURAZOR=MURAZOR
|
||||
20:35:07.420 [main] INFO com.iluwatar.multiton.App - DWAR=DWAR
|
||||
20:35:07.420 [main] INFO com.iluwatar.multiton.App - JI_INDUR=JI_INDUR
|
||||
20:35:07.421 [main] INFO com.iluwatar.multiton.App - AKHORAHIL=AKHORAHIL
|
||||
20:35:07.421 [main] INFO com.iluwatar.multiton.App - HOARMURATH=HOARMURATH
|
||||
20:35:07.421 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=ADUNAPHEL
|
||||
20:35:07.421 [main] INFO com.iluwatar.multiton.App - REN=REN
|
||||
20:35:07.421 [main] INFO com.iluwatar.multiton.App - UVATHA=UVATHA
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Multiton pattern when
|
||||
|
||||
* There must be a specific number of instances of a class, and they must be accessible to clients from
|
||||
a well-known access point.
|
||||
* A class must have named instances, but only one instance for each unique key.
|
||||
* Global access to these instances is necessary without requiring global variables.
|
||||
* You want to manage shared resources categorized by key.
|
||||
|
||||
## Known Uses
|
||||
|
||||
* Managing database connections in different contexts.
|
||||
* Configuration settings for different environments in an application.
|
||||
|
||||
## Consequences
|
||||
|
||||
Benefits:
|
||||
|
||||
* Ensures controlled access to instances based on key.
|
||||
* Reduces global state usage by encapsulating instance management within the pattern.
|
||||
|
||||
Trade-offs:
|
||||
|
||||
* Increased memory usage if not managed properly due to multiple instances.
|
||||
* Potential issues with concurrency if not implemented with thread safety in mind.
|
||||
|
||||
## Related Patterns
|
||||
|
||||
[Singleton](https://java-design-patterns.com/patterns/singleton/): Multiton can be seen as an extension of the Singleton pattern where Singleton allows only one instance of a class, Multiton allows one instance per key.
|
||||
[Factory Method](https://java-design-patterns.com/patterns/factory-method/): Multiton uses a method to create or retrieve instances, similar to how a Factory Method controls object creation.
|
||||
|
||||
## Credits
|
||||
|
||||
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
|
||||
|
||||
@@ -32,7 +32,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* the Multiton by passing an enumeration as a parameter.
|
||||
*
|
||||
* <p>There is more than one way to implement the multiton design pattern. In the first example
|
||||
* {@link Nazgul} is the Multiton and we can ask single {@link Nazgul} from it using {@link
|
||||
* {@link Nazgul} is the Multiton, and we can ask single {@link Nazgul} from it using {@link
|
||||
* NazgulName}. The {@link Nazgul}s are statically initialized and stored in a concurrent hash map.
|
||||
*
|
||||
* <p>In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable
|
||||
|
||||
@@ -26,6 +26,7 @@ package com.iluwatar.multiton;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Nazgul is a Multiton class. Nazgul instances can be queried using {@link #getInstance} method.
|
||||
@@ -34,6 +35,7 @@ public final class Nazgul {
|
||||
|
||||
private static final Map<NazgulName, Nazgul> nazguls;
|
||||
|
||||
@Getter
|
||||
private final NazgulName name;
|
||||
|
||||
static {
|
||||
@@ -56,8 +58,4 @@ public final class Nazgul {
|
||||
public static Nazgul getInstance(NazgulName name) {
|
||||
return nazguls.get(name);
|
||||
}
|
||||
|
||||
public NazgulName getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user