Skip to content

Commit bd71bc1

Browse files
authored
docs: add explanation for twin pattern (iluwatar#1869)
* add explanation for twin pattern * updated explanation of twin pattern
1 parent 54d19d4 commit bd71bc1

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

twin/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,144 @@ tags:
1313
Twin pattern is a design pattern which provides a standard solution to simulate multiple
1414
inheritance in java
1515

16+
## Explanation
17+
18+
Real-world example
19+
20+
> Consider a game with a ball that needs features of two types, Game Item, and threads to function
21+
> smoothly in the game. We can use two objects, with one object compatible with the first type and
22+
> the other compatible with the second type.
23+
> The pair of objects together can function as one ball in the game.
24+
25+
In plain words
26+
27+
> It provides a way to form two closely coupled sub-classes that can act as a twin class having two ends.
28+
29+
Wikipedia says
30+
31+
> In software engineering, the Twin pattern is a software design pattern that allows developers
32+
> to model multiple inheritance in programming languages that do not support multiple inheritance.
33+
> This pattern avoids many of the problems with multiple inheritance.
34+
35+
**Programmatic Example**
36+
37+
Take our game ball example from above. Consider we have a game in which the ball needs to be both a `GameItem` and `Thread`.
38+
First of all, we have the `GameItem` class given below and the `Thread` class.
39+
40+
41+
```java
42+
43+
@Slf4j
44+
public abstract class GameItem {
45+
46+
public void draw() {
47+
LOGGER.info("draw");
48+
doDraw();
49+
}
50+
51+
public abstract void doDraw();
52+
53+
54+
public abstract void click();
55+
}
56+
57+
```
58+
59+
Then, we have subclasses `BallItem` and `BallThread` inheriting them, respectively.
60+
61+
```java
62+
63+
@Slf4j
64+
public class BallItem extends GameItem {
65+
66+
private boolean isSuspended;
67+
68+
@Setter
69+
private BallThread twin;
70+
71+
@Override
72+
public void doDraw() {
73+
74+
LOGGER.info("doDraw");
75+
}
76+
77+
public void move() {
78+
LOGGER.info("move");
79+
}
80+
81+
@Override
82+
public void click() {
83+
84+
isSuspended = !isSuspended;
85+
86+
if (isSuspended) {
87+
twin.suspendMe();
88+
} else {
89+
twin.resumeMe();
90+
}
91+
}
92+
}
93+
94+
95+
@Slf4j
96+
public class BallThread extends Thread {
97+
98+
@Setter
99+
private BallItem twin;
100+
101+
private volatile boolean isSuspended;
102+
103+
private volatile boolean isRunning = true;
104+
105+
/**
106+
* Run the thread.
107+
*/
108+
public void run() {
109+
110+
while (isRunning) {
111+
if (!isSuspended) {
112+
twin.draw();
113+
twin.move();
114+
}
115+
try {
116+
Thread.sleep(250);
117+
} catch (InterruptedException e) {
118+
throw new RuntimeException(e);
119+
}
120+
}
121+
}
122+
123+
public void suspendMe() {
124+
isSuspended = true;
125+
LOGGER.info("Begin to suspend BallThread");
126+
}
127+
128+
public void resumeMe() {
129+
isSuspended = false;
130+
LOGGER.info("Begin to resume BallThread");
131+
}
132+
133+
public void stopMe() {
134+
this.isRunning = false;
135+
this.isSuspended = true;
136+
}
137+
}
138+
139+
```
140+
141+
Now, when we need the ball, we can instantiate objects from both the `BallThread` and `BallItem` as a pair and pass them to its pair object so they can act together as appropriate.
142+
143+
```java
144+
145+
var ballItem = new BallItem();
146+
var ballThread = new BallThread();
147+
148+
ballItem.setTwin(ballThread);
149+
ballThread.setTwin(ballItem);
150+
151+
```
152+
153+
16154
## Class diagram
17155
![alt text](./etc/twin.png "Twin")
18156

0 commit comments

Comments
 (0)