issue #333 factory kit pattern introduced

This commit is contained in:
Kamil Pietruszka 2016-01-17 13:45:33 +01:00
parent bd82387fc1
commit 10bbf988ea
15 changed files with 255 additions and 57 deletions

31
factory-kit/index.md Normal file
View File

@ -0,0 +1,31 @@
---
layout: pattern
title: Factory Kit
folder: factory-kit
permalink: /patterns/factory-kit/
categories: Creational
tags:
- Java
- Difficulty-Beginner
- Functional
---
## Also known as
Virtual Constructor
## Intent
Define factory of immutable content with separated builder and factory interfaces.
![alt text](./etc/factory-kit_1.png "Factory Kit")
## Applicability
Use the Factory Kit pattern when
* a class can't anticipate the class of objects it must create
* you just want a new instance of custom builder instead of global one
* a class wants its subclasses to specify the objects it creates
* classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
## Credits
* [Design Pattern Reloaded by Remi Forax: ](https://www.youtube.com/watch?v=-k2X7guaArU)

21
factory-kit/pom.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.10.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<artifactId>factory-kit</artifactId>
</project>

View File

@ -0,0 +1,15 @@
package com.iluwatar.factorykit;
public class App {
public static void main(String[] args) {
WeaponFactory factory = WeaponFactory.factory(builder -> {
builder.add(WeaponType.SWORD, Sword::new);
builder.add(WeaponType.AXE, Axe::new);
builder.add(WeaponType.SPEAR, Spear::new);
builder.add(WeaponType.BOW, Bow::new);
});
Weapon axe = factory.create(WeaponType.AXE);
System.out.println(axe);
}
}

View File

@ -0,0 +1,7 @@
package com.iluwatar.factorykit;
public class Axe implements Weapon {
@Override public String toString() {
return "Axe{}";
}
}

View File

@ -0,0 +1,7 @@
package com.iluwatar.factorykit;
/**
* Created by crossy on 2016-01-16.
*/
public class Bow implements Weapon {
}

View File

@ -0,0 +1,7 @@
package com.iluwatar.factorykit;
import java.util.function.Supplier;
public interface Builder {
void add(WeaponType name, Supplier<Weapon> supplier);
}

View File

@ -0,0 +1,7 @@
package com.iluwatar.factorykit;
public class Spear implements Weapon {
@Override public String toString() {
return "Spear{}";
}
}

View File

@ -0,0 +1,7 @@
package com.iluwatar.factorykit;
public class Sword implements Weapon {
@Override public String toString() {
return "Sword{}";
}
}

View File

@ -0,0 +1,4 @@
package com.iluwatar.factorykit;
public interface Weapon {
}

View File

@ -0,0 +1,16 @@
package com.iluwatar.factorykit;
import java.util.HashMap;
import java.util.function.Consumer;
import java.util.function.Supplier;
public interface WeaponFactory {
Weapon create(WeaponType name);
static WeaponFactory factory(Consumer<Builder> consumer) {
HashMap<WeaponType, Supplier<Weapon>> map = new HashMap<>();
consumer.accept(map::put);
return name -> map.get(name).get();
}
}

View File

@ -0,0 +1,8 @@
package com.iluwatar.factorykit;
/**
* Created by crossy on 2016-01-16.
*/
public enum WeaponType {
SWORD, AXE, BOW, SPEAR
}

View File

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

View File

@ -0,0 +1,58 @@
package com.iluwatar.factorykit.factorykit;
import com.iluwatar.factorykit.*;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
/**
* Created by crossy on 2016-01-16.
*/
public class FactoryKitTest {
private WeaponFactory factory;
@Before public void init() {
factory = WeaponFactory.factory(builder -> {
builder.add(WeaponType.SPEAR, Spear::new);
builder.add(WeaponType.AXE, Axe::new);
builder.add(WeaponType.SWORD, Sword::new);
});
}
/**
* Testing {@link WeaponFactory} to produce a SPEAR asserting that the Weapon is an instance of {@link Spear}
*/
@Test public void testSpearWeapon() {
Weapon weapon = factory.create(WeaponType.SPEAR);
verifyWeapon(weapon, Spear.class);
}
/**
* Testing {@link WeaponFactory} to produce a AXE asserting that the Weapon is an instance of {@link Axe}
*/
@Test public void testAxeWeapon() {
Weapon weapon = factory.create(WeaponType.AXE);
verifyWeapon(weapon, Axe.class);
}
/**
* Testing {@link WeaponFactory} to produce a SWORD asserting that the Weapon is an instance of {@link Sword}
*/
@Test public void testWeapon() {
Weapon weapon = factory.create(WeaponType.SWORD);
verifyWeapon(weapon, Sword.class);
}
/**
* This method asserts that the weapon object that is passed is an instance of the clazz
*
* @param weapon weapon object which is to be verified
* @param clazz expected class of the weapon
*/
private void verifyWeapon(Weapon weapon, Class clazz) {
assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon));
}
}

View File

@ -1,79 +1,75 @@
package com.iluwatar.factory.method;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* The Factory Method is a creational design pattern which uses factory methods to deal with the
* problem of creating objects without specifying the exact class of object that will be created.
* This is done by creating objects via calling a factory method either specified in an interface
* and implemented by child classes, or implemented in a base class and optionally overridden by
* derived classesrather than by calling a constructor.
*
* <p>Factory produces the object of its liking.
* <p>
* <p>Factory produces the object of its liking.
* The weapon {@link Weapon} manufactured by the
* blacksmith depends on the kind of factory implementation it is referring to.
* </p>
*/
public class FactoryMethodTest {
/**
* Testing {@link OrcBlacksmith} to produce a SPEAR asserting that the Weapon is an instance
* of {@link OrcWeapon}.
*/
@Test
public void testOrcBlacksmithWithSpear() {
Blacksmith blacksmith = new OrcBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
verifyWeapon(weapon, WeaponType.SPEAR, OrcWeapon.class);
}
/**
* Testing {@link OrcBlacksmith} to produce a SPEAR asserting that the Weapon is an instance
* of {@link OrcWeapon}.
*/
@Test public void testOrcBlacksmithWithSpear() {
Blacksmith blacksmith = new OrcBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
verifyWeapon(weapon, WeaponType.SPEAR, OrcWeapon.class);
}
/**
* Testing {@link OrcBlacksmith} to produce a AXE asserting that the Weapon is an instance
* of {@link OrcWeapon}.
*/
@Test
public void testOrcBlacksmithWithAxe() {
Blacksmith blacksmith = new OrcBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
verifyWeapon(weapon, WeaponType.AXE, OrcWeapon.class);
}
/**
* Testing {@link OrcBlacksmith} to produce a AXE asserting that the Weapon is an instance
* of {@link OrcWeapon}.
*/
@Test public void testOrcBlacksmithWithAxe() {
Blacksmith blacksmith = new OrcBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
verifyWeapon(weapon, WeaponType.AXE, OrcWeapon.class);
}
/**
* Testing {@link ElfBlacksmith} to produce a SHORT_SWORD asserting that the Weapon is an
* instance of {@link ElfWeapon}.
*/
@Test
public void testElfBlacksmithWithShortSword() {
Blacksmith blacksmith = new ElfBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD);
verifyWeapon(weapon, WeaponType.SHORT_SWORD, ElfWeapon.class);
}
/**
* Testing {@link ElfBlacksmith} to produce a SHORT_SWORD asserting that the Weapon is an
* instance of {@link ElfWeapon}.
*/
@Test public void testElfBlacksmithWithShortSword() {
Blacksmith blacksmith = new ElfBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SHORT_SWORD);
verifyWeapon(weapon, WeaponType.SHORT_SWORD, ElfWeapon.class);
}
/**
* Testing {@link ElfBlacksmith} to produce a SPEAR asserting that the Weapon is an instance
* of {@link ElfWeapon}.
*/
@Test
public void testElfBlacksmithWithSpear() {
Blacksmith blacksmith = new ElfBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
verifyWeapon(weapon, WeaponType.SPEAR, ElfWeapon.class);
}
/**
* Testing {@link ElfBlacksmith} to produce a SPEAR asserting that the Weapon is an instance
* of {@link ElfWeapon}.
*/
@Test public void testElfBlacksmithWithSpear() {
Blacksmith blacksmith = new ElfBlacksmith();
Weapon weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
verifyWeapon(weapon, WeaponType.SPEAR, ElfWeapon.class);
}
/**
* This method asserts that the weapon object that is passed is an instance of the clazz and the
* weapon is of type expectedWeaponType.
*
* @param weapon weapon object which is to be verified
* @param expectedWeaponType expected WeaponType of the weapon
* @param clazz expected class of the weapon
*/
private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class clazz) {
assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon));
assertEquals("Weapon must be of weaponType: " + clazz.getName(), expectedWeaponType,
weapon.getWeaponType());
}
/**
* This method asserts that the weapon object that is passed is an instance of the clazz and the
* weapon is of type expectedWeaponType.
*
* @param weapon weapon object which is to be verified
* @param expectedWeaponType expected WeaponType of the weapon
* @param clazz expected class of the weapon
*/
private void verifyWeapon(Weapon weapon, WeaponType expectedWeaponType, Class clazz) {
assertTrue("Weapon must be an object of: " + clazz.getName(), clazz.isInstance(weapon));
assertEquals("Weapon must be of weaponType: " + clazz.getName(), expectedWeaponType,
weapon.getWeaponType());
}
}

View File

@ -93,6 +93,7 @@
<module>publish-subscribe</module>
<module>delegation</module>
<module>event-driven-architecture</module>
<module>factory-kit</module>
</modules>
<dependencyManagement>