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>resource-acquisition-is-initialization</module>
|
||||
<module>thread-pool</module>
|
||||
<module>twin</module>
|
||||
<module>private-class-data</module>
|
||||
<module>object-pool</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