Skip to content

Commit

Permalink
refactoring: execute around idiom (iluwatar#1945)
Browse files Browse the repository at this point in the history
* Refactor execute around the idiom

* fix checkstyle errors

Co-authored-by: Subhrodip Mohanta <[email protected]>
  • Loading branch information
iluwatar and ohbus authored Jan 10, 2022
1 parent c549218 commit 07ee94d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 24 deletions.
54 changes: 34 additions & 20 deletions execute-around/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ the user to specify only what to do with the resource.

## 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
> the user we let our service class open and close the file automatically, the user only has to
> A class needs to be provided for writing text strings to files. To make it easy for
> the user, the service class opens and closes the file automatically. The user only has to
> specify what is written into which file.
In plain words
Expand All @@ -35,35 +35,50 @@ In plain words
**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
@FunctionalInterface
public interface FileWriterAction {

void writeFile(FileWriter writer) throws IOException;

}

@Slf4j
public class SimpleFileWriter {

public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
try (var writer = new FileWriter(filename)) {
action.writeFile(writer);
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
LOGGER.info("Opening the file");
try (var writer = new FileWriter(filename)) {
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
FileWriterAction writeHello = writer -> {
writer.write("Hello");
writer.append(" ");
writer.append("there!");
};
new SimpleFileWriter("testfile.txt", writeHello);
FileWriterAction writeHello = writer -> {
writer.write("Gandalf was here");
};
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
Expand All @@ -74,8 +89,7 @@ To utilize the file writer the following code is needed.

Use the Execute Around idiom when

* You use an API that requires methods to be called in pairs such as open/close or
allocate/deallocate.
* An API requires methods to be called in pairs such as open/close or allocate/deallocate.

## Credits

Expand Down
18 changes: 14 additions & 4 deletions execute-around/src/main/java/com/iluwatar/execute/around/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,39 @@

package com.iluwatar.execute.around;

import java.io.File;
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
* allocation/deallocation or lock acquisition/release.
*
* <p>In this example, we have {@link SimpleFileWriter} class that opens and closes the file for
* the user. The user specifies only what to do with the file by providing the {@link
* FileWriterAction} implementation.
*/
@Slf4j
public class App {

/**
* Program entry point.
*/
public static void main(String[] args) throws IOException {

// create the file writer and execute the custom action
FileWriterAction writeHello = writer -> {
writer.write("Hello");
writer.append(" ");
writer.append("there!");
writer.write("Gandalf was here");
};
new SimpleFileWriter("testfile.txt", writeHello);

// print the file contents
var scanner = new Scanner(new File("testfile.txt"));
while (scanner.hasNextLine()) {
LOGGER.info(scanner.nextLine());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,24 @@
import java.io.FileWriter;
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
* to do with the file resource through {@link FileWriterAction} parameter.
*/
@Slf4j
public class SimpleFileWriter {

/**
* Constructor.
*/
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
LOGGER.info("Opening the file");
try (var writer = new FileWriter(filename)) {
LOGGER.info("Executing the action");
action.writeFile(writer);
LOGGER.info("Closing the file");
}
}
}

0 comments on commit 07ee94d

Please sign in to comment.