You are on page 1of 12

Builder Design Pattern

In the following example, we can define a drink builder called StarbucksBuilder which will build a Starbucks
drink. StarbucksBuilder has several steps to build a Starbucks drink, such as buildSize() and buildDrink(). And
finally return the drink built.

// produce to be built class TeaBuilder extends StarbucksBuilder {


class Starbucks { public void buildSize() {
private String size; starbucks.setSize("large");
private String drink; System.out.println("build large size");
public void setSize(String size) { }
this.size = size; public void buildDrink() {
} starbucks.setDrink("tea");
public void setDrink(String drink) { System.out.println("build tea");
this.drink = drink; }
} }
} // Concrete builder to build coffee
//abstract builder class CoffeeBuilder extends StarbucksBuilder {
abstract class StarbucksBuilder { public void buildSize() {
protected Starbucks starbucks; starbucks.setSize("medium");
public Starbucks getStarbucks() { System.out.println("build medium size");
return starbucks; }
} public void buildDrink() {
public void createStarbucks() { starbucks.setDrink("coffee");
starbucks = new Starbucks(); System.out.println("build coffee");
System.out.println("a drink is created"); }
} }
public abstract void buildSize(); //director to encapsulate the builder
public abstract void buildDrink(); class Waiter {
} private StarbucksBuilder starbucksBuilder;
// Concrete Builder to build tea
Page 1 of 12
public void setStarbucksBuilder(StarbucksBuilder public static void main(String[] args) {
builder) { Waiter waiter = new Waiter();
starbucksBuilder = builder; StarbucksBuilder coffeeBuilder = new
} CoffeeBuilder();
public Starbucks getstarbucksDrink() { waiter.setStarbucksBuilder(coffeeBuilder);
return starbucksBuilder.getStarbucks(); waiter.constructStarbucks();
} //get the drink built
public void constructStarbucks() { Starbucks drink = waiter.getstarbucksDrink();
starbucksBuilder.createStarbucks(); }
starbucksBuilder.buildDrink(); }
starbucksBuilder.buildSize();
}
}
//customer
public class Customer {

Lets implement a cake bakery. A colleague of yours wants to open a bakery and asked you to program a
bakerys software for him. Ingredient is the Part, Recipe is the BuilderContract and Builder is the builder itself.
Cake is the final, customizable product. CakeBuilder is the class which actually creates the product after
customization (after the addition of as many parts ingredients as you want). The client would be the final
client or your colleague taking the order.

public interface Ingredient { public int getDeciLiter() {return deciLiter;}


void printName(); public void setDeciLiter(int deciLiter)
String getUnitPrice(); {this.deciLiter = deciLiter;}
void printCalories(); public int getCalories() {return calories;}
} public void setCalories(int calories) {
public class LightMilk implements Ingredient { this.calories = calories;}
private int deciLiter; public void setUnitPrice(String unitPrice)
private int calories; {this.unitPrice = unitPrice;}
private String unitPrice; }
public LightMilk(int public class Sugar implements Ingredient {
deciLiter){this.deciLiter=deciLiter;} private int gram;
public LightMilk(int deciLiter, int calories, String private int calories;
unitPrice) { private String unitPrice;
super(); public Sugar(int deciLiter){this.gram=deciLiter;}
this.deciLiter = deciLiter; public Sugar(int gram, int calories, String
this.calories = calories; unitPrice) {
this.unitPrice = unitPrice; super();
} this.gram = gram;
@Override this.calories = calories;
public void printName() {System.out.printf(" Light this.unitPrice = unitPrice;
Milk");} }
@Override public String getUnitPrice() {return @Override public void printName()
unitPrice;} {System.out.printf(" Sugar");}
@Override public void printCalories() @Override public String getUnitPrice() {return
{System.out.printf(" 76kc");} unitPrice;}
Page 2 of 12
@Override public void printCalories() this.calories = calories;
{System.out.printf(" 40kc");} this.unitPrice = unitPrice;
public int getGram() {return gram;} }
public void setGram(int gram) { @Override public void printName()
this.gram = gram;} {System.out.printf(" No Sugar");}
public int getCalories() {return calories;} @Override public String getUnitPrice() {return
public void setCalories(int calories) { unitPrice;}
this.calories = calories;} @Override public void printCalories()
public void setUnitPrice(String unitPrice) {System.out.printf(" 0kc");}
{this.unitPrice = unitPrice;} public int getGram() {return gram;}
} public void setGram(int gram) {this.gram =
public class Choco implements Ingredient { gram;}
private int gram; public int getCalories() {return calories;}
private int calories; public void setCalories(int calories) {this.calories
private String unitPrice; = calories;}
public Choco(int gram, int calories, String public void setUnitPrice(String unitPrice)
unitPrice) { {this.unitPrice = unitPrice;}
super(); }
this.gram = gram; public class Milk implements Ingredient {
this.calories = calories; private int deciLiter;
this.unitPrice = unitPrice; private int calories;
} private String unitPrice;
public int getGram() {return gram;} public Milk(int deciLiter){this.deciLiter=deciLiter;}
public void setGram(int gram) {this.gram = public Milk(int deciLiter, int calories, String
gram;} unitPrice) {
public int getCalories() {return calories;} super();
public void setCalories(int calories) {this.calories this.deciLiter = deciLiter;
= calories;} this.calories = calories;
public void setUnitPrice(String unitPrice) this.unitPrice = unitPrice;
{this.unitPrice = unitPrice;} }
@Override public void printName() @Override public void printName()
{System.out.printf(" Chocolate");} {System.out.printf(" Milk");}
@Override public void printCalories() @Override public String getUnitPrice() {return
{System.out.printf(" 389kc");} unitPrice;}
@Override public String getUnitPrice() {return @Override public void printCalories()
unitPrice;} {System.out.printf(" 128kc");}
} public int getDeciLiter() {return deciLiter;}
public class NoSugar implements Ingredient { public void setDeciLiter(int deciLiter)
private int gram; {this.deciLiter = deciLiter;}
private int calories; public int getCalories() {return calories;}
private String unitPrice; public void setCalories(int calories) {this.calories
public NoSugar(int = calories;}
deciLiter){this.gram=deciLiter;} public void setUnitPrice(String unitPrice)
public NoSugar(int gram, int calories, String {this.unitPrice = unitPrice;}
unitPrice) { }
super();
this.gram = gram; public interface Recipe < B > {
Page 3 of 12
B addIngredient(Ingredient ingredient); System.out.println(" - Price: "+muffin);
} }
// 3. define the builder construction method public void printResult(){
// which builds and returns the final product "T" System.out.println(" Cake is ready!");
public interface Builder < T > extends Recipe < }
Builder < T > > { }
T build(); public class Client {
} public static void main(String[] args) {
import java.util.ArrayList; Builder < Cake > chocoMuffinBuilder = new
import java.util.List; CakeBuilder();
// 4. implement the builder acc. to your needs chocoMuffinBuilder.addIngredient(new
public class CakeBuilder implements Builder < Cake Choco(10, 23, "3.39"));
>{ chocoMuffinBuilder.addIngredient(new
// IN THIS CASE THE PARTS ARE THE Milk(34, 67, "1.57"));
INGREDIENTS chocoMuffinBuilder.addIngredient(new
private List < Ingredient > ingredients=new Sugar(34, 67, "2.00"));
ArrayList < Ingredient > ( ); final Cake chocoMuffin =
@Override chocoMuffinBuilder.build();
public Cake build() { chocoMuffin.printResult();
if(!ingredients.isEmpty()){ }
return new Cake(ingredients); }
}
return new Cake(null);
}
public Builder < Cake > addIngredient(Ingredient
ingredient) {
if(ingredient!=null)
ingredients.add(ingredient);
return this;
}
}
import java.util.List;
public class Cake {
public Cake(List < Ingredient > ingredients){
String muffin = "";
if(ingredients==null){
System.out.println(" zero cake "+muffin);
return;
}
// PRINT OUT MUFFIN INGREDIENTS
System.out.printf(" Cake with: ");
for (Ingredient ingredient : ingredients) {
ingredient.printName();
}
for (Ingredient ingredient : ingredients) {
muffin+=" "+ingredient.getUnitPrice();
}
Page 4 of 12
Prototype Design Pattern
Lets understand this pattern using an example. I am creating an entertainment application that will require
instances of Movie, Album and Show classes very frequently. I do not want to create their instances
everytime as it is costly. So, I will create their prototype instances, and everytime when i will need a new
instance, I will just clone the prototype.

PrototypeCapable.java {
package com.howtodoinjava.prototypeDemo.contract; private String name = null;
public interface PrototypeCapable extends Cloneable public String getName() {
{ return name;
public PrototypeCapable clone() throws }
CloneNotSupportedException; public void setName(String name) {
} this.name = name;
}
public class Movie implements PrototypeCapable @Override
{ public Album clone() throws
private String name = null; CloneNotSupportedException {
public String getName() { System.out.println("Cloning Album object..");
return name; return (Album) super.clone();
} }
public void setName(String name) { @Override
this.name = name; public String toString() {
} return "Album";
@Override }
public Movie clone() throws }
CloneNotSupportedException { public class Show implements PrototypeCapable
System.out.println("Cloning Movie object.."); {
return (Movie) super.clone(); private String name = null;
} public String getName() {
@Override return name;
public String toString() { }
return "Movie"; public void setName(String name) {
} this.name = name;
} }
@Override
public class Album implements PrototypeCapable

Page 5 of 12
public Show clone() throws public class TestPrototypePattern{
CloneNotSupportedException { public static void main(String[] args)
System.out.println("Cloning Show object.."); {
return (Show) super.clone(); try
} {
@Override String moviePrototype =
public String toString() { PrototypeFactory.getInstance(ModelType.MOVIE).to
return "Show"; String();
} System.out.println(moviePrototype);
}
PrototypeFactory.java String albumPrototype =
public class PrototypeFactory PrototypeFactory.getInstance(ModelType.ALBUM).to
{ String();
public static class ModelType System.out.println(albumPrototype);
{
public static final String MOVIE = "movie"; String showPrototype =
public static final String ALBUM = "album"; PrototypeFactory.getInstance(ModelType.SHOW).toSt
public static final String SHOW = "show"; ring();
} System.out.println(showPrototype);
private static java.util.Map<String ,
PrototypeCapable> prototypes = new }
java.util.HashMap<String , PrototypeCapable>(); catch (CloneNotSupportedException e)
static {
{ e.printStackTrace();
prototypes.put(ModelType.MOVIE, new }
Movie()); }
prototypes.put(ModelType.ALBUM, new }
Album()); When you run the client code, following is the output.
prototypes.put(ModelType.SHOW, new Show());
} Cloning Movie object..
Movie
public static PrototypeCapable getInstance(final Cloning Album object..
String s) throws CloneNotSupportedException { Album
return ((PrototypeCapable) Cloning Show object..
prototypes.get(s)).clone(); Show
}
}
TestPrototypePattern

Let's say that we have a number of items that can go in the cart - books, cds,
dvds.

Abstract Factory
Lets take an example, suppose we want to build a global car factory. We need car factories in each
location like IndiaCarFactory, USACarFactory and DefaultCarFactory. Now, our application should be
smart enough to identify the location where it is being used, so we should be able to use appropriate
car factory without even knowing which car factory implementation will be used internally. This also
saves us from someone calling wrong factory for a particular location.

enum CarType{ this.location = location;


MICRO, MINI, LUXURY }
} abstract void construct();
abstract class Car{ CarType model = null;
Car(CarType model, Location location){ Location location = null;
this.model = model; CarType getModel() {

Page 6 of 12
return model; return car;
} }}
void setModel(CarType model) { class DefaultCarFactory{
this.model = model; public static Car buildCar(CarType model) {
} Car car = null;
Location getLocation() { switch (model)
return location; {
} case MICRO:
void setLocation(Location location) { car = new MicroCar(Location.DEFAULT);
this.location = location; break;
} case MINI:
public String toString() { car = new MiniCar(Location.DEFAULT);
return "CarModel - "+model + " located in break;
"+location; case LUXURY:
}} car = new LuxuryCar(Location.DEFAULT);
class LuxuryCar extends Car{ break;
LuxuryCar(Location location) { default:
super(CarType.LUXURY, location); break;
construct(); }
} return car; }
protected void construct() { }
System.out.println("Connecting to luxury car"); class USACarFactory{
}} public static Car buildCar(CarType model) {
class MicroCar extends Car{ Car car = null;
MicroCar(Location location) { switch (model) {
super(CarType.MICRO, location); case MICRO:
construct(); car = new MicroCar(Location.USA);
} break;
protected void construct() { case MINI:
System.out.println("Connecting to Micro Car "); car = new MiniCar(Location.USA);
}} break;
class MiniCar extends Car{ case LUXURY:
MiniCar(Location location) { car = new LuxuryCar(Location.USA);
super(CarType.MINI,location ); break;
construct(); default:
} break;
void construct() { }
System.out.println("Connecting to Mini car"); return car;
}} }}
enum Location{ class CarFactory{
DEFAULT, USA, INDIA private CarFactory()
} { }
class INDIACarFactory{ public static Car buildCar(CarType type) {
static Car buildCar(CarType model) { Car car = null;
Car car = null; Location location = Location.INDIA;
switch (model) { switch(location) {
case MICRO: case USA:
car = new MicroCar(Location.INDIA); car = USACarFactory.buildCar(type);
break; break;
case MINI: case INDIA:
car = new MiniCar(Location.INDIA); car = INDIACarFactory.buildCar(type);
break; break;
case LUXURY: default:
car = new LuxuryCar(Location.INDIA); car = DefaultCarFactory.buildCar(type);
break; }
default: return car;
break; }}
} class AbstractDesign {

Page 7 of 12
public static void main(String[] args) { System.out.println(CarFactory.buildCar(CarType.LUXU
System.out.println(CarFactory.buildCar(CarType.MICR RY));
O)); }
System.out.println(CarFactory.buildCar(CarType.MINI)) }
;
We need to create the appropriate object containing the information about cell phone based on the user request of 1.
Type of phone 2. Phone manufacturer. For the sake of simplicity, let's assume we have 3 manufacturers:
1. Nokia
2. Samsung
3. HTC
and there could be two types of phones:
1. Smart Phones
2. Dumb Phones
So with this information, we can safely say that we need three concrete factories (one for each manufacturer) and two
sets of related products (one for smart and one for dumb).
interface IDumb{ public ISmart GetSmart() {
string Name(); return new GalaxyS2(); }
} public IDumb GetDumb() {
interface ISmart{ return new Primo();
string Name(); }}
} class HTCFactory : IPhoneFactory{
class Asha : IDumb{ public ISmart GetSmart() {
public string Name() return new Titan();
{ }
return "Asha"; public IDumb GetDumb() {
} return new Genie();
} }}
class Primo : IDumb{ class NokiaFactory : IPhoneFactory{
public string Name() { public ISmart GetSmart() {
return "Guru"; return new Lumia();
} }
} public IDumb GetDumb() {
class Genie : IDumb{ return new Asha();
public string Name() { }}
return "Genie"; enum MANUFACTURERS{
}} SAMSUNG,
class Lumia : ISmart{ HTC,
public string Name() { NOKIA
return "Lumia"; }
}} class PhoneTypeChecker{
class GalaxyS2 : ISmart{ ISmart sam;
public string Name() { IDumb htc;
return "GalaxyS2"; IPhoneFactory factory;
}} MANUFACTURERS manu;
class Titan : ISmart{ public PhoneTypeChecker(MANUFACTURERS m)
public string Name() { { manu = m; }
return "Titan"; public void CheckProducts() {
}} switch (manu) {
interface IPhoneFactory //'I' stands for interface no case MANUFACTURERS.SAMSUNG:
relation with Iphone factory = new SamsungFactory();
{ break;
ISmart GetSmart(); case MANUFACTURERS.HTC:
IDumb GetDumb(); factory = new HTCFactory();
} break;
class SamsungFactory : IPhoneFactory{ case MANUFACTURERS.NOKIA:
Page 8 of 12
factory = new NokiaFactory(); Console.ReadLine();
break; checker = new
} PhoneTypeChecker(MANUFACTURERS.HTC);
Console.WriteLine(manu.ToString() + ":\nSmart checker.CheckProducts();
Phone: " + factory.GetSmart().Name() + "\nDumb Console.ReadLine();
Phone: " + factory.GetDumb().Name()); checker = new
}} PhoneTypeChecker(MANUFACTURERS.NOKIA);
static void Main(string[] args){ checker.CheckProducts();
PhoneTypeChecker checker = new Console.Read();
PhoneTypeChecker(MANUFACTURERS.SAMSUNG); }
checker.CheckProducts();

Factory Method
We have requirement to create multiple currency e.g. INR, SGD, USD and code should be extensible to accommodate new
Currency as well. Here we have made Currency as interface and all currency would be concrete implementation of Currency
interface. Factory Class will create Currency based upon country and return concrete implementation which will be stored in
interface type. This makes code dynamic and extensible.

interface Currency { class CurrencyFactory {


String getSymbol(); public static Currency createCurrency (String
} country) {
// Concrete Rupee Class code if (country. equalsIgnoreCase ("India")){
class Rupee implements Currency { return new Rupee();
@Override }else if(country. equalsIgnoreCase
public String getSymbol() { ("Singapore")){
return "Rs"; return new SGDDollar();
} }else if(country. equalsIgnoreCase ("US")){
} return new USDollar();
// Concrete SGD class Code }
class SGDDollar implements Currency { throw new IllegalArgumentException("No such
@Override currency");
public String getSymbol() { }
return "SGD"; }
} // Factory client code
} public class Factory {
// Concrete US Dollar code public static void main(String args[]) {
class USDollar implements Currency { String country = args[0];
@Override Currency rupee =
public String getSymbol() { CurrencyFactory.createCurrency(country);
return "USD"; System.out.println(rupee.getSymbol());
} }
} }
// Factroy Class code

In this example, upon receiving the user choice of geometric shape, either Circle
or Rectangle, the factory interface will defer the instantiation to the associated
subclass.
public interface ShapeProcessor { public double calcArea();
static final double PI = 3.14159; public double calcCircumference();
public void setFillColor(int redVal, }
int greenVal, int blueVal); import javax.swing.JOptionPane;
Page 9 of 12
public class Draw { break;
public Draw() { default:
super(); }
} if (myshape != null) {
public static void main(String[] args) { double area = myshape.calcArea();
ShapeProcessor myshape = null; String input = JOptionPane.showMessageDialog(null, "Your " +
JOptionPane.showInputDialog(null, "Enter either input + " has an area of " + area + ".",
circle or rectangle:", "Select a shape", 0); "The area of your shape", 0);
switch (input) { } else {
case "circle": JOptionPane.showConfirmDialog(null, input +
myshape = new Circle(5.6); "Sorry. Your choice doesn't exist in the system.
break; Contact us.", null, 0);
case "rectangle": // defer instantiation to } }// End of Main method
subclass Rectangle }
myshape = new Rectangle(3.2, 5.1);

Singleton Pattern
A Singleton Class must have 3 important things,
1. A private static Instance member
2. A private constructor
3. public static getInstance() to get Instance Member specified in POINT 1
Lazy Initialization: We create the object of the class only when it is about to use in the program code. We
are calling it lazy because we wait till the last moment to have an object.
Early Initialization: In this we create the object when the class is getting loaded into the JVM.
Eager initialization is helpful if our application always create and use the Singleton class.

Consider , You have a MUSIC STORE in your IPod That has many categories(as of now in program I have
considered Devotional Songs and Pop Songs). PopSongs and DevotionalSongs are two classes that
implement the Interface IMusicAction. Consider the interface has a method Play(), that is implemented in
both the classes PopSongs and DevotionalSongs, but performing different playAction.

Hold On! Have you noticed that both the classes are of DEFAULT type and NOT Public.
Can you reason out why????

Tats bacause I do not want these classes to be accessed out anywhere out of this package. i.e., Its access
is only within that package(com.aishu.practice.access).
Page 10 of 12
Now lets create the MUSICSTORE.We are going to make it Singleton which means a SINGLE
STORE(a SINGLEINSTANCE) having different song types(holding TONS OF INSTANCES)

class SingletonExample { }
// Static member holds only one instance of the public void printSingleton(){
// SingletonExample class (Lazy Instantiation) System.out.println("Inside print Singleton");
private static SingletonExample singletonInstance; }
// SingletonExample prevents any other class from }
instantiating class Ideone
private SingletonExample() { {
} public static void main (String[] args) throws
// Providing Global point of access java.lang.Exception
public static SingletonExample getSingletonInstance() { {
if (null == singletonInstance) { SingletonExample.getSingletonInstance().printSingleton();
singletonInstance = new SingletonExample(); SingletonExample.getSingletonInstance().printSingleton();
System.out.println("Creating new instance"); }
} }
return singletonInstance;

Design a small ATM printing application which can


generate multiple types of statements of the
transaction including Mini Statement, Detailed
statement etc. However the customer should be
aware of the creation of these statements. Ensure
that the memory consumption is minimized.

Factory.java

Page 11 of 12
public abstract class Factory { public static void main(String[] args) {
protected abstract StatementType createStatements(String System.out.println("Enter your selection:");
selection); BufferedReader br = new BufferedReader(new
} InputStreamReader(System.in));
StatementFactory.java String selection = null;
try {
public class StatementFactory extends Factory { selection = br.readLine();
private static StatementFactory uniqueInstance; } catch (IOException e) {
private StatementFactory() { e.printStackTrace();
} }
public static StatementFactory getUniqueInstance() { Factory factory =
if (uniqueInstance == null) { StatementFactory.getUniqueInstance();
uniqueInstance = new StatementFactory(); StatementType objStmtType =
System.out.println("Creating a new factory.createStatements(selection);
StatementFactory instance"); System.out.println(objStmtType.print());
} }
return uniqueInstance; }
}
public StatementType createStatements(String
selection) {
if (selection.equalsIgnoreCase("detailedStmt")) {
return new DetailedStatement();
} else if (selection.equalsIgnoreCase("miniStmt")) {
return new MiniStatement();
}
throw new IllegalArgumentException("Selection
doesnot exist");
}
}

StatementType.java

public interface StatementType {


String print();
}

DetailedStatement.java

public class DetailedStatement implements StatementType


{
@Override
public String print() {
System.out.println("Detailed Statement Created");
return "detailedStmt";
}
}

MiniStatement.java

public class MiniStatement implements StatementType {


@Override
public String print() {
System.out.println("Mini Statement Created");
return "miniStmt";
}
}

Client.java
public class Client {

Page 12 of 12

You might also like