0% found this document useful (0 votes)
2 views

Leftover Pattern

The document discusses several design patterns, including the Composite, Flyweight, Bridge, and Builder patterns, highlighting their purposes, applicability, and implementations. The Composite pattern allows treating groups of objects uniformly, while the Flyweight pattern reduces memory usage by sharing identical objects. The Bridge pattern decouples abstraction from implementation, and the Builder pattern separates the construction of complex objects from their representation.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Leftover Pattern

The document discusses several design patterns, including the Composite, Flyweight, Bridge, and Builder patterns, highlighting their purposes, applicability, and implementations. The Composite pattern allows treating groups of objects uniformly, while the Flyweight pattern reduces memory usage by sharing identical objects. The Bridge pattern decouples abstraction from implementation, and the Builder pattern separates the construction of complex objects from their representation.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 107

Composite

pattern
• Composite pattern is used where we need to treat a group of objects in a similar
way as a single object.

• Composite pattern composes objects in terms of a tree structure to represent


part as well as a whole hierarchy.

• This pattern creates a class that contains a group of its own objects. This class
provides ways to modify its group of the same objects.

It is described by Gof:
"Compose objects into a tree structure to represent part-whole
hierarchies. Composite lets client treat individual objects and
compositions of objects uniformly".
• Composite design pattern treats each node in two ways: composite or leaf.
Applicability
Use the Composite pattern when:
• There is a component model with a branch-leaf structure (whole-part
or container-contained).

• The structure can have any level of complexity and is dynamic.

• You want to treat the component structure uniformly, using common


operations throughout the hierarchy.
Participants
• Component
• declares interface for objects in composition.
• implements default behavior for the interface common to all classes as appropriate.
• declares an interface for accessing and managing its child components.
• Leaf
• represents leaf objects in the composition. A leaf has no children.
• defines behavior for primitive objects in the composition.
• Composite
• defines behavior for components having children.
• stores child components.
• implements child related operations in the component interface.
• Client
• manipulates objects in the composition through the component interface.
Example
public interface Employee {
public void add(Employee employee);
public void remove(Employee employee);
public Employee getChild(int i);
public String getName();
public double getSalary();
public void print();
}
public class Manager
implements Employee
{
private String name;
private double salary;
public
Manager(String
name,double salary)
{ this.name = name;
this.salary = salary;
}
List<Employee> employees
= new
ArrayList<Employee>();
public void add(Employee
public Employee getChild(int i)
{
return employees.get(i);
}
public String getName()
{
return name;
}
public double getSalary()
{
return salary;
}
public void print()
{
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Salary ="+getSalary());
System.out.println("-------------");
Iterator<Employee> employeeIterator = employees.iterator();
while(employeeIterator.hasNext())
{
Employee employee = employeeIterator.next();
employee.print();
}
}
public void remove(Employee employee)
{
employees.remove(employee);
}
}
public class Developer implements Employee
{
private String name;
private double salary;
public
Developer(String
name, double salary)
{
this.name = name;
this.salary = salary;
}
public void
add(Employee employee)
{ //this is leaf node so
this method is not
applicable to this class.
}
public Employee
public void print()
{
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Salary ="+getSalary());
System.out.println("-------------"); }
public void remove(Employee employee)
{ //this is leaf node so this method is not
applicable to this class. } }
public class CompositeDesignPatternMain
{
public static void main(String[] args)
{
Employee emp1=new Developer("John", 10000);
Employee emp2=new Developer("David", 15000);
Employee manager1=new Manager("Daniel",25000);
manager1.add(emp1);
manager1.add(emp2);
Employee emp3=new Developer("Michael", 20000);
Manager generalManager=new Manager("Mark", 50000);
generalManager.add(emp3);
generalManager.add(manager1); generalManager.print();
}}
Name =Mark
Salary =50000.0

Name =Michael
Salary =20000.0

Name =Daniel
Salary =25000.0

Name =John
Salary =10000.0

Name =David
Salary =15000.0
Flyweight pattern
Purpose

To reduce the number of very low-level, detailed objects within a system by sharing objects.

Introduction

Object-oriented programming causes many objects to exist during execution, especially if


there are several low-level objects.

This places a big load on the Java Virtual Machine’s (JVM) memory.

One way to alleviate the problem of having many objects is to share objects. Many of these
low-level objects only differ slightly, while most of their state and behaviour are identical.

Sharing instances reduces the number dramatically without losing any functionality.

For a set of objects, the Flyweight pattern separates those parts of the objects that are the
same from the parts that are different.
• The data that distinguishes the different instances (also called the externalized data)
is provided to the single generic instance when needed.

Applicability: Use Flyweight when all of the following are true:

• The application uses many identical, or nearly identical, objects.

• For each nearly identical object, the non-identical parts can be separated from the
identical part allowing that identical part to be shared.

• Groups of nearly identical objects can be replaced by one shared object once the non-
identical parts of the state have been removed.

• If the application needs to distinguish among the nearly identical objects in their original
state.
Implementation
• Flyweight – The interface defines the methods clients can use to pass external state
into the flyweight objects.

• ConcreteFlyweight – This implements the Flyweight interface, and implements the


ability to store internal data. The internal data has to be representative for all the
instances where you need the Flyweight.

• FlyweightFactory– This factory is responsible for creating and managing the


Flyweights. Providing access to Flyweight creation through the factory ensures proper
sharing. The factory can create all the flyweights at the start of the application, or wait
until they are needed.

• Client – The client is responsible for creating and providing the context for the
flyweights. The only way to get a reference to a flyweight is through flyweightFactory.
public interface Shape {
void draw(); }

public class Circle


implements Shape
{
private String color; private int x; private int y; private int radius;
public Circle(String color)
{ this.color = color; }
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
public void setRadius(int radius)
{ this.radius = radius; }
public void draw()
{
System.out.println("Circle:
Draw() [Color : " + color + ",
import java.util.HashMap;

public class ShapeFactory


{
private static final HashMap<String, Shape> circleMap = new HashMap();

public static Shape getCircle(String color)


{
Circle circle = (Circle)circleMap.get(color);
if(circle == null)
{
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creatin
g circle of color : " + color);
}
return circle;
}
public class FlyweightPatternDemo
{
private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" };
public static void main(String[] args)
{
for(int i=0; i < 20; ++i)
{
Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw(); }
}
private static String getRandomColor()
{ return colors[(int)
(Math.random()*colors.length)]; }

private static int getRandomX() { return


(int)(Math.random()*100 ); }
Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10,
radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44,
radius :100 Circle: Draw() [Color : Green, x : 19, y :10,
radius :100 Circle: Draw() [Color : Green, x : 94, y :32,
radius :100 Circle: Draw() [Color : White, x : 69, y :98,
radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4,
radius :100 Circle: Draw() [Color : Green, x : 21, y :21,
radius :100 Circle: Draw() [Color : Blue, x : 55, y :86,
radius :100 Circle: Draw() [Color : White, x : 90, y :70,
radius :100 Circle: Draw() [Color : Green, x : 78, y :3,
radius :100 Circle: Draw() [Color : Green, x : 64, y :89,
radius :100 Circle: Draw() [Color : Blue, x : 3, y :91,
radius :100 Circle: Draw() [Color : Blue, x : 62, y :82,
radius :100 Circle: Draw() [Color : Green, x : 97, y :61,
radius :100 Circle: Draw() [Color : Green, x : 86, y :12,
radius :100 Circle: Draw() [Color : Green, x : 38, y :93,
radius :100 Circle: Draw() [Color : Red, x : 76, y :82,
Bridge Pattern

Use a bridge to “decouple an abstraction from its implementation so


that the two can vary independently” (From [Gamma et al 1995])

Also know as a Handle/Body pattern

Allows different implementations of an interface to be decided upon


dynamically.
Bridge Pattern

Taxonomy in Taxonomy in
Application Domain Solution Domain
Motivation for the Bridge Pattern

Decouples an abstraction from its implementation so that the two can


vary independently
This allows to bind one from many different implementations of an
interface to a client dynamically
Design decision that can be realized any time during the runtime of
the system
However, usually the binding occurs at start up time of the system (e.g. in the constructor of the
interface class)
Using a Bridge
The bridge pattern can be used to provide multiple
implementations under the same interface
Interface to a component that is incomplete (only Stub code is available), not yet known or
unavailable during testing
If seat data are required to be read, but the seat is not yet implemented (only stub code
available), or only available by a simulation (AIM or SART), the bridge pattern can be used:

Seat imp
(in Vehicle Subsystem)
VIP SeatImplementation
GetPosition()
SetPosition()

Stub Code AIMSeat SARTSeat


Seat Implementation
public interface SeatImplementation {
public int GetPosition();
public void SetPosition(int newPosition);
}
public class Stubcode implements SeatImplementation {
public int GetPosition() {
} // stub code for GetPosition
} ...
public class AimSeat implements SeatImplementation {
public int GetPosition() {
} // actual call to the AIM simulation system
} ….
public class SARTSeat implements SeatImplementation {
public int GetPosition() {
// actual call to the SART seat simulator
}...
}
public interface DrawAPI
{ public void drawCircle(int radius, int x,
int y);
}

c class RedCircle implements DrawAPI {


public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", " + y +
}

public class GreenCircle implements DrawAPI {


public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green, radius: " + radius + ", x: " + x + ", "
+ y + "]");
}
}
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw(); }

public class Circle extends Shape {


private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI); this.x = x; this.y = y; this.radius = radius;
}
public void draw() {
drawAPI.drawCircle(radius,x,y);
}
}
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100,100, 10, new RedCircle());
Shape greenCircle = new Circle(100,100, 10, new GreenCircle());
redCircle.draw();
greenCircle.draw();
}
}

Drawing Circle[ color: red, radius: 10, x: 100, 100]


Drawing Circle[ color: green, radius: 10, x: 100, 100]
Intent
Decouple an abstraction from its implementation so that the two can vary independently.
Publish interface in an inheritance hierarchy, and bury implementation in its own inheritance hierarchy.
Beyond encapsulation, to insulation

Problem
"Hardening of the software arteries" has occurred by using subclassing of an abstract base class
to provide alternative implementations.

This locks in compile-time binding between interface and implementation.

The abstraction and implementation cannot be independently extended or composed.


Lets extend previous example:

geometric Shape class with a pair of subclasses: Circle and Square.

You want to extend this class hierarchy to incorporate colors. So you plan to create
Red and Blue shape subclasses. However, since you already have two subclasses,
you’ll need to create four class combinations such as BlueCircle and RedSquare.
Another use of the Bridge Pattern:
Support multiple Database Vendors
Builder
An Object Creational Pattern
Intent / Applicability

Separate the construction of a complex object from its


representation so that the same construction process can
create different representations

Use the Builder pattern when:


the algorithm for creating a complex object should be
independent of the parts that make up the object and how they
are assembled
the construction process must allow different representations for
the object that is constructed

Reference: Design Patterns, Gamma, et. al., Addison Wesley, 1995, pp 97-98
UML Structure
Example: building different types of airplanes

AerospaceEngineer:
director
AirplaneBuilder: abstract
builder
Airplane: product
Sample concrete builders:
CropDuster
FighterJet
Glider
Airliner
Director
package builder;
/** "Director" */
public class AerospaceEngineer {

private AirplaneBuilder airplaneBuilder;

public void setAirplaneBuilder(AirplaneBuilder ab) {


airplaneBuilder = ab;
}

public Airplane getAirplane() {


return airplaneBuilder.getAirplane();
}

public void constructAirplane() {


airplaneBuilder.createNewAirplane();
airplaneBuilder.buildWings();
airplaneBuilder.buildPowerplant();
airplaneBuilder.buildAvionics();
airplaneBuilder.buildSeats();
}
}
AbstractBuilder
package builder;
/** "AbstractBuilder" */
public abstract class AirplaneBuilder {

protected Airplane airplane;


protected String customer;
protected String type;

public Airplane getAirplane() {


return airplane;
}

public void createNewAirplane() {


airplane = new Airplane(customer, type);
}

public abstract void buildWings();

public abstract void buildPowerplant();

public abstract void buildAvionics();

public abstract void buildSeats();

}
Product
package builder;
/** "Product" */
public class Airplane {

private String type;


private float wingspan;
private String powerplant;
private int crewSeats;
private int passengerSeats;
private String avionics;
private String customer;

Airplane (String customer, String type){


this.customer = customer;
this.type = type;
}

public void setWingspan(float wingspan) {


this.wingspan = wingspan;
}
Product (continued)
public void setPowerplant(String powerplant) {
this.powerplant = powerplant;
}

public void setAvionics(String avionics) {


this.avionics = avionics;
}

public void setNumberSeats(int crewSeats, int passengerSeats) {


this.crewSeats = crewSeats;
this.passengerSeats = passengerSeats;
}

public String getCustomer() {


return customer;
}

public String getType() {


return type;
}
}
ConcreteBuilder 1
package builder;
/** "ConcreteBuilder" */
public class CropDuster extends AirplaneBuilder {

CropDuster (String customer){


super.customer = customer;
super.type = "Crop Duster v3.4";
}

public void buildWings() {


airplane.setWingspan(9f);
}

public void buildPowerplant() {


airplane.setPowerplant("single piston");
}

public void buildAvionics() {}

public void buildSeats() {


airplane.setNumberSeats(1,1);
}

}
ConcreteBuilder 2
package builder;
/** "ConcreteBuilder" */
public class FighterJet extends AirplaneBuilder {

FighterJet (String customer){


super.customer = customer;
super.type = "F-35 Lightning II";
}

public void buildWings() {


airplane.setWingspan(35.0f);
}

public void buildPowerplant() {


airplane.setPowerplant("dual thrust vectoring");
}

public void buildAvionics() {


airplane.setAvionics("military");
}

public void buildSeats() {


airplane.setNumberSeats(1,0);

}
ConcreteBuilder 3
package builder;
/** "ConcreteBuilder" */
public class Glider extends AirplaneBuilder {

Glider (String customer){


super.customer = customer;
super.type = "Glider v9.0";
}

public void buildWings() {


airplane.setWingspan(57.1f);
}

public void buildPowerplant() {}

public void buildAvionics() {}

public void buildSeats() {


airplane.setNumberSeats(1,0);

}
ConcreteBuilder 4
package builder;
/** "ConcreteBuilder" */
public class Airliner extends AirplaneBuilder {

Airliner (String customer){


super.customer = customer;
super.type = "787 Dreamliner";
}

public void buildWings() {


airplane.setWingspan(197f);
}

public void buildPowerplant() {


airplane.setPowerplant("dual turbofan");
}

public void buildAvionics() {


airplane.setAvionics("commercial");
}

public void buildSeats() {


airplane.setNumberSeats(8,289);

}
Client Application
package builder;
/** Application in which given types of airplanes are being constructed.
*/
public class BuilderExample {
public static void main(String[] args) {
// instantiate the director (hire the engineer)
AerospaceEngineer aero = new AerospaceEngineer();

// instantiate each concrete builder (take orders)


AirplaneBuilder crop = new CropDuster("Farmer Joe");
AirplaneBuilder fighter = new FighterJet("The Navy");
AirplaneBuilder glider = new Glider("Tim Rice");
AirplaneBuilder airliner = new Airliner("United Airlines");

// build a CropDuster
aero.setAirplaneBuilder(crop);
aero.constructAirplane();
Airplane completedCropDuster = aero.getAirplane();
System.out.println(completedCropDuster.getType() +
" is completed and ready for delivery to " +
completedCropDuster.getCustomer());

// the other 3 builds removed to fit the code on one slide


}
}
Client Application output

Crop Duster v3.4 is completed and ready for


delivery to Farmer Joe

F-35 Lightning II is completed and ready for


delivery to The Navy

Glider v9.0 is completed and ready for


delivery to Tim Rice

787 Dreamliner is completed and ready for


delivery to United Airlines
Builder: Advantages / Disadvantages

Advantages:
Allows you to vary a product’s internal representation
Encapsulates code for construction and representation
Provides control over steps of construction process

Disadvantages:
Requires creating a separate ConcreteBuilder for each different
type of Product
Related Patterns

Factory Method: “class creational” pattern


Provides interface for constructing objects, allowing subclasses
decide which creation class to use
Prototype: an “object creational” pattern
Separates system from object creation and representation, using a
prototypical instance
Abstract Factory: another “object creational” pattern
Also separates system from product creation and representation,
but does not have an abstract builder – application calls the
factory methods directly
Memento
This is a simple calculator that finds the result of addition of two numbers,
with the additional option to undo last operation and restore previous
result.
public interface PreviousCalculationToCareTaker {
// no operations permitted for the caretaker
}

public interface PreviousCalculationToOriginator {


public int getFirstNumber();
public int getSecondNumber();
}
public class PreviousCalculationImp implements PreviousCalculationToCareTaker,
PreviousCalculationToOriginator {

private int firstNumber;


private int secondNumber;
public PreviousCalculationImp(int firstNumber, int secondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber; }
public int getFirstNumber() {
return firstNumber;
}
public int getSecondNumber() {
return secondNumber;
}
}
public interface Calculator {
public PreviousCalculationToCareTaker backupLastCalculation();
public void restorePreviousCalculation(PreviousCalculationToCareTaker memento);
public int getCalculationResult();
public void setFirstNumber(int firstNumber);
public void setSecondNumber(int secondNumber);
}
lic class CalculatorImp implements Calculator {
private int firstNumber;
private int secondNumber;
public PreviousCalculationToCareTaker backupLastCalculation() {
PreviousCalculationImp(firstNumber,secondNumber);
}
public int getCalculationResult() {
firstNumber + secondNumber;
}
public void restorePreviousCalculation(PreviousCalculationToCareTaker memento) {
this.firstNumber = ((PreviousCalculationToOriginator)memento).getFirstNumber();
this.secondNumber = ((PreviousCalculationToOriginator)memento).getSecondNumber
}
public void setFirstNumber(int firstNumber) {
this.firstNumber = firstNumber;
}
public void setSecondNumber(int secondNumber) {
this.secondNumber = secondNumber;
}
public class CalculatorDriver {
public static void main(String[] args) {
Calculator calculator = new CalculatorImp();
calculator.setFirstNumber(10);
calculator.setSecondNumber(100); //
System.out.println(calculator.getCalculationResult());
PreviousCalculationToCareTaker memento = calculator.backupLastCalculation();
calculator.setFirstNumber(17);
calculator.setSecondNumber(-290);
System.out.println(calculator.getCalculationResult());
calculator.restorePreviousCalculation(memento);
System.out.println(calculator.getCalculationResult());
}
}
Motivation
It is sometimes necessary to capture the internal state of an object at some
point and have the ability to restore the object to that state later in time.
Such a case is useful in case of error or failure.
In previous example a calculator object with an undo operation such a calculator
could simply maintain a list of all previous operation that it has performed and
thus would be able to restore a previous calculation it has performed.
This would cause the calculator object to become larger, more complex, and
heavyweight, as the calculator object would have to provide additional undo
functionality and should maintain a list of all previous operations.
This functionality is moved out of the calculator class to the external , so that it
can collect the internal state of the calculator and save it.
Intent
•The intent of this pattern is to capture the internal state of an object without
violating encapsulation and thus providing a mean for restoring the object into
initial state when needed.
Memento
• Stores internal state of the Originator object. The state can include any number of
state variables.
• The Memento must have two interfaces, an interface to the caretaker. This
interface must not allow any operations or any access to internal state stored by
the memento and thus honors encapsulation. The other interface is to the
originator and allows the originator to access any state variables necessary to for
the originator to restore previous state.
Originator
• Creates a memento object capturing the originators internal state.
• Use the memento object to restore its previous state.
Caretaker
• Responsible for keeping the memento.
• The memento is opaque to the caretaker, and the caretaker must not operate on
it.
Example – Proxy pattern

Proxy is a structural pattern that separates an interface from an


implementation into different classes.
Proxy object acts as a surrogate to the real object.
Proxy also controls access to the real object.
Proxy pattern explained

Client always operates with the interface defined in abstract class


Subject
Interface in Subject class is implemented in both Proxy and
RealSubject
The RealSubject class does actual implementation
The Proxy class only delegates any calls to the RealSubject class
Client class always works against the Proxy class
Thus Proxy class controls access to RealSubject
Decoupling Group

Patterns in this group divide a software system into several parts in


such a way that individual parts can be built, changed, replaced, and
reused independently.
The advantage of decoupling is local change, i.e., the system can be
changed by modifying one or only a few parts, instead of changing
everything.
public interface OfficeInternetAccess {
public void grantInternetAccess();
}

public class RealInternetAccess implements OfficeI


nternetAccess {
private String employeeName;
public RealInternetAccess(String empName) {
this.employeeName = empName;
}

public void grantInternetAccess() {


System.out.println("Internet Access granted for
employee: "+ employeeName);
}
}
public class ProxyInternetAccess implements OfficeInternetAccess {
private String employeeName;
private RealInternetAccess realaccess;
public ProxyInternetAccess(String employeeName) {
this.employeeName = employeeName;
}

public void grantInternetAccess()


{
if (getRole(employeeName) > 4)
{
realaccess = new RealInternetAccess(employeeName);
realaccess.grantInternetAccess();
}
else
{
System.out.println("No Internet access granted. Your job level is bel
ow 5");
}
}
public int getRole(String emplName) {

return 9;
}
public class ProxyPatternClient {
public static void main(String[] args)
{
OfficeInternetAccess access = new ProxyInternetAccess(“A
BC");
access.grantInternetAccess();
}
}
Factory
public interface Shape {
void draw();
}

public class Rectangle implements Shape {


public void draw()
{
System.out.println("Inside Rectangle::draw() method.");
}
}
public class Circle implements Shape {
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}

public class Square implements Shape {


public void draw()
{
System.out.println("Inside Square::draw()
method.");
}
}
public class ShapeFactory {
public Shape getShape(String shapeType){
if(shapeType == null)
{
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE"))
{ return new Circle();
}
else if(shapeType.equalsIgnoreCase("RECTANGLE"))
{ return new Rectangle();
}
else if(shapeType.equalsIgnoreCase("SQUARE"))
{ return new Square();
}
return null;
}
}
public class FactoryPatternDemo {
public static void main(String[] args)
{
ShapeFactory shapeFactory = new ShapeFactory();
Shape shape1 = shapeFactory.getShape("CIRCLE");
Circle shape1.draw();
Shape shape2 =
shapeFactory.getShape("RECTANGLE");
shape2.draw();
Shape shape3 =
shapeFactory.getShape("SQUARE");
shape3.draw();
}
}

Inside Circle::draw() method.


Inside Rectangle::draw() method.
Inside Square::draw() method.
Why all this stupid exercise ? We are just
transferring the problem to another class.
One thing to remember is that the Factory may have many clients.
So, by encapsulating the product creating in one class, we now have
only one place to make modifications when the implementation
changes.
Don’t forget, we are also just about to remove the concrete
instantiations from our client code.

The Simple Factory isn’t actually a Design Pattern; it’s more of a


programming idiom. But it is commonly used. Some developers do mistake
this idiom for the “Factory Pattern,”.
Another example
Example 2
Factory Method Pattern
When orderPizza() calls createPizza(),
one of your subclasses will be called into
action to create a pizza.
The Factory
Method
Pattern defines
an interface for
creating an
object, but lets
subclasses
decide which
class to
instantiate.
Factory Method
lets a class
defer
instantiation to
subclasses.

You might also like