GoF Design Patterns in Java- Creational

Jathavan Mahendrarajah
6 min readDec 12, 2021

Creational Design Patterns

related to creation of classes and objects

  • Singleton
  • Multiton
  • Object pool
  • Prototype
  • Factory
  • Factory Method
  • Abstract factory
  • Builder

Singleton

used when we need only one instance(object) of a class

public class Sigleton{
//why private? Encapsulation //why static ? the instance is class specific private static Singleton instance; //make constructor private //why? We cannot use outside this class private Singleton(){ } //getter method //ensure only one instance created //make accessor method synchronised in case of multi-threading public static getInstance(){ if(instance==null){ instance= new Singleton(); } return instance; }}

Considering thread-safe instances, we can make the getInstance() method. But the drawback is each time we need to get instance of the class, we have to unnecessarily acquire lock. To overcome this we have double-checking lock

public static getInstance(){   //synchronization is needed  only during the creation of  objectif (instance==null){
synchronized(Singleton.class){
if (instance==null){
instance = new Singleton();
} } }
return instance;
}
class diagram

Multiton

Similar to singleton but ensures only one instance created per key

public class Multiton{    //inorder to store Multiton instance use hash map
//use concurrent map if you want thread safety
private static HashMap<String, Multiton> instances = new HashMap<String, Multiton>;
//other attributes
private key;
//private constructor private Multiton(String key){ this.key=key; } //public getter //checks whether key present in hash map //if not creates new Multiton according to key and put in hash map //return from hash map public static getInstance(String key){ if(!instances.containsKey(key)){ instances.put(key, new Multiton(key)) } return instances.get(key);}}

Object Pool

reuse the objects which are expensive to create

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class ReusablePool { private long expTime; private HashMap<Reusable,Long> available,inUse; public ReusablePool() { expTime=6000; available= new HashMap<Reusable,Long>(); inUse= new HashMap<Reusable,Long>(); } public synchronized Reusable getObject() { long now = System.currentTimeMillis(); //if there are objects available
if(!available.isEmpty()) {
//iterrate through them
for(Entry<Reusable,Long> entry : available.entrySet() ) {
//pop timed out items from available if expired if(now - entry.getValue()>expTime) { available.remove(entry.getKey()); } else { //if not expired get that entry Reusable o = entry.getKey();
available.remove(o);
inUse.put(o, now);
return o;
} } } //if nothing available or everything expired return new return createNew(now); }
private Reusable createNew(long t) { Reusable created = new Reusable();
inUse.put(created, t);
return created;
}}
class diagram for object pool

Prototype

when creation of an object is coslty we clone pre-existing object. In this way we can create object without knowing how to create them. Eg: in case we dont know what are the arguments to be passed when creating an object

//class of object which we clone must be implementing Cloneable interface
public class Car implements Cloneable{
private String model;

public Car(String model) {this.model=model;}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); }}public class DemoPrototype { public static void main(String[] args) throws CloneNotSupportedException { Car car1 = new Car("civic"); //type casting needed
Car car2= (Car)car1.clone();
}}
class diagram prototype pattern

Factory

Factory class is dedicated to create objects. Client do not know about the creation logic of objects.

//interface which is visible to client
public interface Shape{
void draw();
}
//concrete class
public class Rectangle implements Shape{
void draw(){ System.out.println("draw rectangle");
}
}
//concrete class
public class Circle implements Shape{
void draw(){ System.out.println("draw circle");
}
}
//factory class
public class ShapeFactory{
public Shape getShape(String type){ if (type.equals(rectangle)){return new Rectangle();} if (type.equals(circle){return new Circle();}
}
}
//client
public class Demo{
public static void main(String[] args){ ShapeFactory shapeFactory = new ShapeFactory();
Shape shape1 = shapeFactory.getShape() ;
}
}

We know that Factory class is responsible for object creation. So other classes should not create objects. How to achieve this?

make constructors of concrete classes protected and put the concrete classes and Factory class in same package.

We can also make getShape(String type) method static: because it doesn’t deal with any instances of same class.

Inorder to guarantee only one ShapeFactory object we can use singleton.

Inorder to prevent making sub classes from ShapeFactory, make it final.

class diagram for factory design pattern

Factory Method

Similar to Factory design pattern. In Factory pattern, one class responsible for object creation. But in Factory method, it lets the subclasses of Factory class to decide which objects to create.

public interface Shape{
void draw();
}public class Circle implements Shape{ void draw(){System.out.println("draw circle");}
}
public class Rectangle implements Rectangle{ void draw(){System.out.println("draw rectangle");}
}
public abstract class Factory{ //factory method
protected abstract Shape getShape();
}public class CircleFactory extends Factory{
protected Shape getShape(){
return (Shape)new Circle();
}
}public class RectangleFactory extends Factory{
protected Shape getShape(){
return (Shape)new Rectangle();
}
}
factory method class diagram

Abstract Factory

For creating family of related objects.

//abstract classes
public abstract class Pen{
}
public abstract class Pencil{
}
//concrete classes
public class RedPen extends Pen{
}
public class BluePen extends Pen{
}
public class RedPencil extends Pencil{
}
public class BluePencil extends Pencil{
}
//abstract Factory
public abstract class AbstractFactory{
abstract Pen getPen();
abstract Pencil getPencil();
}//concrete Factory for creating family of Red
public class RedFactory extends AbstractFactory{
Pen getPen(){return new RedPen();}
Pen getPencil(){return new RedPencil();}
}//concrete Factory for creating family of Blue
public class BlueFactory extends AbstractFactory{
Pen getPen(){return new BluePen();}
Pen getPencil(){return new BluePencil();}
}
class diagram abstract factory

Builder

used to create complex objects. We are building a complex object using other objects. It is a step-by-step process.

public interface Item{
}
public class Ram extends Item{}
public class Battery extends Item{}
public class Casing extends Item{}
public class OS extends Item{}
public class Phone{
private List<Item> items = new ArrayList<Item>();

public void addItem(Item i){
items.add(i):
}
}//builder class
public abstract class Builder{
public abstract Phone makePhone();
}
//concrete builder class
public class PhoneBuilder extends Builder{
Phone phone;

public Phone makePhone(){
phone = new Phone();
phone.addItem(new Casing);
phone.addItem(new Battery);
phone.addItem(new Ram);
phone.addItem(new OS);
return phone;
}}
builder pattern class diagram

For the Builder design pattern, there is also another way : having the builder class as an inner class

Why?

Because it is strongly related to outer class. achive high cohesion.

Builder class can access the private members of the product class. Do not have to rely on getters and setters.

public class Phone{
private List<Item> items = new ArrayList<Item>();

public void addItem(Item i){
items.add(i):
}
public static class PhoneBuilder {
Phone phone;

public Phone makePhone(){
phone = new Phone();
phone.addItem(new Casing);
phone.addItem(new Battery);
phone.addItem(new Ram);
phone.addItem(new OS);
return phone;
} }}======================
accessing:
Phone phone = new Phone.PhoneBuilder().makePhone();

Builder inner class is defined as static because if the inner class is not static you can’t instantiate it without creating an instance of the outer class.

see more about builder

--

--