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:
parent
2814a5f8d0
commit
8de9f342e4
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.designpatterns.creational.abstractfactory;
|
||||
|
||||
public interface AbstractFactory {
|
||||
Animal getAnimal(String toyType) ;
|
||||
Color getColor(String colorType);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.designpatterns.creational.abstractfactory;
|
||||
|
||||
public interface Animal {
|
||||
String getType();
|
||||
String makeSound();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.abstractfactory;
|
||||
|
||||
public class Brown implements Color {
|
||||
|
||||
@Override
|
||||
public String getColor() {
|
||||
return "brown";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.designpatterns.creational.abstractfactory;
|
||||
|
||||
public interface Color {
|
||||
String getColor();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.abstractfactory;
|
||||
|
||||
public class White implements Color {
|
||||
|
||||
@Override
|
||||
public String getColor() {
|
||||
return "White";
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.factory;
|
||||
|
||||
public class Heptagon implements Polygon {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Heptagon";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.factory;
|
||||
|
||||
public class Octagon implements Polygon {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Octagon";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.factory;
|
||||
|
||||
public class Pentagon implements Polygon {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Pentagon";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.designpatterns.creational.factory;
|
||||
|
||||
public interface Polygon {
|
||||
String getType();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.factory;
|
||||
|
||||
public class Square implements Polygon {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Square";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.designpatterns.creational.factory;
|
||||
|
||||
public class Triangle implements Polygon {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Triangle";
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue