diff --git a/factory-kit/index.md b/factory-kit/index.md new file mode 100644 index 000000000..63809ecc3 --- /dev/null +++ b/factory-kit/index.md @@ -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) diff --git a/factory-kit/pom.xml b/factory-kit/pom.xml new file mode 100644 index 000000000..451d74b1b --- /dev/null +++ b/factory-kit/pom.xml @@ -0,0 +1,21 @@ + + + + java-design-patterns + com.iluwatar + 1.10.0-SNAPSHOT + + 4.0.0 + + + junit + junit + test + + + factory-kit + + + \ No newline at end of file diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/App.java b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java new file mode 100644 index 000000000..572b24630 --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/App.java @@ -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); + } +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java new file mode 100644 index 000000000..8a3ca587b --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/Axe.java @@ -0,0 +1,7 @@ +package com.iluwatar.factorykit; + +public class Axe implements Weapon { + @Override public String toString() { + return "Axe{}"; + } +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java new file mode 100644 index 000000000..aac272513 --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/Bow.java @@ -0,0 +1,7 @@ +package com.iluwatar.factorykit; + +/** + * Created by crossy on 2016-01-16. + */ +public class Bow implements Weapon { +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java new file mode 100644 index 000000000..e20795a1f --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/Builder.java @@ -0,0 +1,7 @@ +package com.iluwatar.factorykit; + +import java.util.function.Supplier; + +public interface Builder { + void add(WeaponType name, Supplier supplier); +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java new file mode 100644 index 000000000..9bbb41915 --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/Spear.java @@ -0,0 +1,7 @@ +package com.iluwatar.factorykit; + +public class Spear implements Weapon { + @Override public String toString() { + return "Spear{}"; + } +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java new file mode 100644 index 000000000..f6e5c5a3e --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/Sword.java @@ -0,0 +1,7 @@ +package com.iluwatar.factorykit; + +public class Sword implements Weapon { + @Override public String toString() { + return "Sword{}"; + } +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java b/factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java new file mode 100644 index 000000000..039628f3d --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/Weapon.java @@ -0,0 +1,4 @@ +package com.iluwatar.factorykit; + +public interface Weapon { +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java b/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java new file mode 100644 index 000000000..e77e2023b --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponFactory.java @@ -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 consumer) { + HashMap> map = new HashMap<>(); + consumer.accept(map::put); + return name -> map.get(name).get(); + } +} diff --git a/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java b/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java new file mode 100644 index 000000000..1db668b0e --- /dev/null +++ b/factory-kit/src/main/java/com/iluwatar/factorykit/WeaponType.java @@ -0,0 +1,8 @@ +package com.iluwatar.factorykit; + +/** + * Created by crossy on 2016-01-16. + */ +public enum WeaponType { + SWORD, AXE, BOW, SPEAR +} diff --git a/factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java b/factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java new file mode 100644 index 000000000..9dbb8444e --- /dev/null +++ b/factory-kit/src/test/java/com/iluwatar/factorykit/app/AppTest.java @@ -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); + } +} + diff --git a/factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java b/factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java new file mode 100644 index 000000000..088b54ba9 --- /dev/null +++ b/factory-kit/src/test/java/com/iluwatar/factorykit/factorykit/FactoryKitTest.java @@ -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)); + } +} diff --git a/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java b/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java index a6786a717..6a9b03d2e 100644 --- a/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java +++ b/factory-method/src/test/java/com/iluwatar/factory/method/FactoryMethodTest.java @@ -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 classes—rather than by calling a constructor. - * - *

Factory produces the object of its liking. + *

+ *

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

*/ 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()); + } } diff --git a/pom.xml b/pom.xml index d2b02fdf7..dbe19088a 100644 --- a/pom.xml +++ b/pom.xml @@ -93,6 +93,7 @@ publish-subscribe delegation event-driven-architecture + factory-kit