Design Pattern
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.
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.
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.
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.
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;
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
DetailedStatement.java
MiniStatement.java
Client.java
public class Client {
Page 12 of 12