Skip to content

Commit c6c4e6e

Browse files
committed
Merge branch 'master' into vuepress
# Conflicts: # README.md # command/README.md
2 parents 223b779 + 801be25 commit c6c4e6e

File tree

38 files changed

+1722
-522
lines changed

38 files changed

+1722
-522
lines changed

.all-contributorsrc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,6 +1586,51 @@
15861586
"contributions": [
15871587
"code"
15881588
]
1589+
},
1590+
{
1591+
"login": "tan31989",
1592+
"name": "Nagaraj Tantri",
1593+
"avatar_url": "https://avatars.githubusercontent.com/u/3784194?v=4",
1594+
"profile": "https://stackoverflow.com/users/308565/nagaraj-tantri",
1595+
"contributions": [
1596+
"code"
1597+
]
1598+
},
1599+
{
1600+
"login": "frascu",
1601+
"name": "Francesco Scuccimarri",
1602+
"avatar_url": "https://avatars.githubusercontent.com/u/7107651?v=4",
1603+
"profile": "http://scuccimarri.it",
1604+
"contributions": [
1605+
"code"
1606+
]
1607+
},
1608+
{
1609+
"login": "Conhan93",
1610+
"name": "Conny Hansson",
1611+
"avatar_url": "https://avatars.githubusercontent.com/u/71334757?v=4",
1612+
"profile": "https://github.com/Conhan93",
1613+
"contributions": [
1614+
"doc"
1615+
]
1616+
},
1617+
{
1618+
"login": "muklasr",
1619+
"name": "Muklas Rahmanto",
1620+
"avatar_url": "https://avatars.githubusercontent.com/u/43443753?v=4",
1621+
"profile": "http://muklasr.medium.com",
1622+
"contributions": [
1623+
"translation"
1624+
]
1625+
},
1626+
{
1627+
"login": "VxDxK",
1628+
"name": "Vadim",
1629+
"avatar_url": "https://avatars.githubusercontent.com/u/38704817?v=4",
1630+
"profile": "https://github.com/VxDxK",
1631+
"contributions": [
1632+
"translation"
1633+
]
15891634
}
15901635
],
15911636
"contributorsPerLine": 4,

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
1111
[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
1212
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
13-
[![All Contributors](https://img.shields.io/badge/all_contributors-174-orange.svg?style=flat-square)](#contributors-)
13+
[![All Contributors](https://img.shields.io/badge/all_contributors-179-orange.svg?style=flat-square)](#contributors-)
1414
<!-- ALL-CONTRIBUTORS-BADGE:END -->
1515

1616
<br/>
1717

18-
Read in different language : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md)
18+
Read in different language : [**zh**](localization/zh/README.md), [**ko**](localization/ko/README.md), [**fr**](localization/fr/README.md), [**tr**](localization/tr/README.md), [**ar**](localization/ar/README.md), [**es**](localization/es/README.md), [**pt**](localization/pt/README.md), [**id**](localization/id/README.md), [**ru**](localization/ru/README.md)
1919

2020
<br/>
2121

@@ -336,6 +336,13 @@ This project is licensed under the terms of the MIT license.
336336
<tr>
337337
<td align="center"><a href="https://github.com/karthikbhat13"><img src="https://avatars.githubusercontent.com/u/22431014?v=4?s=100" width="100px;" alt=""/><br /><sub><b>karthikbhat13</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=karthikbhat13" title="Code">💻</a></td>
338338
<td align="center"><a href="https://github.com/mortezaadi"><img src="https://avatars.githubusercontent.com/u/1329687?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Morteza Adigozalpour</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=mortezaadi" title="Code">💻</a></td>
339+
<td align="center"><a href="https://stackoverflow.com/users/308565/nagaraj-tantri"><img src="https://avatars.githubusercontent.com/u/3784194?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nagaraj Tantri</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=tan31989" title="Code">💻</a></td>
340+
<td align="center"><a href="http://scuccimarri.it"><img src="https://avatars.githubusercontent.com/u/7107651?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Francesco Scuccimarri</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=frascu" title="Code">💻</a></td>
341+
</tr>
342+
<tr>
343+
<td align="center"><a href="https://github.com/Conhan93"><img src="https://avatars.githubusercontent.com/u/71334757?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Conny Hansson</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=Conhan93" title="Documentation">📖</a></td>
344+
<td align="center"><a href="http://muklasr.medium.com"><img src="https://avatars.githubusercontent.com/u/43443753?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Muklas Rahmanto</b></sub></a><br /><a href="#translation-muklasr" title="Translation">🌍</a></td>
345+
<td align="center"><a href="https://github.com/VxDxK"><img src="https://avatars.githubusercontent.com/u/38704817?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vadim</b></sub></a><br /><a href="#translation-VxDxK" title="Translation">🌍</a></td>
339346
</tr>
340347
</table>
341348

active-object/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ tags:
88

99

1010
## Intent
11-
The active object design pattern decouples method execution from method invocation for objects that each reside in their thread of control. The goal is to introduce concurrency, by using asynchronous method invocation and a scheduler for handling requests.
11+
The active object design pattern decouples method execution from method invocation for objects that each reside in their thread of control. The goal is to introduce concurrency, by using asynchronous method invocation, and a scheduler for handling requests.
1212

1313
## Explanation
1414

@@ -67,7 +67,7 @@ public abstract class ActiveCreature{
6767
requests.put(new Runnable() {
6868
@Override
6969
public void run() {
70-
logger.info("{} has started to roam and the wastelands.",name());
70+
logger.info("{} has started to roam the wastelands.",name());
7171
}
7272
}
7373
);
@@ -79,7 +79,7 @@ public abstract class ActiveCreature{
7979
}
8080
```
8181

82-
We can see that any class that will extend the ActiveCreature class will have its own thread of control to execute and invocate methods.
82+
We can see that any class that will extend the ActiveCreature class will have its own thread of control to invoke and execute methods.
8383

8484
For example, the Orc class:
8585

@@ -93,7 +93,7 @@ public class Orc extends ActiveCreature {
9393
}
9494
```
9595

96-
Now, we can create multiple creatures such as Orcs, tell them to eat and roam and they will execute it on their own thread of control:
96+
Now, we can create multiple creatures such as Orcs, tell them to eat and roam, and they will execute it on their own thread of control:
9797

9898
```java
9999
public static void main(String[] args) {

active-object/src/main/java/com/iluwatar/activeobject/ActiveCreature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public void eat() throws InterruptedException {
8282
}
8383

8484
/**
85-
* Roam in the wastelands.
85+
* Roam the wastelands.
8686
* @throws InterruptedException due to firing a new Runnable.
8787
*/
8888
public void roam() throws InterruptedException {

aggregator-microservices/aggregator-service/src/test/java/com/iluwatar/aggregator/microservices/AggregatorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class AggregatorTest {
4848

4949
@BeforeEach
5050
public void setup() {
51-
MockitoAnnotations.initMocks(this);
51+
MockitoAnnotations.openMocks(this);
5252
}
5353

5454
/**

api-gateway/api-gateway-service/src/test/java/com/iluwatar/api/gateway/ApiGatewayTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class ApiGatewayTest {
4848

4949
@BeforeEach
5050
public void setup() {
51-
MockitoAnnotations.initMocks(this);
51+
MockitoAnnotations.openMocks(this);
5252
}
5353

5454
/**

async-method-invocation/src/test/java/com/iluwatar/async/method/invocation/ThreadAsyncExecutorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class ThreadAsyncExecutorTest {
6868

6969
@BeforeEach
7070
void setUp() {
71-
MockitoAnnotations.initMocks(this);
71+
MockitoAnnotations.openMocks(this);
7272
}
7373

7474
/**

caching/README.md

Lines changed: 66 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -40,39 +40,29 @@ Wikipedia says:
4040
**Programmatic Example**
4141

4242
Let's first look at the data layer of our application. The interesting classes are `UserAccount`
43-
which is a simple Java object containing the user account details, and `DbManager` which handles
44-
reading and writing of these objects to/from MongoDB database.
43+
which is a simple Java object containing the user account details, and `DbManager` interface which handles
44+
reading and writing of these objects to/from database.
4545

4646
```java
47-
@Setter
48-
@Getter
47+
@Data
4948
@AllArgsConstructor
5049
@ToString
50+
@EqualsAndHashCode
5151
public class UserAccount {
5252
private String userId;
5353
private String userName;
5454
private String additionalInfo;
5555
}
5656

57-
@Slf4j
58-
public final class DbManager {
59-
60-
private static MongoClient mongoClient;
61-
private static MongoDatabase db;
62-
63-
private DbManager() { /*...*/ }
64-
65-
public static void createVirtualDb() { /*...*/ }
66-
67-
public static void connect() throws ParseException { /*...*/ }
68-
69-
public static UserAccount readFromDb(String userId) { /*...*/ }
57+
public interface DbManager {
7058

71-
public static void writeToDb(UserAccount userAccount) { /*...*/ }
72-
73-
public static void updateDb(UserAccount userAccount) { /*...*/ }
74-
75-
public static void upsertDb(UserAccount userAccount) { /*...*/ }
59+
void connect();
60+
void disconnect();
61+
62+
UserAccount readFromDb(String userId);
63+
UserAccount writeToDb(UserAccount userAccount);
64+
UserAccount updateDb(UserAccount userAccount);
65+
UserAccount upsertDb(UserAccount userAccount);
7666
}
7767
```
7868

@@ -168,30 +158,43 @@ strategies.
168158
@Slf4j
169159
public class CacheStore {
170160

161+
private static final int CAPACITY = 3;
171162
private static LruCache cache;
163+
private final DbManager dbManager;
172164

173165
/* ... details omitted ... */
174166

175-
public static UserAccount readThrough(String userId) {
167+
public UserAccount readThrough(final String userId) {
176168
if (cache.contains(userId)) {
177-
LOGGER.info("# Cache Hit!");
169+
LOGGER.info("# Found in Cache!");
178170
return cache.get(userId);
179171
}
180-
LOGGER.info("# Cache Miss!");
181-
UserAccount userAccount = DbManager.readFromDb(userId);
172+
LOGGER.info("# Not found in cache! Go to DB!!");
173+
UserAccount userAccount = dbManager.readFromDb(userId);
182174
cache.set(userId, userAccount);
183175
return userAccount;
184176
}
185177

186-
public static void writeThrough(UserAccount userAccount) {
178+
public void writeThrough(final UserAccount userAccount) {
187179
if (cache.contains(userAccount.getUserId())) {
188-
DbManager.updateDb(userAccount);
180+
dbManager.updateDb(userAccount);
189181
} else {
190-
DbManager.writeToDb(userAccount);
182+
dbManager.writeToDb(userAccount);
191183
}
192184
cache.set(userAccount.getUserId(), userAccount);
193185
}
194186

187+
public void writeAround(final UserAccount userAccount) {
188+
if (cache.contains(userAccount.getUserId())) {
189+
dbManager.updateDb(userAccount);
190+
// Cache data has been updated -- remove older
191+
cache.invalidate(userAccount.getUserId());
192+
// version from cache.
193+
} else {
194+
dbManager.writeToDb(userAccount);
195+
}
196+
}
197+
195198
public static void clearCache() {
196199
if (cache != null) {
197200
cache.clear();
@@ -222,34 +225,39 @@ class.
222225
public final class AppManager {
223226

224227
private static CachingPolicy cachingPolicy;
228+
private final DbManager dbManager;
229+
private final CacheStore cacheStore;
225230

226231
private AppManager() {
227232
}
228233

229-
public static void initDb(boolean useMongoDb) { /* ... */ }
234+
public void initDb() { /* ... */ }
230235

231236
public static void initCachingPolicy(CachingPolicy policy) { /* ... */ }
232237

233238
public static void initCacheCapacity(int capacity) { /* ... */ }
234239

235-
public static UserAccount find(String userId) {
236-
if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) {
237-
return CacheStore.readThrough(userId);
240+
public UserAccount find(final String userId) {
241+
LOGGER.info("Trying to find {} in cache", userId);
242+
if (cachingPolicy == CachingPolicy.THROUGH
243+
|| cachingPolicy == CachingPolicy.AROUND) {
244+
return cacheStore.readThrough(userId);
238245
} else if (cachingPolicy == CachingPolicy.BEHIND) {
239-
return CacheStore.readThroughWithWriteBackPolicy(userId);
246+
return cacheStore.readThroughWithWriteBackPolicy(userId);
240247
} else if (cachingPolicy == CachingPolicy.ASIDE) {
241248
return findAside(userId);
242249
}
243250
return null;
244251
}
245252

246-
public static void save(UserAccount userAccount) {
253+
public void save(final UserAccount userAccount) {
254+
LOGGER.info("Save record!");
247255
if (cachingPolicy == CachingPolicy.THROUGH) {
248-
CacheStore.writeThrough(userAccount);
256+
cacheStore.writeThrough(userAccount);
249257
} else if (cachingPolicy == CachingPolicy.AROUND) {
250-
CacheStore.writeAround(userAccount);
258+
cacheStore.writeAround(userAccount);
251259
} else if (cachingPolicy == CachingPolicy.BEHIND) {
252-
CacheStore.writeBehind(userAccount);
260+
cacheStore.writeBehind(userAccount);
253261
} else if (cachingPolicy == CachingPolicy.ASIDE) {
254262
saveAside(userAccount);
255263
}
@@ -269,24 +277,35 @@ Here is what we do in the main class of the application.
269277
@Slf4j
270278
public class App {
271279

272-
public static void main(String[] args) {
273-
AppManager.initDb(false);
274-
AppManager.initCacheCapacity(3);
275-
var app = new App();
280+
public static void main(final String[] args) {
281+
boolean isDbMongo = isDbMongo(args);
282+
if(isDbMongo){
283+
LOGGER.info("Using the Mongo database engine to run the application.");
284+
} else {
285+
LOGGER.info("Using the 'in Memory' database to run the application.");
286+
}
287+
App app = new App(isDbMongo);
276288
app.useReadAndWriteThroughStrategy();
289+
String splitLine = "==============================================";
290+
LOGGER.info(splitLine);
277291
app.useReadThroughAndWriteAroundStrategy();
292+
LOGGER.info(splitLine);
278293
app.useReadThroughAndWriteBehindStrategy();
294+
LOGGER.info(splitLine);
279295
app.useCacheAsideStategy();
296+
LOGGER.info(splitLine);
280297
}
281298

282299
public void useReadAndWriteThroughStrategy() {
283300
LOGGER.info("# CachingPolicy.THROUGH");
284-
AppManager.initCachingPolicy(CachingPolicy.THROUGH);
301+
appManager.initCachingPolicy(CachingPolicy.THROUGH);
302+
285303
var userAccount1 = new UserAccount("001", "John", "He is a boy.");
286-
AppManager.save(userAccount1);
287-
LOGGER.info(AppManager.printCacheContent());
288-
AppManager.find("001");
289-
AppManager.find("001");
304+
305+
appManager.save(userAccount1);
306+
LOGGER.info(appManager.printCacheContent());
307+
appManager.find("001");
308+
appManager.find("001");
290309
}
291310

292311
public void useReadThroughAndWriteAroundStrategy() { /* ... */ }
@@ -297,16 +316,6 @@ public class App {
297316
}
298317
```
299318

300-
Finally, here is some of the console output from the program.
301-
302-
```
303-
12:32:53.845 [main] INFO com.iluwatar.caching.App - # CachingPolicy.THROUGH
304-
12:32:53.900 [main] INFO com.iluwatar.caching.App -
305-
--CACHE CONTENT--
306-
UserAccount(userId=001, userName=John, additionalInfo=He is a boy.)
307-
----
308-
```
309-
310319
## Class diagram
311320

312321
![alt text](./etc/caching.png "Caching")

caching/docker-compose.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: '3.7'
2+
services:
3+
mongodb_container:
4+
image: mongo:latest
5+
environment:
6+
MONGO_INITDB_ROOT_USERNAME: root
7+
MONGO_INITDB_ROOT_PASSWORD: rootpassword
8+
ports:
9+
- 27017:27017
10+
volumes:
11+
- ./mongo-data/:/data/db

caching/etc/caching.png

-112 KB
Binary file not shown.

0 commit comments

Comments
 (0)