Behavioral design patterns
Part-2
Purpose
Creational Structural Behavioral
Interpreter
Class Factory Method Adapter
Template Method
Chain of Responsibility
Command
Scope Adapter Iterator
Abstract Factory Bridge Mediator
Builder Composite
Object Prototype Decorator Façade Memento
Singleton Flyweight Observer
Proxy State
Strategy
Visitor
Chain of Responsibility
Design Pattern
Chain of Responsibility Design Pattern
Chain of responsibility pattern is used to achieve loose coupling in
software design where a request from the client is passed to a chain
of objects to process them.
Later, the object in the chain will decide themselves who will be
processing the request and whether the request is required to be sent
to the next object in the chain or not.
When to use Chain of Responsibility pattern :
• Use the CoR pattern when your program is expected to process
different kinds of requests in various ways, but the exact types
of requests and their sequences are unknown beforehand.
• Use the pattern when it’s essential to execute several handlers in
a particular order.
• Use the CoR pattern when the set of handlers and their order are
supposed to change at runtime.
Interface
Components
Handler : This can be an interface which will primarily receive the request
and dispatches the request to chain of handlers. It has reference of
only first handler in the chain and does not know anything about
rest of the handlers.
Concrete handlers : These are actual handlers of the request chained
in some sequential order.
Client : Originator of request and this will access the handler to
handle it.
How to send a request in the application using the Chain of
Responsibility
• The Client in need of a request to be handled sends it to the chain of
handlers which are classes that extend the Handler class.
• Each of the handlers in the chain takes its turn at trying to handle the
request it receives from the client.
• If ConcreteHandler1 can handle it, then the request is handled, if
not it is sent to the handler ConcreteHandler2, the next one in the
chain.
Lets see an Example of Chain of Responsibility Design
Pattern:
interface Chain
{
public abstract void setNext(Chain nextInChain);
public abstract void process(Number request);
}
class Number
{
private int number;
public Number(int number)
{
this.number = number;
}
public int getNumber()
{
return number;
}
}
class NegativeProcessor implements Chain
{
private Chain nextInChain;
public void setNext(Chain c)
{
nextInChain = c;
}
public void process(Number request)
{
if (request.getNumber() < 0)
{
System.out.println("NegativeProcessor : " + request.getNumber());
}
else
{
nextInChain.process(request);
}
}
}
class ZeroProcessor implements Chain
{
private Chain nextInChain;
public void setNext(Chain c)
{
nextInChain = c;
}
public void process(Number request)
{
if (request.getNumber() == 0)
{
System.out.println("ZeroProcessor : " + request.getNumber());
}
else
{
nextInChain.process(request);
}
}
}
class PositiveProcessor implements Chain
{
private Chain nextInChain;
public void setNext(Chain c)
{
nextInChain = c;
}
public void process(Number request)
{
if (request.getNumber() > 0)
{
System.out.println("PositiveProcessor : " + request.getNumber());
}
else
{
nextInChain.process(request);
}
}
}
class TestChain
{
public static void main(String[] args) {
//configure Chain of Responsibility
Chain c1 = new NegativeProcessor();
Chain c2 = new ZeroProcessor();
Chain c3 = new PositiveProcessor();
c1.setNext(c2);
c2.setNext(c3);
//calling chain of responsibility
c1.process(new Number(90));
c1.process(new Number(-50));
c1.process(new Number(0));
c1.process(new Number(91));
}
}
Output :
Positive Processor : 90
Negative Processor : -50
Zero Processor :
0 Positive Processor : 91
Advantages of Chain of Responsibility Design Pattern
• To reduce the coupling degree. Decoupling it will request the sender
and receiver.
• Simplified object. The object does not need to know the chain structure.
• Enhance flexibility of object assigned duties. By changing the
members within the chain or change their order, allow dynamic adding or
deleting responsibility.
• Increase the request processing new class of very convenient.
Dis-Advantages of Chain of Responsibility Design Pattern
• The request must be received is not guarantee.
• The performance of the system will be affected, but also in the
code debugging is not easy may cause cycle call.
• It may not be easy to observe the characteristics of operation,
due to debug.
Interpreter Design Pattern
Interpreter Design Pattern
• Interpreter pattern is used to define a grammatical
representation for a language and provides an interpreter to
deal with this grammar.
• This pattern involves implementing an expression interface which tells
to interpret a particular context.
• This pattern is used in SQL parsing, symbol processing engine
etc.
• This pattern performs upon a hierarchy of expressions. Each
expression here is a terminal or non-terminal.
• The tree structure of Interpreter design pattern is somewhat similar to
that defined by the composite design pattern with terminal expressions
being leaf objects and non-terminal expressions being composites.
• The tree contains the expressions to be evaluated and is usually
generated by a parser. The parser itself is not a part of the interpreter
pattern.
• For Example :
Here is the hierarchy of expressions for “+ – 9 8 7” :
Implementing the Interpreter Pattern
UML Diagram Interpreter Design Pattern
Design components
• Abstract Expression (Expression): Declares an interpret() operation
that all nodes (terminal and nonterminal) in the AST overrides.
• Terminal Expression (Number Expression): Implements the
interpret() operation for terminal expressions.
• Nonterminal Expression (Addition Expression, Subtraction
Expression, and Multiplication Expression): Implements the
interpret() operation for all nonterminal expressions.
• Context (String): Contains information that is global to the
interpreter. It is this String expression with the Postfix notation that has
to be interpreted and parsed.
• Client (Expression Parser): Builds (or is provided) the AST
assembled from Terminal Expression and Non Terminal Expression.
The Client invokes the interpret() operation.
• Let’s see an example of Interpreter Design Pattern.
// Expression interface used to
// check the interpreter.
interface Expression
{
boolean interpreter(String con);
}
// TerminalExpression class implementing
// the above interface. This interpreter
// just check if the data is same as the
// interpreter data.
class TerminalExpression implements Expression
{
String data;
public TerminalExpression(String data)
{
this.data = data;
}
public boolean interpreter(String con)
{
if(con.contains(data))
{
return true;
}
else
{
return false;
}
}
}
// OrExpression class implementing
// the above interface. This interpreter
// just returns the or condition of the
// data is same as the interpreter data.
class OrExpression implements Expression
{
Expression expr1;
Expression expr2;
public OrExpression(Expression expr1, Expression expr2)
{
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpreter(String con)
{
return expr1.interpreter(con) || expr2.interpreter(con);
}
}
// AndExpression class implementing
// the above interface. This interpreter
// just returns the And condition of the
// data is same as the interpreter data.
class AndExpression implements Expression
{
Expression expr1;
Expression expr2;
public AndExpression(Expression expr1, Expression expr2)
{
this.expr1 = expr1;
this.expr2 = expr2;
}
public boolean interpreter(String con)
{
return expr1.interpreter(con) && expr2.interpreter(con);
}
}
// Driver class
class InterpreterPattern
{
public static void main(String[] args)
{
Expression person1 = new TerminalExpression("Kushagra");
Expression person2 = new TerminalExpression("Lokesh");
Expression isSingle = new OrExpression(person1, person2);
Expression vikram = new TerminalExpression("Vikram");
Expression committed = new TerminalExpression("Committed");
Expression isCommitted = new AndExpression(vikram, committed);
System.out.println(isSingle.interpreter("Kushagra"));
System.out.println(isSingle.interpreter("Lokesh"));
System.out.println(isSingle.interpreter("Achint"));
System.out.println(isCommitted.interpreter("Committed, Vikram"));
System.out.println(isCommitted.interpreter("Single, Vikram"));
}
}
Output:
true
true
false
True
false
• In the above code , We are creating an interface Expression and concrete classes
implementing the Expression interface. A class Terminal Expression is defined
which acts as a main interpreter and other classes Or Expression, And
Expression are used to create combinational expressions.
Advantages
• It’s easy to change and extend the grammar. Because the pattern uses
classes to represent grammar rules, you can use inheritance to change
or extend the grammar. Existing expressions can be modified
incrementally, and new expressions can be defined as variations on old ones.
• Implementing the grammar is easy, too. Classes defining nodes in the
abstract syntax tree have similar implementations. These classes are easy to
write, and often their generation can be automated with a compiler or parser
generator.
Disadvantages
• Complex grammars are hard to maintain.
• The Interpreter pattern defines at least one class for every rule in the
grammar.
• Hence grammars containing many rules can be hard to manage and
maintain.
Memento design pattern
Memento design pattern
• Memento pattern that lets you save and restore the previous state
of an object without revealing the details of its
implementation.
UML Diagram Memento design pattern
Design components
Originator : The Originator class can produce snapshots of its own
state, as well as restore its state from snapshots when needed.
Memento : The Memento is a value object that acts as a snapshot of the
originator’s state. It’s a common practice to make the memento immutable
and pass it the data only once, via the constructor.
Caretaker : The Caretaker knows not only “when” and “why” to capture the
originator’s state, but also when the state should be restored.
A caretaker can keep track of the originator’s history by storing a
stack of mementos. When the originator has to travel back in history, the
caretaker fetches the topmost memento from the stack and passes it to the
originator’s restoration method.
• A Caretaker would like to perform an operation on the Originator
while having the possibility to rollback.
• The caretaker calls the create Memento() method on the originator
asking the originator to pass it a memento object.
• At this point the originator creates a memento object saving its internal
state and passes the memento to the caretaker.
• The caretaker maintains the memento object and performs the
operation.
• In case of the need to undo the operation, the caretaker calls the set
Memento() method on the originator passing the maintained memento
object.
• The originator would accept the memento, using it to restore its
previous state.
• Let’s see an example of Memento design pattern.
import java.util.List;
import java.util.ArrayList;
class Life
{
private String time;
public void set(String time)
{
System.out.println("Setting time to " + time);
this.time = time;
}
public Memento saveToMemento()
{
System.out.println("Saving time to Memento");
return new Memento(time);
}
public void restoreFromMemento(Memento memento)
{
time = memento.getSavedTime();
System.out.println("Time restored from Memento: " + time);
}
public static class Memento
{
private final String time;
public Memento(String timeToSave)
{
time = timeToSave;
}
public String getSavedTime()
{
return time;
}
}
}
class Design
{
public static void main(String[] args)
{
List<Life.Memento> savedTimes = new ArrayList<Life.Memento>();
Life life = new Life();
//time travel and record the eras
life.set("1000 B.C.");
savedTimes.add(life.saveToMemento());
life.set("1000 A.D.");
savedTimes.add(life.saveToMemento());
life.set("2000 A.D.");
savedTimes.add(life.saveToMemento());
life.set("4000 A.D.");
life.restoreFromMemento(savedTimes.get(0));
}
}
• Output:
Setting time to 1000 B.C.
Saving time to Memento
Setting time to 1000 A.D.
Saving time to Memento
Setting time to 2000 A.D.
Saving time to Memento
Setting time to 4000 A.D.
Time restored from Memento: 1000 B.C.
Advantage
• We can use Serialization to achieve memento pattern
implementation that is more generic rather than Memento pattern where
every object needs to have it’s own Memento class implementation.
Disadvantage
• If Originator object is very huge then Memento object size
will also be huge and use a lot of memory.
State Design Pattern
State Design Pattern
• State design pattern is used when an Object changes its behavior
based on its internal state.
• If we have to change behavior of an object based on its state, we
can have a state variable in the Object and use if-else
condition block to perform different actions based on the state.
• State pattern is used to provide a systematic and lose-coupled
way to achieve this through Context and State implementations.
UML Diagram of State Design Pattern
• Context: Defines an interface to client to interact. It maintains
references to concrete state object which may be used to
define current state of object.
• State: Defines interface for declaring what each concrete state
should do.
• Concrete State: Provides implementation for methods defined in
State.
Example of State Design Pattern
• In below example, we have implemented a mobile state scenario . With
respect to alerts, a mobile can be in different states.
For example,
• vibration and silent. Based on this alert state, behavior of the mobile
changes when an alert is to be done.
// Java program to demonstrate working of
// State Design Pattern
interface MobileAlertState
{
public void alert(AlertStateContext ctx);
}
class AlertStateContext
{
private MobileAlertState currentState;
public AlertStateContext()
{
currentState = new Vibration();
}
public void setState(MobileAlertState state)
{
currentState = state;
}
public void alert()
{
currentState.alert(this);
}
}
class Vibration implements MobileAlertState
{
@Override
public void alert(AlertStateContext ctx)
Output:
{
System.out.println("vibration...");
}
}
vibration...
class Silent implements MobileAlertState
{
vibration...
@Override
public void alert(AlertStateContext ctx)
silent...
{
System.out.println("silent..."); silent...
}
}
silent...
class StatePattern
{
public static void main(String[] args)
{
AlertStateContext stateContext = new AlertStateContext();
stateContext.alert();
stateContext.alert();
stateContext.setState(new Silent());
stateContext.alert();
stateContext.alert();
stateContext.alert();
}
}
When to Use the State pattern
Use the State pattern when you have an object that behaves
differently depending on its current state, the number of
states is enormous, and the state-specific code changes frequently.
Use the pattern when you have a class polluted with massive
conditionals that alter how the class behaves according to the current
values of the class’s fields.
Use State when you have a lot of duplicate code across similar
states and transitions of a condition-based state machine.
Advantages of State Design Pattern
• With State pattern, the benefits of implementing polymorphic
behavior are evident, and it is also easier to add states to
support additional behavior.
• In the State design pattern, an object’s behavior is the result of the
function of its state, and the behavior gets changed at runtime
depending on the state. This removes the dependency on the
if/else or switch/case conditional logic. For example, in the TV remote
scenario, we could have also implemented the behavior by simply
writing one class and method that will ask for a parameter and perform
an action (switch the TV on/off) with an if/else block.
• The State design pattern also improves Cohesion since state-specific
behaviors are aggregated into the Concrete State classes, which are
placed in one location in the code.
Disadvantages of State Design Pattern
• The State design pattern can be used when we need to change state
of object at runtime by inputting in it different subclasses of some
State base class. This circumstance is advantage and
disadvantage in the same time, because we have a clear separate
State classes with some logic and from the other hand the number of
classes grows up.
Template Method Design Pattern
Template Method Design Pattern
• Template method design pattern is to defines the skeleton of an
algorithm in the super class and leave the details to be
implemented by the child classes.
• The overall structure and sequence of the algorithm is
preserved by the parent class.
• Template means Preset format like HTML templates which has fixed
preset format. Similarly in template method pattern, we have a preset
structure method called template method which consists of
steps. This steps can be abstract method which will be implemented
by its subclasses.
• This behavioral design pattern is one of the easiest to understand
and implement.
• This design pattern is used popularly in framework development.
• This helps to avoid code duplication also.
• Abstract Class contains the template Method() which should be made
final so that it cannot be overridden. This template method makes use
of other operations available in order to run the algorithm but is
decoupled for the actual implementation of these methods. All
operations used by this template method are made abstract, so their
implementation is deferred to subclasses.
• Concrete Class implements all the operations required by the template
Method that were defined as abstract in the parent class. There can be
many different Concrete Classes.
• Lets see an example of the template method pattern.
abstract class OrderProcessTemplate public abstract void doDelivery();
{
public boolean isGift; public final void processOrder(boolean isGift)
{
public abstract void doSelect(); doSelect();
doPayment();
public abstract void doPayment(); if (isGift) {
giftWrap();
public final void giftWrap() }
{ doDelivery();
try }
{ }
System.out.println("Gift wrap successfull");
}
catch (Exception e)
{
System.out.println("Gift wrap unsuccessful");
}
}
class NetOrder extends OrderProcessTemplate
{
@Override
public void doSelect()
{
System.out.println("Item added to online shopping cart");
System.out.println("Get gift wrap preference");
System.out.println("Get delivery address.");
}
@Override
public void doPayment()
{
System.out.println
("Online Payment through Netbanking, card or Paytm");
}
@Override
public void doDelivery()
{
System.out.println
("Ship the item through post to delivery address");
}
}
class StoreOrder extends OrderProcessTemplate
{
@Override
public void doSelect()
{
System.out.println("Customer chooses the item from shelf.");
}
@Override
public void doPayment()
{
System.out.println("Pays at counter through cash/POS");
}
@Override
public void doDelivery()
{
System.out.println("Item deliverd to in delivery counter.");
}
}
class TemplateMethodPatternClient
{
public static void main(String[] args)
{
OrderProcessTemplate netOrder = new NetOrder();
netOrder.processOrder(true);
System.out.println();
OrderProcessTemplate storeOrder = new StoreOrder();
storeOrder.processOrder(true);
}
}
Output :
Item added to online shopping cart
Get gift wrap preference
Get delivery address.
Online Payment through Netbanking,card or Paytm
Gift wrap successfull
Ship the item through post to delivery address
Customer chooses the item from shelf.
Pays at counter through cash/POS
Gift wrap successful
Item deliverd to in delivery counter.
• The above example deals with order processing flow. The Order
Process Template class is an abstract class containing the algorithm
skeleton. As shown on note, process Order() is the method that contains
the process steps. We have two subclasses Net Order and Store Order
which has the same order processing steps.
• So the overall algorithm used to process an order is defined in the base
class and used by the subclasses. But the way individual operations are
performed vary depending on the subclass.
When to use template method
• The template method is used in frameworks, where each implements
the invariant parts of a domain’s architecture, leaving “placeholders”
for customization options.
The template method is used for the following reasons :
• Let subclasses implement varying behavior (through method
overriding)
• Avoid duplication in the code , the general workflow structure is
implemented once in the abstract class’s algorithm, and necessary
variations are implemented in the subclasses.
• Control at what points subclassing is allowed. As opposed to a simple
polymorphic override, where the base method would be entirely
rewritten allowing radical change to the workflow, only the specific
details of the workflow are allowed to change.
Mediator design pattern
Mediator design pattern
• Mediator is a behavioral design pattern that lets you reduce chaotic
dependencies between objects.
• The pattern restricts direct communications between the
objects and forces them to collaborate only via a mediator
object.
• Air traffic controller is a great example of mediator pattern where
the airport control room works as a mediator for communication
between different flights. Mediator works as a router between objects
and it can have it’s own logic to provide way of communication.
UML Diagram Mediator design pattern
Design components
• Mediator :It defines the interface for communication between
colleague objects.
• Concrete Mediator : It implements the mediator interface and
coordinates communication between colleague objects.
• Colleague : It defines the interface for communication with
other colleagues.
• Concrete Colleague : It implements the colleague interface and
communicates with other colleagues through its mediator.
Let’s see an example of Mediator design pattern.
class ATCMediator implements IATCMediator
{
private Flight flight;
private Runway runway;
public boolean land;
public void registerRunway(Runway runway)
{
this.runway = runway;
}
public void registerFlight(Flight flight)
{
this.flight = flight;
}
public boolean isLandingOk()
{
return land;
}
@Override
public void setLandingStatus(boolean status)
{
land = status;
}
}
interface Command
{
void land();
}
interface IATCMediator
{
public void registerRunway(Runway runway);
public void registerFlight(Flight flight);
public boolean isLandingOk();
public void setLandingStatus(boolean status);
}
class Flight implements Command
{
private IATCMediator atcMediator;
public Flight(IATCMediator atcMediator)
{
this.atcMediator = atcMediator;
}
public void land()
{
if (atcMediator.isLandingOk())
{
System.out.println("Successfully Landed.");
atcMediator.setLandingStatus(true);
}
else
System.out.println("Waiting for landing.");
}
public void getReady()
{
System.out.println("Ready for landing.");
}
}
class Runway implements Command
{
private IATCMediator atcMediator;
public Runway(IATCMediator atcMediator)
{
this.atcMediator = atcMediator;
atcMediator.setLandingStatus(true);
}
@Override Output:
public void land() Ready for landing.
{ Landing permission granted.
System.out.println("Landing permission granted."); Successfully Landed.
atcMediator.setLandingStatus(true);
}
}
class MediatorDesignPattern
{
public static void main(String args[])
{
IATCMediator atcMediator = new ATCMediator();
Flight sparrow101 = new Flight(atcMediator);
Runway mainRunway = new Runway(atcMediator);
atcMediator.registerFlight(sparrow101);
atcMediator.registerRunway(mainRunway);
sparrow101.getReady();
mainRunway.land();
sparrow101.land();
}
}
Advantage
• It limits sub-classing. A mediator localizes behavior that otherwise
would be distributed among several objects. Changing this behavior
requires sub-classing Mediator only, Colleague classes can be reused as
is.
Disadvantage
• It centralizes control. The mediator pattern trades complexity of
interaction for complexity in the mediator. Because a mediator
encapsulates protocols, it can become more complex than any
individual colleague. This can make the mediator itself a monolith
that’s hard to maintain
Thank You