diff --git a/README.md b/README.md index 7a5baaa..de6fd4b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ cd java-patterns-and-constructs ``` ## Da List ### Patterns +* [Abstract Factory](src/main/java/com/penapereira/example/constructs/abstractfactory/) +* [Factory](src/main/java/com/penapereira/example/constructs/factory/) * [Factory Method](src/main/java/com/penapereira/example/constructs/factorymethod/) * [Observer](src/main/java/com/penapereira/example/constructs/observer/) * [Singleton](src/main/java/com/penapereira/example/constructs/singleton/) diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/AbstractFactory.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/AbstractFactory.java new file mode 100644 index 0000000..dc3c24c --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/AbstractFactory.java @@ -0,0 +1,6 @@ +package com.penapereira.example.constructs.abstractfactory; + +public interface AbstractFactory { + ProductA createProductA(); + ProductB createProductB(); +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryExampleRunner.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryExampleRunner.java new file mode 100644 index 0000000..74c3dfb --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryExampleRunner.java @@ -0,0 +1,28 @@ +package com.penapereira.example.constructs.abstractfactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import com.penapereira.example.constructs.app.ExampleRunnerInterface; + +@Component +public class AbstractFactoryExampleRunner implements ExampleRunnerInterface { + + private static final Logger log = + LoggerFactory.getLogger(AbstractFactoryExampleRunner.class); + + @Override + public void runExample() throws Exception { + log.trace("Executing Abstract Factory Pattern Implementation:"); + + AbstractFactory factory1 = new Factory1(); + AbstractFactory factory2 = new Factory2(); + + log.trace(" " + factory1.createProductA().name()); + log.trace(" " + factory1.createProductB().name()); + + log.trace(" " + factory2.createProductA().name()); + log.trace(" " + factory2.createProductB().name()); + } +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/Factory1.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/Factory1.java new file mode 100644 index 0000000..a6adccf --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/Factory1.java @@ -0,0 +1,14 @@ +package com.penapereira.example.constructs.abstractfactory; + +public class Factory1 implements AbstractFactory { + + @Override + public ProductA createProductA() { + return new ProductA1(); + } + + @Override + public ProductB createProductB() { + return new ProductB1(); + } +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/Factory2.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/Factory2.java new file mode 100644 index 0000000..997ce00 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/Factory2.java @@ -0,0 +1,14 @@ +package com.penapereira.example.constructs.abstractfactory; + +public class Factory2 implements AbstractFactory { + + @Override + public ProductA createProductA() { + return new ProductA2(); + } + + @Override + public ProductB createProductB() { + return new ProductB2(); + } +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA.java new file mode 100644 index 0000000..6d60d29 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA.java @@ -0,0 +1,5 @@ +package com.penapereira.example.constructs.abstractfactory; + +public interface ProductA { + String name(); +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA1.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA1.java new file mode 100644 index 0000000..0f31eec --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA1.java @@ -0,0 +1,9 @@ +package com.penapereira.example.constructs.abstractfactory; + +public class ProductA1 implements ProductA { + + @Override + public String name() { + return "ProductA1"; + } +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA2.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA2.java new file mode 100644 index 0000000..7f6e76e --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductA2.java @@ -0,0 +1,9 @@ +package com.penapereira.example.constructs.abstractfactory; + +public class ProductA2 implements ProductA { + + @Override + public String name() { + return "ProductA2"; + } +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB.java new file mode 100644 index 0000000..90c8f55 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB.java @@ -0,0 +1,5 @@ +package com.penapereira.example.constructs.abstractfactory; + +public interface ProductB { + String name(); +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB1.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB1.java new file mode 100644 index 0000000..95afab8 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB1.java @@ -0,0 +1,9 @@ +package com.penapereira.example.constructs.abstractfactory; + +public class ProductB1 implements ProductB { + + @Override + public String name() { + return "ProductB1"; + } +} diff --git a/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB2.java b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB2.java new file mode 100644 index 0000000..c804cbc --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/abstractfactory/ProductB2.java @@ -0,0 +1,9 @@ +package com.penapereira.example.constructs.abstractfactory; + +public class ProductB2 implements ProductB { + + @Override + public String name() { + return "ProductB2"; + } +} diff --git a/src/main/java/com/penapereira/example/constructs/factory/ConcreteProductA.java b/src/main/java/com/penapereira/example/constructs/factory/ConcreteProductA.java new file mode 100644 index 0000000..c12ba5d --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/factory/ConcreteProductA.java @@ -0,0 +1,9 @@ +package com.penapereira.example.constructs.factory; + +public class ConcreteProductA implements Product { + + @Override + public String name() { + return "Concrete Product A"; + } +} diff --git a/src/main/java/com/penapereira/example/constructs/factory/ConcreteProductB.java b/src/main/java/com/penapereira/example/constructs/factory/ConcreteProductB.java new file mode 100644 index 0000000..7648cd6 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/factory/ConcreteProductB.java @@ -0,0 +1,9 @@ +package com.penapereira.example.constructs.factory; + +public class ConcreteProductB implements Product { + + @Override + public String name() { + return "Concrete Product B"; + } +} diff --git a/src/main/java/com/penapereira/example/constructs/factory/FactoryExampleRunner.java b/src/main/java/com/penapereira/example/constructs/factory/FactoryExampleRunner.java new file mode 100644 index 0000000..21fec97 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/factory/FactoryExampleRunner.java @@ -0,0 +1,26 @@ +package com.penapereira.example.constructs.factory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import com.penapereira.example.constructs.app.ExampleRunnerInterface; + +@Component +public class FactoryExampleRunner implements ExampleRunnerInterface { + + private static final Logger log = LoggerFactory.getLogger(FactoryExampleRunner.class); + + @Override + public void runExample() throws Exception { + log.trace("Executing Factory Pattern Implementation:"); + + ProductFactory factory = new ProductFactory(); + + Product productA = factory.createProduct("A"); + Product productB = factory.createProduct("B"); + + log.trace(" " + productA.name()); + log.trace(" " + productB.name()); + } +} diff --git a/src/main/java/com/penapereira/example/constructs/factory/Product.java b/src/main/java/com/penapereira/example/constructs/factory/Product.java new file mode 100644 index 0000000..9f9ef09 --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/factory/Product.java @@ -0,0 +1,5 @@ +package com.penapereira.example.constructs.factory; + +public interface Product { + String name(); +} diff --git a/src/main/java/com/penapereira/example/constructs/factory/ProductFactory.java b/src/main/java/com/penapereira/example/constructs/factory/ProductFactory.java new file mode 100644 index 0000000..ac4c4be --- /dev/null +++ b/src/main/java/com/penapereira/example/constructs/factory/ProductFactory.java @@ -0,0 +1,12 @@ +package com.penapereira.example.constructs.factory; + +public class ProductFactory { + + public Product createProduct(String type) { + return switch (type) { + case "A" -> new ConcreteProductA(); + case "B" -> new ConcreteProductB(); + default -> throw new IllegalArgumentException("Unknown type: " + type); + }; + } +} diff --git a/src/test/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryExampleRunnerTests.java b/src/test/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryExampleRunnerTests.java new file mode 100644 index 0000000..0d91e57 --- /dev/null +++ b/src/test/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryExampleRunnerTests.java @@ -0,0 +1,10 @@ +package com.penapereira.example.constructs.abstractfactory; + +import org.junit.jupiter.api.Test; + +class AbstractFactoryExampleRunnerTests { + @Test + void runExampleRuns() throws Exception { + new AbstractFactoryExampleRunner().runExample(); + } +} diff --git a/src/test/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryTests.java b/src/test/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryTests.java new file mode 100644 index 0000000..39eac76 --- /dev/null +++ b/src/test/java/com/penapereira/example/constructs/abstractfactory/AbstractFactoryTests.java @@ -0,0 +1,16 @@ +package com.penapereira.example.constructs.abstractfactory; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class AbstractFactoryTests { + @Test + void factoriesProduceCorrectProducts() { + AbstractFactory f1 = new Factory1(); + AbstractFactory f2 = new Factory2(); + assertEquals("ProductA1", f1.createProductA().name()); + assertEquals("ProductB1", f1.createProductB().name()); + assertEquals("ProductA2", f2.createProductA().name()); + assertEquals("ProductB2", f2.createProductB().name()); + } +} diff --git a/src/test/java/com/penapereira/example/constructs/factory/FactoryExampleRunnerTests.java b/src/test/java/com/penapereira/example/constructs/factory/FactoryExampleRunnerTests.java new file mode 100644 index 0000000..df9940b --- /dev/null +++ b/src/test/java/com/penapereira/example/constructs/factory/FactoryExampleRunnerTests.java @@ -0,0 +1,10 @@ +package com.penapereira.example.constructs.factory; + +import org.junit.jupiter.api.Test; + +class FactoryExampleRunnerTests { + @Test + void runExampleRuns() throws Exception { + new FactoryExampleRunner().runExample(); + } +} diff --git a/src/test/java/com/penapereira/example/constructs/factory/FactoryTests.java b/src/test/java/com/penapereira/example/constructs/factory/FactoryTests.java new file mode 100644 index 0000000..e77b299 --- /dev/null +++ b/src/test/java/com/penapereira/example/constructs/factory/FactoryTests.java @@ -0,0 +1,15 @@ +package com.penapereira.example.constructs.factory; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class FactoryTests { + @Test + void factoryCreatesConcreteProducts() { + ProductFactory factory = new ProductFactory(); + Product a = factory.createProduct("A"); + Product b = factory.createProduct("B"); + assertEquals("Concrete Product A", a.name()); + assertEquals("Concrete Product B", b.name()); + } +}