From d26454af88ba9d97bff22ddadef1d099c52655eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilkka=20Sepp=C3=A4l=C3=A4?= Date: Mon, 27 May 2024 14:31:29 +0300 Subject: [PATCH] docs: update twin --- twin/README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/twin/README.md b/twin/README.md index 00d95fede..532e67a80 100644 --- a/twin/README.md +++ b/twin/README.md @@ -75,7 +75,9 @@ public class BallItem extends GameItem { } } } +``` +```java @Slf4j public class BallThread extends Thread { @Setter @@ -117,25 +119,85 @@ public class BallThread extends Thread { To use these classes together: ```java -var ballItem = new BallItem(); -var ballThread = new BallThread(); +public class App { -ballItem.setTwin(ballThread); -ballThread.setTwin(ballItem); + public static void main(String[] args) throws Exception { + + var ballItem = new BallItem(); + var ballThread = new BallThread(); + + ballItem.setTwin(ballThread); + ballThread.setTwin(ballItem); + + ballThread.start(); + + waiting(); + + ballItem.click(); + + waiting(); + + ballItem.click(); + + waiting(); + + // exit + ballThread.stopMe(); + } + + private static void waiting() throws Exception { + Thread.sleep(750); + } +} +``` + +Let's break down what happens in `App`. + +1. An instance of `BallItem` and `BallThread` are created. +2. The `BallItem` and `BallThread` instances are set as twins of each other. This means that each instance has a reference to the other. +3. The `BallThread` is started. This begins the execution of the `run` method in the `BallThread` class, which continuously calls the `draw` and `move` methods of the `BallItem` (its twin) as long as the `BallThread` is not suspended. +4. The program waits for 750 milliseconds. This is done to allow the `BallThread` to execute its `run` method a few times. +5. The `click` method of the `BallItem` is called. This toggles the `isSuspended` state of the `BallItem` and its twin `BallThread`. If the `BallThread` was running, it gets suspended. If it was suspended, it resumes running. +6. Steps 4 and 5 are repeated twice. This means the `BallThread` is suspended and resumed once. +7. Finally, the `stopMe` method of the `BallThread` is called to stop its execution. + +Console output: + +``` +14:29:33.778 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw +14:29:33.780 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw +14:29:33.780 [Thread-0] INFO com.iluwatar.twin.BallItem -- move +14:29:34.035 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw +14:29:34.035 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw +14:29:34.035 [Thread-0] INFO com.iluwatar.twin.BallItem -- move +14:29:34.291 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw +14:29:34.291 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw +14:29:34.291 [Thread-0] INFO com.iluwatar.twin.BallItem -- move +14:29:34.533 [main] INFO com.iluwatar.twin.BallThread -- Begin to suspend BallThread +14:29:35.285 [main] INFO com.iluwatar.twin.BallThread -- Begin to resume BallThread +14:29:35.308 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw +14:29:35.308 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw +14:29:35.308 [Thread-0] INFO com.iluwatar.twin.BallItem -- move +14:29:35.564 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw +14:29:35.564 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw +14:29:35.565 [Thread-0] INFO com.iluwatar.twin.BallItem -- move +14:29:35.817 [Thread-0] INFO com.iluwatar.twin.GameItem -- draw +14:29:35.817 [Thread-0] INFO com.iluwatar.twin.BallItem -- doDraw +14:29:35.817 [Thread-0] INFO com.iluwatar.twin.BallItem -- move ``` This setup allows `BallItem` and `BallThread` to act together as a single cohesive unit in the game, leveraging the capabilities of both `GameItem` and `Thread` without multiple inheritance. -## Class diagram - -![Twin](./etc/twin.png "Twin") - ## Applicability * Use when you need to decouple classes that share common functionality but cannot inherit from a common base class due to various reasons such as the use of different frameworks or languages. * Useful in performance-critical applications where inheritance might introduce unnecessary overhead. * Applicable in systems requiring resilience through the ability to replace or update one of the twins without affecting the other. +## Tutorials + +* [Twin – A Design Pattern for Modeling Multiple Inheritance (Hanspeter Mössenböck)](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf) + ## Known Uses * User interfaces where different frameworks are used for rendering and logic. @@ -165,4 +227,3 @@ Trade-offs: * [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) * [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3yhh525) * [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR) -* [Twin – A Design Pattern for Modeling Multiple Inheritance - Hanspeter Mössenböck](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf)