Compare commits
2 Commits
executeAro
...
multitonUp
Author | SHA1 | Date | |
---|---|---|---|
58b7d0115b | |||
07ee94d671 |
@ -17,10 +17,10 @@ the user to specify only what to do with the resource.
|
|||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real-world example
|
||||||
|
|
||||||
> We need to provide a class that can be used to write text strings to files. To make it easy for
|
> A class needs to be provided for writing text strings to files. To make it easy for
|
||||||
> the user we let our service class open and close the file automatically, the user only has to
|
> the user, the service class opens and closes the file automatically. The user only has to
|
||||||
> specify what is written into which file.
|
> specify what is written into which file.
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
@ -35,35 +35,50 @@ In plain words
|
|||||||
|
|
||||||
**Programmatic Example**
|
**Programmatic Example**
|
||||||
|
|
||||||
Let's introduce our file writer class.
|
`SimpleFileWriter` class implements the Execute Around idiom. It takes `FileWriterAction` as a
|
||||||
|
constructor argument allowing the user to specify what gets written into the file.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface FileWriterAction {
|
public interface FileWriterAction {
|
||||||
|
|
||||||
void writeFile(FileWriter writer) throws IOException;
|
void writeFile(FileWriter writer) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class SimpleFileWriter {
|
public class SimpleFileWriter {
|
||||||
|
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
|
||||||
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
|
LOGGER.info("Opening the file");
|
||||||
try (var writer = new FileWriter(filename)) {
|
try (var writer = new FileWriter(filename)) {
|
||||||
action.writeFile(writer);
|
LOGGER.info("Executing the action");
|
||||||
|
action.writeFile(writer);
|
||||||
|
LOGGER.info("Closing the file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
To utilize the file writer the following code is needed.
|
The following code demonstrates how `SimpleFileWriter` is used. `Scanner` is used to print the file
|
||||||
|
contents after the writing finishes.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
FileWriterAction writeHello = writer -> {
|
FileWriterAction writeHello = writer -> {
|
||||||
writer.write("Hello");
|
writer.write("Gandalf was here");
|
||||||
writer.append(" ");
|
};
|
||||||
writer.append("there!");
|
new SimpleFileWriter("testfile.txt", writeHello);
|
||||||
};
|
|
||||||
new SimpleFileWriter("testfile.txt", writeHello);
|
var scanner = new Scanner(new File("testfile.txt"));
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
LOGGER.info(scanner.nextLine());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's the console output.
|
||||||
|
|
||||||
|
```
|
||||||
|
21:18:07.185 [main] INFO com.iluwatar.execute.around.SimpleFileWriter - Opening the file
|
||||||
|
21:18:07.188 [main] INFO com.iluwatar.execute.around.SimpleFileWriter - Executing the action
|
||||||
|
21:18:07.189 [main] INFO com.iluwatar.execute.around.SimpleFileWriter - Closing the file
|
||||||
|
21:18:07.199 [main] INFO com.iluwatar.execute.around.App - Gandalf was here
|
||||||
```
|
```
|
||||||
|
|
||||||
## Class diagram
|
## Class diagram
|
||||||
@ -74,8 +89,7 @@ To utilize the file writer the following code is needed.
|
|||||||
|
|
||||||
Use the Execute Around idiom when
|
Use the Execute Around idiom when
|
||||||
|
|
||||||
* You use an API that requires methods to be called in pairs such as open/close or
|
* An API requires methods to be called in pairs such as open/close or allocate/deallocate.
|
||||||
allocate/deallocate.
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
@ -23,10 +23,14 @@
|
|||||||
|
|
||||||
package com.iluwatar.execute.around;
|
package com.iluwatar.execute.around;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Execute Around idiom specifies some code to be executed before and after a method. Typically
|
* The Execute Around idiom specifies executable code before and after a method. Typically
|
||||||
* the idiom is used when the API has methods to be executed in pairs, such as resource
|
* the idiom is used when the API has methods to be executed in pairs, such as resource
|
||||||
* allocation/deallocation or lock acquisition/release.
|
* allocation/deallocation or lock acquisition/release.
|
||||||
*
|
*
|
||||||
@ -34,6 +38,7 @@ import java.io.IOException;
|
|||||||
* the user. The user specifies only what to do with the file by providing the {@link
|
* the user. The user specifies only what to do with the file by providing the {@link
|
||||||
* FileWriterAction} implementation.
|
* FileWriterAction} implementation.
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,11 +46,16 @@ public class App {
|
|||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
|
// create the file writer and execute the custom action
|
||||||
FileWriterAction writeHello = writer -> {
|
FileWriterAction writeHello = writer -> {
|
||||||
writer.write("Hello");
|
writer.write("Gandalf was here");
|
||||||
writer.append(" ");
|
|
||||||
writer.append("there!");
|
|
||||||
};
|
};
|
||||||
new SimpleFileWriter("testfile.txt", writeHello);
|
new SimpleFileWriter("testfile.txt", writeHello);
|
||||||
|
|
||||||
|
// print the file contents
|
||||||
|
var scanner = new Scanner(new File("testfile.txt"));
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
LOGGER.info(scanner.nextLine());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,24 @@ package com.iluwatar.execute.around;
|
|||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SimpleFileWriter handles opening and closing file for the user. The user only has to specify what
|
* SimpleFileWriter handles opening and closing file for the user. The user only has to specify what
|
||||||
* to do with the file resource through {@link FileWriterAction} parameter.
|
* to do with the file resource through {@link FileWriterAction} parameter.
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class SimpleFileWriter {
|
public class SimpleFileWriter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
|
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
|
||||||
|
LOGGER.info("Opening the file");
|
||||||
try (var writer = new FileWriter(filename)) {
|
try (var writer = new FileWriter(filename)) {
|
||||||
|
LOGGER.info("Executing the action");
|
||||||
action.writeFile(writer);
|
action.writeFile(writer);
|
||||||
|
LOGGER.info("Closing the file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,18 @@ Registry
|
|||||||
|
|
||||||
## Intent
|
## Intent
|
||||||
|
|
||||||
Ensure a class only has limited number of instances and provide a global point of access to them.
|
Ensure a class only has a limited number of instances and provide a global point of access to them.
|
||||||
|
|
||||||
## Explanation
|
## Explanation
|
||||||
|
|
||||||
Real world example
|
Real-world example
|
||||||
|
|
||||||
> The Nazgûl, also called ringwraiths or the Nine Riders, are Sauron's most terrible servants. By
|
> The Nazgûl, also called ringwraiths or the Nine Riders, are Sauron's most terrible servants. By
|
||||||
> definition there's always nine of them.
|
> definition, there's always nine of them.
|
||||||
|
|
||||||
In plain words
|
In plain words
|
||||||
|
|
||||||
> Multiton pattern ensures there's predefined amount of instances available globally.
|
> Multiton pattern ensures there are a predefined amount of instances available globally.
|
||||||
|
|
||||||
Wikipedia says
|
Wikipedia says
|
||||||
|
|
||||||
@ -81,29 +81,54 @@ public final class Nazgul {
|
|||||||
And here's how we access the `Nazgul` instances.
|
And here's how we access the `Nazgul` instances.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
|
// eagerly initialized multiton
|
||||||
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
|
LOGGER.info("Printing out eagerly initialized multiton contents");
|
||||||
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
|
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
|
||||||
LOGGER.info("JI_INDUR={}", Nazgul.getInstance(NazgulName.JI_INDUR));
|
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
|
||||||
LOGGER.info("AKHORAHIL={}", Nazgul.getInstance(NazgulName.AKHORAHIL));
|
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
|
||||||
LOGGER.info("HOARMURATH={}", Nazgul.getInstance(NazgulName.HOARMURATH));
|
LOGGER.info("JI_INDUR={}", Nazgul.getInstance(NazgulName.JI_INDUR));
|
||||||
LOGGER.info("ADUNAPHEL={}", Nazgul.getInstance(NazgulName.ADUNAPHEL));
|
LOGGER.info("AKHORAHIL={}", Nazgul.getInstance(NazgulName.AKHORAHIL));
|
||||||
LOGGER.info("REN={}", Nazgul.getInstance(NazgulName.REN));
|
LOGGER.info("HOARMURATH={}", Nazgul.getInstance(NazgulName.HOARMURATH));
|
||||||
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
|
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:
|
Program output:
|
||||||
|
|
||||||
```
|
```
|
||||||
KHAMUL=com.iluwatar.multiton.Nazgul@2b214b94
|
20:35:07.413 [main] INFO com.iluwatar.multiton.App - Printing out eagerly initialized multiton contents
|
||||||
MURAZOR=com.iluwatar.multiton.Nazgul@17814b1c
|
20:35:07.417 [main] INFO com.iluwatar.multiton.App - KHAMUL=com.iluwatar.multiton.Nazgul@48cf768c
|
||||||
DWAR=com.iluwatar.multiton.Nazgul@7ac9af2a
|
20:35:07.419 [main] INFO com.iluwatar.multiton.App - MURAZOR=com.iluwatar.multiton.Nazgul@7960847b
|
||||||
JI_INDUR=com.iluwatar.multiton.Nazgul@7bb004b8
|
20:35:07.419 [main] INFO com.iluwatar.multiton.App - DWAR=com.iluwatar.multiton.Nazgul@6a6824be
|
||||||
AKHORAHIL=com.iluwatar.multiton.Nazgul@78e89bfe
|
20:35:07.419 [main] INFO com.iluwatar.multiton.App - JI_INDUR=com.iluwatar.multiton.Nazgul@5c8da962
|
||||||
HOARMURATH=com.iluwatar.multiton.Nazgul@652ce654
|
20:35:07.419 [main] INFO com.iluwatar.multiton.App - AKHORAHIL=com.iluwatar.multiton.Nazgul@512ddf17
|
||||||
ADUNAPHEL=com.iluwatar.multiton.Nazgul@522ba524
|
20:35:07.419 [main] INFO com.iluwatar.multiton.App - HOARMURATH=com.iluwatar.multiton.Nazgul@2c13da15
|
||||||
REN=com.iluwatar.multiton.Nazgul@29c5ee1d
|
20:35:07.419 [main] INFO com.iluwatar.multiton.App - ADUNAPHEL=com.iluwatar.multiton.Nazgul@77556fd
|
||||||
UVATHA=com.iluwatar.multiton.Nazgul@15cea7b0
|
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
|
## Class diagram
|
||||||
@ -114,5 +139,5 @@ UVATHA=com.iluwatar.multiton.Nazgul@15cea7b0
|
|||||||
|
|
||||||
Use the Multiton pattern when
|
Use the Multiton pattern when
|
||||||
|
|
||||||
* There must be specific number of instances of a class, and they must be accessible to clients from
|
* 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 well-known access point.
|
||||||
|
@ -26,13 +26,13 @@ package com.iluwatar.multiton;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whereas Singleton design pattern introduces single globally accessible object the Multiton
|
* Whereas Singleton design pattern introduces single globally accessible object, the Multiton
|
||||||
* pattern defines many globally accessible objects. The client asks for the correct instance from
|
* pattern defines many globally accessible objects. The client asks for the correct instance from
|
||||||
* the Multiton by passing an enumeration as parameter.
|
* 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
|
* <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 concurrent hash map.
|
* 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
|
* <p>In the enum implementation {@link NazgulEnum} is the multiton. It is static and mutable
|
||||||
* because of the way java supports enums.
|
* because of the way java supports enums.
|
||||||
@ -47,6 +47,7 @@ public class App {
|
|||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// eagerly initialized multiton
|
// eagerly initialized multiton
|
||||||
|
LOGGER.info("Printing out eagerly initialized multiton contents");
|
||||||
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
|
LOGGER.info("KHAMUL={}", Nazgul.getInstance(NazgulName.KHAMUL));
|
||||||
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
|
LOGGER.info("MURAZOR={}", Nazgul.getInstance(NazgulName.MURAZOR));
|
||||||
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
|
LOGGER.info("DWAR={}", Nazgul.getInstance(NazgulName.DWAR));
|
||||||
@ -58,6 +59,7 @@ public class App {
|
|||||||
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
|
LOGGER.info("UVATHA={}", Nazgul.getInstance(NazgulName.UVATHA));
|
||||||
|
|
||||||
// enum multiton
|
// enum multiton
|
||||||
|
LOGGER.info("Printing out enum-based multiton contents");
|
||||||
LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL);
|
LOGGER.info("KHAMUL={}", NazgulEnum.KHAMUL);
|
||||||
LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR);
|
LOGGER.info("MURAZOR={}", NazgulEnum.MURAZOR);
|
||||||
LOGGER.info("DWAR={}", NazgulEnum.DWAR);
|
LOGGER.info("DWAR={}", NazgulEnum.DWAR);
|
||||||
|
@ -48,5 +48,4 @@ public class NazgulTest {
|
|||||||
assertEquals(name, nazgul.getName());
|
assertEquals(name, nazgul.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user