Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions twin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target/
Binary file added twin/etc/twin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 79 additions & 0 deletions twin/etc/twin.ucls
Original file line number Diff line number Diff line change
@@ -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>
24 changes: 24 additions & 0 deletions twin/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
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



![alt text](./etc/twin.png "Twin")

**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.

**Credits:**

* [Twin – A Design Pattern for Modeling Multiple Inheritance](http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf)
18 changes: 18 additions & 0 deletions twin/pom.xml
Original file line number Diff line number Diff line change
@@ -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>
46 changes: 46 additions & 0 deletions twin/src/main/java/com/iluwatar/twin/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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, the essence of the Twin pattern is the {@link BallItem} class and
* {@link BallThread} class represent the twin objects to coordinate with each other(via the twin
* reference) like a single class inheriting from {@link GameItem} and {@link Thread}.
*/

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();

// exit
ballThread.stopMe();
}

private static void waiting() throws Exception {
Thread.sleep(2500);
}
}
41 changes: 41 additions & 0 deletions twin/src/main/java/com/iluwatar/twin/BallItem.java
Original file line number Diff line number Diff line change
@@ -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 changes: 53 additions & 0 deletions twin/src/main/java/com/iluwatar/twin/BallThread.java
Original file line number Diff line number Diff line change
@@ -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 changes: 25 additions & 0 deletions twin/src/main/java/com/iluwatar/twin/GameItem.java
Original file line number Diff line number Diff line change
@@ -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 changes: 17 additions & 0 deletions twin/src/test/java/com/iluwatar/twin/AppTest.java
Original file line number Diff line number Diff line change
@@ -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);
}
}