implements Twin design pattern #63
This commit is contained in:
parent
27199325ec
commit
fdbfa9e8ee
1
pom.xml
1
pom.xml
@ -68,6 +68,7 @@
|
|||||||
<module>multiton</module>
|
<module>multiton</module>
|
||||||
<module>resource-acquisition-is-initialization</module>
|
<module>resource-acquisition-is-initialization</module>
|
||||||
<module>thread-pool</module>
|
<module>thread-pool</module>
|
||||||
|
<module>twin</module>
|
||||||
<module>private-class-data</module>
|
<module>private-class-data</module>
|
||||||
<module>object-pool</module>
|
<module>object-pool</module>
|
||||||
<module>dependency-injection</module>
|
<module>dependency-injection</module>
|
||||||
|
1
twin/.gitignore
vendored
Normal file
1
twin/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target/
|
BIN
twin/etc/twin.png
Normal file
BIN
twin/etc/twin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
79
twin/etc/twin.ucls
Normal file
79
twin/etc/twin.ucls
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<class-diagram version="1.1.8" icons="true" automaticImage="PNG" always-add-relationships="false" generalizations="true"
|
||||||
|
realizations="true" associations="true" dependencies="false" nesting-relationships="true">
|
||||||
|
<class id="1" language="java" name="com.iluwatar.twin.BallThread" project="twin"
|
||||||
|
file="/twin/src/main/java/com/iluwatar/twin/BallThread.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
|
<position height="-1" width="-1" x="550" y="316"/>
|
||||||
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
</display>
|
||||||
|
</class>
|
||||||
|
<class id="2" language="java" name="com.iluwatar.twin.BallItem" project="twin"
|
||||||
|
file="/twin/src/main/java/com/iluwatar/twin/BallItem.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
|
<position height="-1" width="-1" x="285" y="315"/>
|
||||||
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
</display>
|
||||||
|
</class>
|
||||||
|
<class id="3" language="java" name="com.iluwatar.twin.GameItem" project="twin"
|
||||||
|
file="/twin/src/main/java/com/iluwatar/twin/GameItem.java" binary="false" corner="BOTTOM_RIGHT">
|
||||||
|
<position height="-1" width="-1" x="285" y="84"/>
|
||||||
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
</display>
|
||||||
|
</class>
|
||||||
|
<class id="4" language="java" name="java.lang.Thread" project="twin"
|
||||||
|
file="/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre/lib/rt.jar" binary="true"
|
||||||
|
corner="BOTTOM_RIGHT">
|
||||||
|
<position height="-1" width="-1" x="550" y="96"/>
|
||||||
|
<display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="false" package="false" protected="false" private="false" static="true"/>
|
||||||
|
<operations public="false" package="false" protected="false" private="false" static="true"/>
|
||||||
|
</display>
|
||||||
|
</class>
|
||||||
|
<generalization id="5">
|
||||||
|
<end type="SOURCE" refId="2"/>
|
||||||
|
<end type="TARGET" refId="3"/>
|
||||||
|
</generalization>
|
||||||
|
<association id="6">
|
||||||
|
<end type="SOURCE" refId="2" navigable="false">
|
||||||
|
<attribute id="7" name="twin"/>
|
||||||
|
<multiplicity id="8" minimum="0" maximum="1"/>
|
||||||
|
</end>
|
||||||
|
<end type="TARGET" refId="1" navigable="true"/>
|
||||||
|
<display labels="true" multiplicity="true"/>
|
||||||
|
</association>
|
||||||
|
<association id="9">
|
||||||
|
<end type="SOURCE" refId="4" navigable="false">
|
||||||
|
<attribute id="10" name="threadQ"/>
|
||||||
|
<multiplicity id="11" minimum="0" maximum="1"/>
|
||||||
|
</end>
|
||||||
|
<end type="TARGET" refId="4" navigable="true"/>
|
||||||
|
<display labels="true" multiplicity="true"/>
|
||||||
|
</association>
|
||||||
|
<association id="12">
|
||||||
|
<end type="SOURCE" refId="1" navigable="false">
|
||||||
|
<attribute id="13" name="twin"/>
|
||||||
|
<multiplicity id="14" minimum="0" maximum="1"/>
|
||||||
|
</end>
|
||||||
|
<end type="TARGET" refId="2" navigable="true"/>
|
||||||
|
<display labels="true" multiplicity="true"/>
|
||||||
|
</association>
|
||||||
|
<generalization id="15">
|
||||||
|
<end type="SOURCE" refId="1"/>
|
||||||
|
<end type="TARGET" refId="4"/>
|
||||||
|
</generalization>
|
||||||
|
<classifier-display autosize="true" stereotype="true" package="true" initial-value="false" signature="true"
|
||||||
|
sort-features="false" accessors="true" visibility="true">
|
||||||
|
<attributes public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
<operations public="true" package="true" protected="true" private="true" static="true"/>
|
||||||
|
</classifier-display>
|
||||||
|
<association-display labels="true" multiplicity="true"/>
|
||||||
|
</class-diagram>
|
20
twin/index.md
Normal file
20
twin/index.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
layout: pattern
|
||||||
|
title: Twin
|
||||||
|
folder: twin
|
||||||
|
permalink: /patterns/twin/
|
||||||
|
categories: Creational
|
||||||
|
tags: Java
|
||||||
|
---
|
||||||
|
|
||||||
|
**Intent:** Twin pattern is a design pattern which provides a standard solution to simulate multiple
|
||||||
|
inheritance in java
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Applicability:** Use the Twin idiom when
|
||||||
|
|
||||||
|
* to simulate multiple inheritance in a language that does not support this feature.
|
||||||
|
* to avoid certain problems of multiple inheritance such as name clashes.
|
18
twin/pom.xml
Normal file
18
twin/pom.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.iluwatar</groupId>
|
||||||
|
<artifactId>java-design-patterns</artifactId>
|
||||||
|
<version>1.8.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>twin</artifactId>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
53
twin/src/main/java/com/iluwatar/twin/App.java
Normal file
53
twin/src/main/java/com/iluwatar/twin/App.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package com.iluwatar.twin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Twin pattern is a design pattern which provides a standard solution to simulate multiple
|
||||||
|
* inheritance in java.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* In this example, there is a ball game, a ball needs to subclass {@link GameItem} which provide
|
||||||
|
* some common method like draw and click. Moreover, it needs to subclass {@link Thread} as ball is
|
||||||
|
* a moving item (we use {@link Thread} instead of implements {@link Runnable} for example only)
|
||||||
|
* <p>
|
||||||
|
* Threre is scenario, when user click the ball, the ball will stop, when user click it gain, it
|
||||||
|
* will resume to move. We create two class, ons is {@link BallItem} which subclass {@link GameItem}
|
||||||
|
* , another is {@link BallThread} which subclass {@link Thread}. These two object both hold a field
|
||||||
|
* named "Twin" reference to another object. In {@link BallItem#click()}, it will invoke
|
||||||
|
* {@link BallThread} to suspend or resume moving; in {@link BallThread#run()}, it will invoke
|
||||||
|
* {@link BallItem} for drawing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class App {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Program entry point
|
||||||
|
*
|
||||||
|
* @param args command line args
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
BallItem ballItem = new BallItem();
|
||||||
|
BallThread ballThread = new BallThread();
|
||||||
|
|
||||||
|
ballItem.setTwin(ballThread);
|
||||||
|
ballThread.setTwin(ballItem);
|
||||||
|
|
||||||
|
ballThread.start();
|
||||||
|
|
||||||
|
waiting();
|
||||||
|
|
||||||
|
ballItem.click();
|
||||||
|
|
||||||
|
waiting();
|
||||||
|
|
||||||
|
ballItem.click();
|
||||||
|
|
||||||
|
waiting();
|
||||||
|
|
||||||
|
ballThread.stopMe();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void waiting() throws Exception {
|
||||||
|
Thread.sleep(2500);
|
||||||
|
}
|
||||||
|
}
|
41
twin/src/main/java/com/iluwatar/twin/BallItem.java
Normal file
41
twin/src/main/java/com/iluwatar/twin/BallItem.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
package com.iluwatar.twin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a Ball which extends {@link GameItem} and implements the logic for ball
|
||||||
|
* item, like move and draw. It hold a reference of {@link BallThread} to delegate the suspend and
|
||||||
|
* resume task.
|
||||||
|
*/
|
||||||
|
public class BallItem extends GameItem {
|
||||||
|
|
||||||
|
private boolean isSuspended = false;
|
||||||
|
|
||||||
|
private BallThread twin;
|
||||||
|
|
||||||
|
public void setTwin(BallThread twin) {
|
||||||
|
this.twin = twin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doDraw() {
|
||||||
|
|
||||||
|
System.out.println("doDraw");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move() {
|
||||||
|
System.out.println("move");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void click() {
|
||||||
|
|
||||||
|
isSuspended = !isSuspended;
|
||||||
|
|
||||||
|
if (isSuspended) {
|
||||||
|
twin.suspendMe();
|
||||||
|
} else {
|
||||||
|
twin.resumeMe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
53
twin/src/main/java/com/iluwatar/twin/BallThread.java
Normal file
53
twin/src/main/java/com/iluwatar/twin/BallThread.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
package com.iluwatar.twin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a UI thread for drawing the {@link BallItem}, and provide the method for suspend
|
||||||
|
* and resume. It hold the reference of {@link BallItem} to delegate the draw task.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BallThread extends Thread {
|
||||||
|
|
||||||
|
private BallItem twin;
|
||||||
|
|
||||||
|
private volatile boolean isSuspended;
|
||||||
|
|
||||||
|
private volatile boolean isRunning = true;
|
||||||
|
|
||||||
|
public void setTwin(BallItem twin) {
|
||||||
|
this.twin = twin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
while (isRunning) {
|
||||||
|
while (!isSuspended) {
|
||||||
|
twin.draw();
|
||||||
|
twin.move();
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void suspendMe() {
|
||||||
|
isSuspended = true;
|
||||||
|
System.out.println("Begin to suspend BallThread");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resumeMe() {
|
||||||
|
isSuspended = false;
|
||||||
|
System.out.println("Begin to resume BallThread");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopMe() {
|
||||||
|
this.isRunning = false;
|
||||||
|
this.isSuspended = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
25
twin/src/main/java/com/iluwatar/twin/GameItem.java
Normal file
25
twin/src/main/java/com/iluwatar/twin/GameItem.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
|
||||||
|
package com.iluwatar.twin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GameItem is a common class which provides some common methods for game object.
|
||||||
|
*/
|
||||||
|
public abstract class GameItem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method, do some common logic before draw
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void draw() {
|
||||||
|
System.out.println("draw");
|
||||||
|
doDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void doDraw();
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void click();
|
||||||
|
}
|
17
twin/src/test/java/com/iluwatar/twin/AppTest.java
Normal file
17
twin/src/test/java/com/iluwatar/twin/AppTest.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package com.iluwatar.twin;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Application test
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AppTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws Exception {
|
||||||
|
String[] args = {};
|
||||||
|
App.main(args);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user