merged master fixed conflict

This commit is contained in:
Josh 2015-04-04 05:46:19 +08:00
commit ddace113eb
18 changed files with 468 additions and 2 deletions

View File

@ -4,6 +4,14 @@
![Build status](https://travis-ci.org/iluwatar/java-design-patterns.svg?branch=master)
## Introduction
Design patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.
Design patterns can speed up the development process by providing tested, proven development paradigms.
Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code readability for coders and architects who are familiar with the patterns.
## <a name="list-of-design-patterns">List of Design Patterns</a>
### Creational Patterns
@ -14,8 +22,9 @@ Creational design patterns abstract the instantiation process. They help make a
* [Builder](#builder)
* [Factory Method](#factory-method)
* [Prototype](#prototype)
* [Property](#property)
* [Singleton](#singleton)
### Structural Patterns
Structural patterns are concerned with how classes and objects are composed to form larger structures.
@ -50,6 +59,7 @@ Behavioral patterns are concerned with algorithms and the assignment of responsi
* [Double Checked Locking](#double-checked-locking)
* [Null Object](#null-object)
* [Callback](#callback)
* [Execute Around](#execute-around)
### Presentation Tier Patterns
@ -427,6 +437,7 @@ Presentation Tier patterns are the top-most level of the application, this is co
**Applicability:** Use the Callback pattern when
* When some arbitrary synchronous or asynchronous action must be performed after execution of some defined activity.
<<<<<<< HEAD
## <a name="intercepting-filter">Intercepting Filter</a> [&#8593;](#list-of-design-patterns)
**Intent:** Provide pluggable filters to conduct necessary pre-processing and post-processing to requests from a client to a target
@ -436,6 +447,29 @@ Presentation Tier patterns are the top-most level of the application, this is co
* a system uses pre-processing or post-processing requests
* a system should do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers
* you want a modular approach to configuring pre-processing and post-processing schemes
=======
**Real world examples:**
* [CyclicBarrier] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) constructor can accept callback that will be triggered every time when barrier is tripped.
## <a name="execute-around">Execute Around</a> [&#8593;](#list-of-design-patterns)
**Intent:** Execute Around idiom frees the user from certain actions that should always be executed before and after the business method. A good example of this is resource allocation and deallocation leaving the user to specify only what to do with the resource.
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/execute-around/execute-around.png "Execute Around")
**Applicability:** Use the Execute Around idiom when
* You use an API that requires methods to be called in pairs such as open/close or allocate/deallocate.
## <a name="property">Property</a> [&#8593;](#list-of-design-patterns)
**Intent:** Create hierarchy of objects and new objects using already existing objects as parents.
![alt text](https://github.com/iluwatar/java-design-patterns/blob/master/property/etc/property.jpg "Property")
**Applicability:** Use the Property pattern when
* when you like to have objects with dynamic set of fields and prototype inheritance
**Real world examples:**
* [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) prototype inheritance
>>>>>>> origin/master
# Frequently asked questions
@ -481,8 +515,14 @@ The difference is the intent of the patterns. While Proxy controls access to the
* [Lets Modify the Objects-First Approach into Design-Patterns-First](http://edu.pecinovsky.cz/papers/2006_ITiCSE_Design_Patterns_First.pdf)
* [Pattern Languages of Program Design](http://www.amazon.com/Pattern-Languages-Program-Design-Coplien/dp/0201607344/ref=sr_1_1)
* [Martin Fowler - Event Aggregator](http://martinfowler.com/eaaDev/EventAggregator.html)
<<<<<<< HEAD
* [TutorialsPoint - Intercepting Filter](http://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm)
* [Presentation Tier Pattern](http://www.javagyan.com/tutorials/corej2eepatterns/presentation-tier-patterns)
=======
* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](http://www.amazon.com/Functional-Programming-Java-Harnessing-Expressions/dp/1937785467/ref=sr_1_1)
>>>>>>> origin/master
# License

View File

@ -1,7 +1,7 @@
package com.iluwatar;
/**
* Callback pattern is more native for dynamic languages where function are first-class citizen.
* Callback pattern is more native for functional languages where function is treated as first-class citizen.
* Prior to Java8 can be simulated using simple (alike command) interfaces.
*/
public class App {

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,28 @@
<?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.SimpleFileWriter" project="execute-around"
file="/execute-around/src/main/java/com/iluwatar/SimpleFileWriter.java" binary="false" corner="BOTTOM_RIGHT">
<position height="88" width="261" x="213" y="298"/>
<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>
<interface id="2" language="java" name="com.iluwatar.FileWriterAction" project="execute-around"
file="/execute-around/src/main/java/com/iluwatar/FileWriterAction.java" binary="false" corner="BOTTOM_RIGHT">
<position height="88" width="164" x="514" y="298"/>
<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>
</interface>
<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>

18
execute-around/pom.xml Normal file
View 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.0-SNAPSHOT</version>
</parent>
<artifactId>execute-around</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,30 @@
package com.iluwatar;
import java.io.FileWriter;
import java.io.IOException;
/**
* The Execute Around idiom specifies some code to be executed before and after
* a method. Typically the idiom is used when the API has methods to be executed in
* pairs, such as resource allocation/deallocation or lock acquisition/release.
*
* In this example, we have SimpleFileWriter class that opens and closes the file
* for the user. The user specifies only what to do with the file by providing the
* FileWriterAction implementation.
*
*/
public class App {
public static void main( String[] args ) throws IOException {
new SimpleFileWriter("testfile.txt", new FileWriterAction() {
@Override
public void writeFile(FileWriter writer) throws IOException {
writer.write("Hello");
writer.append(" ");
writer.append("there!");
}
});
}
}

View File

@ -0,0 +1,15 @@
package com.iluwatar;
import java.io.FileWriter;
import java.io.IOException;
/**
*
* Interface for specifying what to do with the file resource.
*
*/
public interface FileWriterAction {
void writeFile(FileWriter writer) throws IOException;
}

View File

@ -0,0 +1,23 @@
package com.iluwatar;
import java.io.FileWriter;
import java.io.IOException;
/**
*
* SimpleFileWriter handles opening and closing file for the user. The user
* only has to specify what to do with the file resource through FileWriterAction
* parameter.
*
*/
public class SimpleFileWriter {
public SimpleFileWriter(String filename, FileWriterAction action) throws IOException {
FileWriter writer = new FileWriter(filename);
try {
action.writeFile(writer);
} finally {
writer.close();
}
}
}

View File

@ -0,0 +1,19 @@
package com.iluwatar;
import java.io.IOException;
import org.junit.Test;
/**
*
* Tests execute-around example.
*
*/
public class AppTest {
@Test
public void test() throws IOException {
String[] args = {};
App.main(args);
}
}

View File

@ -41,8 +41,14 @@
<module>null-object</module>
<module>event-aggregator</module>
<module>callback</module>
<<<<<<< HEAD
<module>intercepting-filter</module>
</modules>
=======
<module>execute-around</module>
<module>property</module>
</modules>
>>>>>>> origin/master
<dependencyManagement>
<dependencies>

BIN
property/etc/property.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<class-diagram version="1.1.8" icons="true" automaticImage="JPEG" always-add-relationships="false"
generalizations="true" realizations="true" associations="true" dependencies="false" nesting-relationships="true">
<class id="1" language="java" name="com.iluwatar.Character" project="property"
file="/property/src/main/java/com/iluwatar/Character.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="497" y="232"/>
<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>
<enumeration id="2" language="java" name="com.iluwatar.Character.Type" project="property"
file="/property/src/main/java/com/iluwatar/Character.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="320" y="231"/>
<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>
</enumeration>
<enumeration id="3" language="java" name="com.iluwatar.Stats" project="property"
file="/property/src/main/java/com/iluwatar/Stats.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="695" y="205"/>
<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>
</enumeration>
<interface id="4" language="java" name="com.iluwatar.Prototype" project="property"
file="/property/src/main/java/com/iluwatar/Prototype.java" binary="false" corner="BOTTOM_RIGHT">
<position height="-1" width="-1" x="495" y="487"/>
<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>
</interface>
<association id="5">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="6" name="type"/>
<multiplicity id="7" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="2" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<association id="8">
<end type="SOURCE" refId="1" navigable="false">
<attribute id="9" name="prototype"/>
<multiplicity id="10" minimum="0" maximum="1"/>
</end>
<end type="TARGET" refId="4" navigable="true"/>
<display labels="true" multiplicity="true"/>
</association>
<nesting id="11">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="2"/>
</nesting>
<realization id="12">
<end type="SOURCE" refId="1"/>
<end type="TARGET" refId="4"/>
</realization>
<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>

18
property/pom.xml Normal file
View 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.0-SNAPSHOT</version>
</parent>
<artifactId>property</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,49 @@
package com.iluwatar;
import com.iluwatar.Character.Type;
/**
* Example of Character instantiation using Property pattern (as concept also known like Prototype inheritance).
* In prototype inheritance instead of classes, as opposite to Java class inheritance,
* objects are used to create another objects and object hierarchies.
* Hierarchies are created using prototype chain through delegation: every object has link to parent object.
* Any base (parent) object can be amended at runtime (by adding or removal of some property), and all child objects will be affected as result.
*/
public class App {
public static void main(String[] args) {
/* set up */
Prototype charProto = new Character();
charProto.set(Stats.STRENGTH, 10);
charProto.set(Stats.AGILITY, 10);
charProto.set(Stats.ARMOR, 10);
charProto.set(Stats.ATTACK_POWER, 10);
Character mageProto = new Character(Type.MAGE, charProto);
mageProto.set(Stats.INTELLECT, 15);
mageProto.set(Stats.SPIRIT, 10);
Character warProto = new Character(Type.WARRIOR, charProto);
warProto.set(Stats.RAGE, 15);
warProto.set(Stats.ARMOR, 15); // boost default armor for warrior
Character rogueProto = new Character(Type.ROGUE, charProto);
rogueProto.set(Stats.ENERGY, 15);
rogueProto.set(Stats.AGILITY, 15); // boost default agility for rogue
/* usage */
Character mag = new Character("Player_1", mageProto);
mag.set(Stats.ARMOR, 8);
System.out.println(mag);
Character warrior = new Character("Player_2", warProto);
System.out.println(warrior);
Character rogue = new Character("Player_3", rogueProto);
System.out.println(rogue);
Character rogueDouble = new Character("Player_4", rogue);
rogueDouble.set(Stats.ATTACK_POWER, 12);
System.out.println(rogueDouble);
}
}

View File

@ -0,0 +1,117 @@
package com.iluwatar;
import java.util.HashMap;
import java.util.Map;
/**
* Represents Character in game and his abilities (base stats).
*/
public class Character implements Prototype {
public enum Type {
WARRIOR, MAGE, ROGUE
}
private final Prototype prototype;
private final Map<Stats, Integer> properties = new HashMap<>();
private String name;
private Type type;
public Character() {
this.prototype = new Prototype() { // Null-value object
@Override
public Integer get(Stats stat) {
return null;
}
@Override
public boolean has(Stats stat) {
return false;
}
@Override
public void set(Stats stat, Integer val) {
}
@Override
public void remove(Stats stat) {
}}
;
}
public Character(Type type, Prototype prototype) {
this.type = type;
this.prototype = prototype;
}
public Character(String name, Character prototype) {
this.name = name;
this.type = prototype.type;
this.prototype = prototype;
}
public String name() {
return name;
}
public Type type() {
return type;
}
@Override
public Integer get(Stats stat) {
boolean containsValue = properties.containsKey(stat);
if (containsValue) {
return properties.get(stat);
} else {
return prototype.get(stat);
}
}
@Override
public boolean has(Stats stat) {
return get(stat) != null;
}
@Override
public void set(Stats stat, Integer val) {
properties.put(stat, val);
}
@Override
public void remove(Stats stat) {
properties.put(stat, null);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (name != null) {
builder
.append("Player: ")
.append(name)
.append("\n");
}
if (type != null) {
builder
.append("Character type: ")
.append(type.name())
.append("\n");
}
builder.append("Stats:\n");
for (Stats stat : Stats.values()) {
Integer value = this.get(stat);
if (value == null) {
continue;
}
builder
.append(" - ")
.append(stat.name())
.append(":")
.append(value)
.append("\n");
}
return builder.toString();
}
}

View File

@ -0,0 +1,12 @@
package com.iluwatar;
/**
* Interface for prototype inheritance
*/
public interface Prototype {
public Integer get(Stats stat);
public boolean has(Stats stat);
public void set(Stats stat, Integer val);
public void remove(Stats stat);
}

View File

@ -0,0 +1,9 @@
package com.iluwatar;
/**
* All possible attributes that Character can have
*/
public enum Stats {
AGILITY, STRENGTH, ATTACK_POWER, ARMOR, INTELLECT, SPIRIT, ENERGY, RAGE
}

View File

@ -0,0 +1,12 @@
package com.iluwatar;
import org.junit.Test;
public class AppTest {
@Test
public void test() {
String[] args = {};
App.main(args);
}
}