Tuesday, April 01, 2014

Design Patterns - Creational

Creational

Creational patterns are ones that create objects for you, rather than having you instantiate objects directly. This gives your program more flexibility in deciding which objects need to be created for a given case.

1.     Factory Methodcreates objects without specifying the exact class to create. Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.



interface Pet {
          public String speak();
}

class Dog implements Pet {
          public String speak() {
                   return "Bark bark...";
          }
}

class Duck implements Pet {
          public String speak() {
                   return "Quack quack...";
          }
}

class PetFactory {

          public Pet getPet(String petType) {
                   Pet pet = null;

                   // based on logic factory instantiates an object
                   if ("bark".equals(petType))
                             pet = new Dog();
                   else if ("quack".equals(petType))
                             pet = new Duck();
                   return pet;
          }
}

public class FactoryMethodExample {

          public static void main(String[] args) {
                   //creating the factory
                    PetFactory petFactory = new PetFactory();
                    
                    //factory instantiates an object
                    Pet pet = petFactory.getPet("bark");
                    
                    //you don't know which object factory created
                    System.out.println(pet.speak());
          }
}

Factory method (recognizeable by creational methods returning an implementation of an abstract/interface type)

·      java.net.URLStreamHandlerFactory#createURLStreamHandler(String) (Returns singleton object per protocol)

2.       Abstract Factorygroups object factories that have a common theme.
In the example below, Sea/Land factories are grouped as AnimalFactory.
Note: Shark and Elephant classes may not be implementing a common interface but may still be created by factories that can be grouped by a common abstract factory interface.


interface Animal {
          public void breathe();
}

interface AnimalFactory {
          public Animal createAnimal();
}

class SeaFactory implements AnimalFactory {

          public Animal createAnimal() {
                   return new Shark();
          }

}

class LandFactory implements AnimalFactory {
          public Animal createAnimal() {
                   return new Elephant();
          }
}

class Shark implements Animal {
          public void breathe() {
                   System.out.println("I breathe in water! He he!");
          }
}

class Elephant implements Animal {
          public void breathe() {
                   System.out.println("I breathe with my lungs. Its easy!");
          }
}

/**
 * Given an animal factory, creates an animal.
 *
 * @author Watsh
 *
 */
class Wonderland {
          public Wonderland(AnimalFactory factory) {
                   Animal animal = factory.createAnimal();
                   animal.breathe();
          }
}

/**
 * Test abstract factory pattern.
 *
 * @author Watsh
 *
 */
public class AbstractFactoryExample {

          public static void main(String[] args) {
                   new Wonderland(createAnimalFactory("water"));
          }

          public static AnimalFactory createAnimalFactory(String type) {
                   if ("water".equals(type))
                             return new SeaFactory();
                   else
                             return new LandFactory();
          }
}

Abstract factory (recognizeable by creational methods returning the factory itself which in turn can be used to create another abstract/interface type)


3.     Builder - Separate the construction of a complex object from its representation.

If there are optional properties in a class then we will have to write several different constructors that can take different combinations of those optional properties. Instead if we use Builder pattern we only set the optional properties through their setter methods - thus keeping the code cleaner.

In the example below, NutritionalFacts class:
a.       has a static Builder class which takes the mandatory properties in its constructor,
b.      there are setter methods in Builder for each of the optional properties.
c.       The setter methods return this instance – for fluent API.
d.      NutritionalFacts constructor takes Builder and is private.

class NutritionalFacts {
          private int sodium; // mandatory property

          // optional properties
          private int fat;
          private int carbo;

          /**
           * A nested static class.
           *
           */
          static class Builder {
                   private int sodium;
                   private int fat;
                   private int carbo;

                   /**
                    * Use constructor param for mandatory properties.
                    *
                    * @param s
                    */
                   public Builder(int s) {
                             this.sodium = s;
                   }

                   /*
                    * Have methods for each property that return this.
                    *
                    * @param f
                    * @return
                    */
                   public Builder fat(int f) {
                             this.fat = f;
                             return this;
                   }

                   public Builder carbo(int c) {
                             this.carbo = c;
                             return this;
                   }

                   public NutritionalFacts build() {
                             return new NutritionalFacts(this);
                   }
          }

          private NutritionalFacts(Builder b) {
                   this.sodium = b.sodium;
                   this.fat = b.fat;
                   this.carbo = b.carbo;
          }

          @Override
          public String toString() {
                   return "NutritionalFacts [sodium=" + sodium + ", fat=" + fat
                                      + ", carbo=" + carbo + "]";
          }
         
         
}
/**
 * Builder test.
 *
 * @author Watsh
 *
 */
public class BuilderExample {
          public static void main(String[] args) {
                   NutritionalFacts n = new NutritionalFacts.Builder(10).carbo(23).fat(1)
                                      .build();
                   System.out.println(n);
          }

}

Builder (recognizeable by creational methods returning the instance itself)

·      java.lang.StringBuilder#append() (unsynchronized)
·      java.lang.StringBuffer#append() (synchronized)
·      All implementations of java.lang.Appendable

4.       Prototype - creates objects by cloning an existing object.



class Bike implements Cloneable {
          private int gears;
          private String bikeType;
          private String model;

          public Bike() {
                   bikeType = "Standard";
                   model = "Leopard";
                   gears = 4;
          }

          public Bike clone() {
                   return new Bike();
          }

          public void makeAdvanced() {
                   bikeType = "Advanced";
                   model = "Jaguar";
                   gears = 6;
          }

          public String getModel() {
                   return model;
          }

          @Override
          public String toString() {
                   return "Bike [gears=" + gears + ", bikeType=" + bikeType + ", model="
                                      + model + "]";
          }

}

public class PrototypeExample {
          /**
           * Takes a basic bike object and makes an advanced bike object.
           *
           * @param basicBike
           * @return
           */
          public static Bike makeJaguar(Bike basicBike) {
                   basicBike.makeAdvanced();
                   return basicBike;
          }

          public static void main(String[] args) {
                   Bike bike = new Bike();
                   Bike basicBike = bike.clone();
                   System.out.println(basicBike);
                   Bike advancedBike = makeJaguar(basicBike);
                   System.out.println("Prototype Design Pattern: " + advancedBike);
          }
}

Prototype (recognizeable by creational methods returning a different instance of itself with the same properties)

·      java.lang.Object#clone() (the class has to implement java.lang.Cloneable)

5.       Singleton - Ensure a class has only one instance, and provide a global point of access to it.


package patterns.creational;

/**
 * Singleton instance created when class is loaded.
 *
 * @author Watsh
 *
 */
class EagerSingleton {
          private static EagerSingleton INSTANCE = new EagerSingleton();

          private EagerSingleton() {
          }

          public static EagerSingleton getSingleInstance() {
                   return INSTANCE;
          }
}

/**
 * This is also lazy initialization. Only works for Java SE 5.0 or later.
 *
 */
class DoubleCheckedLockingSingleton {
          private static DoubleCheckedLockingSingleton INSTANCE = null;

          private DoubleCheckedLockingSingleton() {
          }

          public static DoubleCheckedLockingSingleton getSingleInstance() {
                   if (INSTANCE == null) {
                             synchronized (DoubleCheckedLockingSingleton.class) {
                                      if (INSTANCE == null) {
                                                INSTANCE = new DoubleCheckedLockingSingleton();
                                      }
                             }
                   }
                   return INSTANCE;
          }
}

/**
 * Initialization on-demand holder. The nested class is referenced no earlier
 * (and therefore loaded no earlier by the class loader) than the moment that
 * getInstance() is called. Thus, this solution is thread-safe without requiring
 * special language constructs (i.e. volatile or synchronized).
 */
class Singleton {
          // Private constructor prevents instantiation from other classes
          private Singleton() {
          }

          /**
           * SingletonHolder is loaded on the first execution of
           * Singleton.getInstance() or the first access to SingletonHolder.INSTANCE,
           * not before.
           */
          private static class SingletonHolder {
                   private static final Singleton INSTANCE = new Singleton();
          }

          public static Singleton getInstance() {
                   return SingletonHolder.INSTANCE;
          }
}

/**
 * Best approach - does not have the drawback of serializable objects. Any enum
 * value is instantiated only once in a Java program. Since Java enum values are
 * globally accessible, so is the singleton, initialized lazily by the
 * classloader.
 *
 * @author Watsh
 *
 */
enum LazySingleton {
          INSTANCE;
          public void execute(String arg) {
                   System.out.println(arg);
          }
}

public class SingletonExample {

          public static void main(String[] args) {
                   LazySingleton in = LazySingleton.INSTANCE;
                   in.execute("test");
          }
}

Singleton (recognizeable by creational methods returning the same instance (usually of itself) everytime)


No comments:

Popular micro services patterns

Here are some popular Microservice design patterns that a programmer should know: Service Registry  pattern provides a  central location  fo...