BAEL-1212 Guide to Creational Design Patterns (#2932)

* Initial commit for 'Introduction to Creational Design Patterns'

* second commit with some minor fixes and test case additions

* second commit with some minor fixes and test case additions

* BAEL-1212 Guide to Creational Patterns - Made changes as per latest review

* Renamed Toy family to AAnimal family.
This commit is contained in:
ramansahasi 2017-11-21 02:43:07 +05:30 committed by Grzegorz Piwowarek
parent 2814a5f8d0
commit 8de9f342e4
27 changed files with 450 additions and 0 deletions

View File

@ -0,0 +1,6 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public interface AbstractFactory {
Animal getAnimal(String toyType) ;
Color getColor(String colorType);
}

View File

@ -0,0 +1,18 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class AbstractPatternDriver {
public static void main(String[] args) {
AbstractFactory abstractFactory;
//creating a brown toy dog
abstractFactory = FactoryProvider.getFactory("Toy");
Animal toy = abstractFactory.getAnimal("Dog");
abstractFactory = FactoryProvider.getFactory("Color");
Color color = abstractFactory.getColor("Brown");
String result = "A " + toy.getType() + " with " + color.getColor() + " color " + toy.makeSound();
System.out.println(result);
}
}

View File

@ -0,0 +1,6 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public interface Animal {
String getType();
String makeSound();
}

View File

@ -0,0 +1,21 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class AnimalFactory implements AbstractFactory {
@Override
public Animal getAnimal(String animalType) {
if ("Dog".equalsIgnoreCase(animalType)) {
return new Dog();
} else if ("Duck".equalsIgnoreCase(animalType)) {
return new Duck();
}
return null;
}
@Override
public Color getColor(String color) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class Brown implements Color {
@Override
public String getColor() {
return "brown";
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public interface Color {
String getColor();
}

View File

@ -0,0 +1,21 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class ColorFactory implements AbstractFactory {
@Override
public Color getColor(String colorType) {
if ("Brown".equalsIgnoreCase(colorType)) {
return new Brown();
} else if ("White".equalsIgnoreCase(colorType)) {
return new White();
}
return null;
}
@Override
public Animal getAnimal(String toyType) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class Dog implements Animal {
@Override
public String getType() {
return "Dog";
}
@Override
public String makeSound() {
return "Barks";
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class Duck implements Animal {
@Override
public String getType() {
return "Duck";
}
@Override
public String makeSound() {
return "Squeks";
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class FactoryProvider {
public static AbstractFactory getFactory(String choice){
if("Toy".equalsIgnoreCase(choice)){
return new AnimalFactory();
}
else if("Color".equalsIgnoreCase(choice)){
return new ColorFactory();
}
return null;
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.abstractfactory;
public class White implements Color {
@Override
public String getColor() {
return "White";
}
}

View File

@ -0,0 +1,64 @@
package com.baeldung.designpatterns.creational.builder;
public class BankAccount {
private String name;
private String accountNumber;
private String email;
private boolean newsletter;
//The constructor that takes a builder from which it will create object
//the access to this is only provided to builder
private BankAccount(BankAccountBuilder builder) {
this.name = builder.name;
this.accountNumber = builder.accountNumber;
this.email = builder.email;
this.newsletter = builder.newsletter;
}
public static class BankAccountBuilder {
private String name;
private String accountNumber;
private String email;
private boolean newsletter;
//All Mandatory parameters goes with this constructor
public BankAccountBuilder(String name, String accountNumber) {
this.name = name;
this.accountNumber = accountNumber;
}
//setters for optional parameters which returns this same builder
//to support fluent design
public BankAccountBuilder withEmail(String email) {
this.email = email;
return this;
}
public BankAccountBuilder wantNewsletter(boolean newsletter) {
this.newsletter = newsletter;
return this;
}
//the actual build method that prepares and returns a BankAccount object
public BankAccount build() {
return new BankAccount(this);
}
}
//getters
public String getName() {
return name;
}
public String getAccountNumber() {
return accountNumber;
}
public String getEmail() {
return email;
}
public boolean isNewsletter() {
return newsletter;
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.designpatterns.creational.builder;
public class BuilderPatternDriver {
public static void main(String[] args) {
BankAccount newAccount = new BankAccount
.BankAccountBuilder("Jon", "22738022275")
.withEmail("jon@example.com")
.wantNewsletter(true)
.build();
System.out.println("Name: " + newAccount.getName());
System.out.println("AccountNumber:" + newAccount.getAccountNumber());
System.out.println("Email: " + newAccount.getEmail());
System.out.println("Want News letter?: " + newAccount.isNewsletter());
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.designpatterns.creational.factory;
public class FactoryDriver {
public static void main(String[] args) {
Polygon p;
PolygonFactory factory = new PolygonFactory();
//get the shape which has 4 sides
p = factory.getPolygon(4);
System.out.println("The shape with 4 sides is a " + p.getType());
//get the shape which has 4 sides
p = factory.getPolygon(8);
System.out.println("The shape with 8 sides is a " + p.getType());
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.factory;
public class Heptagon implements Polygon {
@Override
public String getType() {
return "Heptagon";
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.factory;
public class Octagon implements Polygon {
@Override
public String getType() {
return "Octagon";
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.factory;
public class Pentagon implements Polygon {
@Override
public String getType() {
return "Pentagon";
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.designpatterns.creational.factory;
public interface Polygon {
String getType();
}

View File

@ -0,0 +1,22 @@
package com.baeldung.designpatterns.creational.factory;
public class PolygonFactory {
public Polygon getPolygon(int numberOfSides) {
if(numberOfSides == 3) {
return new Triangle();
}
if(numberOfSides == 4) {
return new Square();
}
if(numberOfSides == 5) {
return new Pentagon();
}
if(numberOfSides == 4) {
return new Heptagon();
}
else if(numberOfSides == 8) {
return new Octagon();
}
return null;
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.factory;
public class Square implements Polygon {
@Override
public String getType() {
return "Square";
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.designpatterns.creational.factory;
public class Triangle implements Polygon {
@Override
public String getType() {
return "Triangle";
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.designpatterns.creational.singleton;
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.designpatterns.creational.singleton;
public class SingletonDriver {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
System.out.println(instance.toString());
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.designpatterns.creational.abstractfactory;
import static org.junit.Assert.*;
import org.junit.Test;
public class AbstractPatternIntegrationTest {
@Test
public void givenAbstractFactory_whenGettingObjects_thenSuccessful() {
AbstractFactory abstractFactory;
//creating a brown toy dog
abstractFactory = FactoryProvider.getFactory("Toy");
Animal toy = abstractFactory.getAnimal("Dog");
abstractFactory = FactoryProvider.getFactory("Color");
Color color = abstractFactory.getColor("Brown");
String result = "A " + toy.getType() + " with " + color.getColor() + " color " + toy.makeSound();
assertEquals("A Dog with brown color Barks", result);
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.designpatterns.creational.builder;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class BuilderPatternIntegrationTest {
@Test
public void whenCreatingObjectThroughBuilder_thenObjectValid() {
BankAccount newAccount = new BankAccount
.BankAccountBuilder("Jon", "22738022275")
.withEmail("jon@example.com")
.wantNewsletter(true)
.build();
assertEquals(newAccount.getName(), "Jon");
assertEquals(newAccount.getAccountNumber(), "22738022275");
assertEquals(newAccount.getEmail(), "jon@example.com");
assertEquals(newAccount.isNewsletter(), true);
}
@Test
public void whenSkippingOptionalParameters_thenObjectValid() {
BankAccount newAccount = new BankAccount
.BankAccountBuilder("Jon", "22738022275")
.build();
assertEquals(newAccount.getName(), "Jon");
assertEquals(newAccount.getAccountNumber(), "22738022275");
assertEquals(newAccount.getEmail(), null);
assertEquals(newAccount.isNewsletter(), false);
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.designpatterns.creational.factory;
import static org.junit.Assert.*;
import org.junit.Test;
public class FactoryIntegrationTest {
@Test
public void whenUsingFactoryForSquare_thenCorrectObjectReturned() {
Polygon p;
PolygonFactory factory = new PolygonFactory();
//get the shape which has 4 sides
p = factory.getPolygon(4);
String result = "The shape with 4 sides is a " + p.getType();
assertEquals("The shape with 4 sides is a Square", result);
}
@Test
public void whenUsingFactoryForOctagon_thenCorrectObjectReturned() {
Polygon p;
PolygonFactory factory = new PolygonFactory();
//get the shape which has 4 sides
p = factory.getPolygon(8);
String result = "The shape with 8 sides is a " + p.getType();
assertEquals("The shape with 8 sides is a Octagon", result);
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.designpatterns.creational.singleton;
import org.junit.Test;
import static org.junit.Assert.*;
public class SingletonIntegrationTest {
@Test
/**
* Although there is absolutely no way to determine whether
* a class is Singleton, in this test case, we will just
* check for two objects if they point to same instance or
* not. We will also check for their hashcode.
*/
public void whenGettingMultipleObjects_thenAllPointToSame() {
//first object
Singleton obj1 = Singleton.getInstance();
//Second object
Singleton obj2 = Singleton.getInstance();
assertTrue(obj1 == obj2);
assertEquals(obj1.hashCode(), obj2.hashCode());
}
}