Skip to content

Commit 953af7c

Browse files
authored
feature: Add Service to Worker Pattern (#2004)
* update service to worker * update pom.xml and make GiantModel public * add javadoc for GaintModel
1 parent b027d29 commit 953af7c

File tree

19 files changed

+886
-1
lines changed

19 files changed

+886
-1
lines changed

model-view-controller/src/main/java/com/iluwatar/model/view/controller/GiantModel.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ public class GiantModel {
3333
private Fatigue fatigue;
3434
private Nourishment nourishment;
3535

36-
GiantModel(Health health, Fatigue fatigue, Nourishment nourishment) {
36+
/**
37+
* Instantiates a new GiantModel.
38+
*/
39+
public GiantModel(Health health, Fatigue fatigue, Nourishment nourishment) {
3740
this.health = health;
3841
this.fatigue = fatigue;
3942
this.nourishment = nourishment;

pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
<module>domain-model</module>
231231
<module>composite-view</module>
232232
<module>metadata-mapping</module>
233+
<module>service-to-worker</module>
233234
</modules>
234235
<repositories>
235236
<repository>

service-to-worker/README.md

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
layout: pattern
3+
title: Service to Worker
4+
folder: service-to-worker
5+
permalink: /patterns/service-to-worker/
6+
categories: Architectural
7+
tags:
8+
- Decoupling
9+
---
10+
11+
## Intent
12+
13+
Combine a controller and dispatcher with views and helpers to handle client requests and prepare a dynamic presentation as the response. Controllers delegate content retrieval to helpers, which manage the population of the intermediate model for the view. A dispatcher is responsible for view management and navigation and can be encapsulated either within a controller or a separate component.
14+
15+
## Explanation
16+
17+
Real world example
18+
19+
> In the classic MVC pattern, M refers to the business model, V refers to the user interface, and C is the controller. The purpose of using MVC is to separate the implementation code of M and V, so that the same program can use different forms of expression. In the Service to Worker pattern, the C directly controls the display of the V and can receive commands to control the dispatcher indirectly. The dispatcher stores different commands that can be used to modify the `model` with `action`s or to modify the display in the `view`s.
20+
21+
In plain words
22+
23+
> Service to Worker Pattern uses Dispatcher to combine the controller and the view to handle client requests and prepare a dynamic presentation as the response.
24+
25+
**Programmatic Example**
26+
27+
We modified this pattern based on a classic design patterns [Model View Controller Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/model-view-controller) as the Class Diagram and two main classes `Dispatcher` and `Action` have been added.
28+
29+
The Dispatcher, which encapsulates worker and view selection based on request information and/or an internal navigation model.
30+
31+
```java
32+
public class Dispatcher {
33+
34+
private final GiantView giantView;
35+
private final List<Action> actions;
36+
37+
/**
38+
* Instantiates a new Dispatcher.
39+
*
40+
* @param giantView the giant view
41+
*/
42+
public Dispatcher(GiantView giantView) {
43+
this.giantView = giantView;
44+
this.actions = new ArrayList<>();
45+
}
46+
47+
/**
48+
* Add an action.
49+
*
50+
* @param action the action
51+
*/
52+
void addAction(Action action) {
53+
actions.add(action);
54+
}
55+
56+
/**
57+
* Perform an action.
58+
*
59+
* @param s the s
60+
* @param actionIndex the action index
61+
*/
62+
public void performAction(Command s, int actionIndex) {
63+
actions.get(actionIndex).updateModel(s);
64+
}
65+
66+
/**
67+
* Update view.
68+
*
69+
* @param giantModel the giant model
70+
*/
71+
public void updateView(GiantModel giantModel) {
72+
giantView.displayGiant(giantModel);
73+
}
74+
}
75+
```
76+
77+
The Action (Worker), which can process user input and perform a specific update on the model.
78+
79+
```java
80+
public class Action {
81+
82+
private final GiantModel giant;
83+
84+
/**
85+
* Instantiates a new Action.
86+
*
87+
* @param giant the giant
88+
*/
89+
public Action(GiantModel giant) {
90+
this.giant = giant;
91+
}
92+
93+
/**
94+
* Update model based on command.
95+
*
96+
* @param command the command
97+
*/
98+
public void updateModel(Command command) {
99+
setFatigue(command.getFatigue());
100+
setHealth(command.getHealth());
101+
setNourishment(command.getNourishment());
102+
}
103+
}
104+
```
105+
106+
Therefore, this example leverages the Service to Worker pattern to increase functionality cohesion and improve the business logic.
107+
108+
109+
## Class diagram
110+
![alt text](./etc/service-to-worker.png "Service to Worker")
111+
112+
## Applicability
113+
- For the business logic of web development, the responsibility of a dispatcher component may be to translate the logical name login into the resource name of an appropriate view, such as login.jsp, and dispatch to that view. To accomplish this translation, the dispatcher may access resources such as an XML configuration file that specifies the appropriate view to display.
114+
115+
## Credits
116+
* [J2EE Design Patterns](https://www.oreilly.com/library/view/j2ee-design-patterns/0596004273/re05.html)
117+
* [Core J2EE Patterns](http://corej2eepatterns.com/Patterns/ServiceToWorker.htm)
88.1 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
@startuml
2+
package com.iluwatar.servicetoworker {
3+
class App {
4+
+ App()
5+
+ main(args : String[]) {static}
6+
}
7+
enum Health {
8+
+ DEAD {static}
9+
+ HEALTHY {static}
10+
+ WOUNDED {static}
11+
- title : String
12+
+ toString() : String
13+
}
14+
enum Nourishment {
15+
+ HUNGRY {static}
16+
+ SATURATED {static}
17+
+ STARVING {static}
18+
- title : String
19+
+ toString() : String
20+
}
21+
enum Fatigue {
22+
+ ALERT {static}
23+
+ SLEEPING {static}
24+
+ TIRED {static}
25+
- title : String
26+
+ toString() : String
27+
}
28+
29+
class GiantController {
30+
- dispatcher : Dispatcher
31+
+ GiantController(dispatcher : Dispatcher)
32+
+ setCommand(s : Command, index : int)
33+
+ updateView(giantModel : GiantModel)
34+
}
35+
36+
class GiantModel {
37+
- fatigue : Fatigue
38+
- health : Health
39+
- nourishment : Nourishment
40+
# GiantModel(health : Health, fatigue : Fatigue, nourishment : Nourishment)
41+
+ getFatigue() : Fatigue
42+
+ getHealth() : Health
43+
+ getNourishment() : Nourishment
44+
+ setFatigue(fatigue : Fatigue)
45+
+ setHealth(health : Health)
46+
+ setNourishment(nourishment : Nourishment)
47+
+ toString() : String
48+
}
49+
class GiantView {
50+
- LOGGER : Logger {static}
51+
+ GiantView()
52+
+ displayGiant(giant : GiantModel)
53+
}
54+
55+
class Action{
56+
- giant : GiantModel
57+
+ Action(giant: GiantModel)
58+
+ updateModel(command: Command)
59+
+ setHealth(health : Health)
60+
+ setFatigue(fatigue : Fatigue)
61+
+ setNourishment(nourishment : Nourishment)
62+
}
63+
64+
class Dispatcher{
65+
- giantView : GiantView
66+
- actions : ArrayList<Action>
67+
+ Dispatcher(giantView : GiantView)
68+
+ addAction(action: Action)
69+
+ performAction(s: Command, actionIndex: int)
70+
+ updateView(giant : GiantModel)
71+
}
72+
}
73+
GiantModel --> Nourishment
74+
GiantModel --> Fatigue
75+
GiantModel --> Health
76+
77+
GiantView ..> GiantModel
78+
Dispatcher o-up- Action
79+
GiantController -up-> Dispatcher
80+
81+
GiantController .up.> GiantModel
82+
Action --> GiantModel
83+
Dispatcher -up-> GiantView
84+
Dispatcher .left.> GiantModel
85+
86+
@enduml

service-to-worker/pom.xml

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>java-design-patterns</artifactId>
7+
<groupId>com.iluwatar</groupId>
8+
<version>1.26.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>service-to-worker</artifactId>
13+
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.junit.jupiter</groupId>
17+
<artifactId>junit-jupiter-engine</artifactId>
18+
<scope>test</scope>
19+
</dependency>
20+
<dependency>
21+
<groupId>com.iluwatar</groupId>
22+
<artifactId>model-view-controller</artifactId>
23+
<version>1.26.0-SNAPSHOT</version>
24+
<scope>compile</scope>
25+
</dependency>
26+
</dependencies>
27+
<build>
28+
<plugins>
29+
<plugin>
30+
<groupId>org.apache.maven.plugins</groupId>
31+
<artifactId>maven-assembly-plugin</artifactId>
32+
<executions>
33+
<execution>
34+
<configuration>
35+
<archive>
36+
<manifest>
37+
<mainClass>com.iluwatar.servicetoworker.App</mainClass>
38+
</manifest>
39+
</archive>
40+
</configuration>
41+
</execution>
42+
</executions>
43+
</plugin>
44+
</plugins>
45+
</build>
46+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.iluwatar.servicetoworker;
2+
3+
import com.iluwatar.model.view.controller.Fatigue;
4+
import com.iluwatar.model.view.controller.Health;
5+
import com.iluwatar.model.view.controller.Nourishment;
6+
7+
/**
8+
* The type Action (Worker), which can process user input and perform a specific update on the
9+
* model.
10+
*/
11+
public class Action {
12+
13+
public GiantModel giant;
14+
15+
/**
16+
* Instantiates a new Action.
17+
*
18+
* @param giant the giant
19+
*/
20+
public Action(GiantModel giant) {
21+
this.giant = giant;
22+
}
23+
24+
/**
25+
* Update model based on command.
26+
*
27+
* @param command the command
28+
*/
29+
public void updateModel(Command command) {
30+
setFatigue(command.getFatigue());
31+
setHealth(command.getHealth());
32+
setNourishment(command.getNourishment());
33+
}
34+
35+
/**
36+
* Sets health.
37+
*
38+
* @param health the health
39+
*/
40+
public void setHealth(Health health) {
41+
giant.setHealth(health);
42+
}
43+
44+
/**
45+
* Sets fatigue.
46+
*
47+
* @param fatigue the fatigue
48+
*/
49+
public void setFatigue(Fatigue fatigue) {
50+
giant.setFatigue(fatigue);
51+
}
52+
53+
/**
54+
* Sets nourishment.
55+
*
56+
* @param nourishment the nourishment
57+
*/
58+
public void setNourishment(Nourishment nourishment) {
59+
giant.setNourishment(nourishment);
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.iluwatar.servicetoworker;
2+
3+
import com.iluwatar.model.view.controller.Fatigue;
4+
import com.iluwatar.model.view.controller.Health;
5+
import com.iluwatar.model.view.controller.Nourishment;
6+
7+
/**
8+
* The front controller intercepts all requests and performs common functions using decorators. The
9+
* front controller passes request information to the dispatcher, which uses the request and an
10+
* internal model to chooses and execute appropriate actions. The actions process user input,
11+
* translating it into appropriate updates to the model. The model applies business rules and stores
12+
* the data persistently. Based on the user input and results of the actions, the dispatcher chooses
13+
* a view. The view transforms the updated model data into a form suitable for the user.
14+
*/
15+
public class App {
16+
17+
/**
18+
* Program entry point.
19+
*
20+
* @param args command line args
21+
*/
22+
public static void main(String[] args) {
23+
// create model, view and controller
24+
var giant1 = new GiantModel("giant1", Health.HEALTHY, Fatigue.ALERT, Nourishment.SATURATED);
25+
var giant2 = new GiantModel("giant2", Health.DEAD, Fatigue.SLEEPING, Nourishment.STARVING);
26+
var action1 = new Action(giant1);
27+
var action2 = new Action(giant2);
28+
var view = new GiantView();
29+
var dispatcher = new Dispatcher(view);
30+
dispatcher.addAction(action1);
31+
dispatcher.addAction(action2);
32+
var controller = new GiantController(dispatcher);
33+
34+
// initial display
35+
controller.updateView(giant1);
36+
controller.updateView(giant2);
37+
38+
// controller receives some interactions that affect the giant
39+
controller.setCommand(new Command(Fatigue.SLEEPING, Health.HEALTHY, Nourishment.STARVING), 0);
40+
controller.setCommand(new Command(Fatigue.ALERT, Health.HEALTHY, Nourishment.HUNGRY), 1);
41+
42+
// redisplay
43+
controller.updateView(giant1);
44+
controller.updateView(giant2);
45+
// controller receives some interactions that affect the giant
46+
}
47+
}

0 commit comments

Comments
 (0)