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

Behavioral Design Patterns

The document discusses various behavioral design patterns in Java, specifically focusing on the Command, Interpreter, and Chain of Responsibility patterns. Each pattern is explained with its components, implementation details, and example code to illustrate its functionality. The Command pattern allows for encapsulating requests as objects, the Interpreter pattern defines a grammar representation for interpreting sentences, and the Chain of Responsibility pattern creates a chain of receivers to handle requests based on their type.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Behavioral Design Patterns

The document discusses various behavioral design patterns in Java, specifically focusing on the Command, Interpreter, and Chain of Responsibility patterns. Each pattern is explained with its components, implementation details, and example code to illustrate its functionality. The Command pattern allows for encapsulating requests as objects, the Interpreter pattern defines a grammar representation for interpreting sentences, and the Chain of Responsibility pattern creates a chain of receivers to handle requests based on their type.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Object Oriented Programming

BITS Pilani Dr. Tanmaya Mahapatra and Asish Bera


Computer Science & Information Systems
Pilani Campus
BITS Pilani
Pilani Campus

Behavioral Design Patterns in Java


(Module- 10c)
Command Design Patterns

Command pattern is a data driven behavioral design pattern category.


A request is wrapped under an object as command and passed to invoker object.
Invoker object looks for the appropriate object which can handle this command
and passes the command to the corresponding object which executes the
command.

BITS Pilani, Pilani Campus


Description

Command: an interface for executing an


operation.
ConcreteCommand This class extends the
Command interface and implements the
execute method. This class creates a binding
between the action and the receiver.
Client This class creates the ConcreteCommand
class and associates it with the receiver.
Invoker This class asks the command to carry
out the request.
Receiver This class knows to perform the
operation.

BITS Pilani, Pilani Campus


Implementation

• create an interface Order which is acting as a command.


• create a Stock class which acts as a request.
• classes BuyStock and SellStock implementing Order interface which will
perform actual command processing.
• A class Broker is created which acts as an invoker object. It can take and place
orders.
• Broker object uses command pattern to identify which object will execute which
command based on the type of command.
• CommandPatternDemo, our demo class, will use Broker class to demonstrate
command pattern.

BITS Pilani, Pilani Campus


Example

Command pattern requires implementing four


components: the Command, the Receiver, the
Invoker, and the Client.

BITS Pilani, Pilani Campus


Code
// Create a command interface.
public interface Order { // Create a concrete class implementing Order interface.
void execute();
public class BuyStock implements Order {
}
private Stock abcStock;
// Create a request class.
public class Stock { public BuyStock(Stock abcStock){
private String name = "ABC"; this.abcStock = abcStock;
private int quantity = 10; }
public void buy(){
System.out.println("Stock [ Name: "+name+", public void execute() {
Quantity: " + quantity +" ] bought"); } abcStock.buy();
public void sell(){ }
System.out.println("Stock [ Name: "+name+", }
Quantity: " + quantity +" ] sold");
}
}
BITS Pilani, Pilani Campus
Contd…

// Create sell-stock class implementing Order interface.


public class SellStock implements Order { //Create command invoker class.
private Stock abcStock; import java.util.ArrayList;
import java.util.List;
public SellStock(Stock abcStock){ public class Broker {
this.abcStock = abcStock; private List<Order> orderList = new ArrayList<Order>();
} public void takeOrder(Order order){
orderList.add(order);
public void execute() { }
abcStock.sell(); public void placeOrders(){
for (Order order : orderList) {
}
order.execute(); }
} orderList.clear();
}
}
BITS Pilani, Pilani Campus
Contd…
// use Broker class to take and execute commands.

public class CommandPatternDemo {


public static void main(String[] args) {
Stock abcStock = new Stock();
BuyStock buyStockOrder = new BuyStock(abcStock);
SellStock sellStockOrder = new SellStock(abcStock);
Broker broker = new Broker();
broker.takeOrder(buyStockOrder); Verify the output.
broker.takeOrder(sellStockOrder);
Stock [ Name: ABC, Quantity: 10 ] bought
broker.placeOrders(); Stock [ Name: ABC, Quantity: 10 ] sold
}
}
BITS Pilani, Pilani Campus
Interpreter Pattern

An Interpreter Pattern says that "to define a representation of grammar of a


given language, along with an interpreter that uses this representation
to interpret sentences in the language".
Interpreter pattern only in terms of formal grammars but in this area there are
better solutions that is why it is not frequently used.
This pattern can applied for parsing the expressions defined in simple
grammars and sometimes in simple rule engines.

It is easier to change and extend the grammar.


Implementing the grammar is straightforward.

Example: SQL Parsing, symbol processing engine etc. uses interpreter design
pattern.
BITS Pilani, Pilani Campus
Description
Design components
•AbstractExpression (Expression): Declares an interpret()
operation that all nodes (terminal and nonterminal) in the
design overrides.
•TerminalExpression (NumberExpression): Implements
the interpret() operation for terminal expressions.
•NonterminalExpression (AdditionExpression,
SubtractionExpression, and MultiplicationExpression):
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 (ExpressionParser): Builds (or is provided) the AST
assembled from TerminalExpression and
NonTerminalExpression. A Client invokes interpret() operation.

BITS Pilani, Pilani Campus


Description

AbstractExpression defines one abstract method which takes the context as a


parameter. Thanks to that, each expression will affect the context, change its
state and either continue the interpretation or return the result itself.
Therefore, the context is going to be the holder of the global state of processing, and
it’s going to be reused during the whole interpretation process.
So what’s the difference between
the TerminalExpression and NonTerminalExpression?
A NonTerminalExpression may have one or more
other AbstractExpressions associated in it, therefore it can be recursively
interpreted. In the end, the process of interpretation has to finish with a
TerminalExpression that will return the result.
It’s worth to note that NonTerminalExpression is a composite.
the role of the client is to create or use an already created abstract syntax tree, which
is nothing more than a sentence defined in the created language.

BITS Pilani, Pilani Campus


Terminal and non-terminal symbols
Consider the following Parse grammar:
greeting: ['hi | 'hello | 'howdy]
person: [name surname]
name: ['john | 'jane]
surname: ['doe | 'smith]
sentence: [greeting person]

greeting, person, name, surname and sentence are non-terminals (because


they never actually appear in the linear input sequence, only in grammar
rules);
hi, hello, howdy with john, jane, doe and smith are terminals (because
parser cannot "expand" them into a set of terminals and non-terminals as it
does with non-terminals, hence it "terminates" by reaching the bottom).
>> parse [howdy john smith] sentence
== true
>> parse [wazzup bubba ?] sentence
== false

BITS Pilani, Pilani Campus


Example

//Create an expression interface.


public interface Expression {
public boolean interpret(String context);
}

//Create concrete classes implementing interface


public class TerminalExpression implements
Expression {
private String data;
public TerminalExpression(String data){
this.data = data; }
public boolean interpret(String context) {
if(context.contains(data)){
return true; }
return false; }
}
BITS Pilani, Pilani Campus
Code
public class OrExpression implements Expression {

private Expression expr1 = null;


private Expression expr2 = null;

public OrExpression(Expression expr1, Expression expr2) {


this.expr1 = expr1;
this.expr2 = expr2;
}

public boolean interpret(String context) {


return expr1.interpret(context) || expr2.interpret(context);
}
}

BITS Pilani, Pilani Campus


Contd ..
public class AndExpression implements Expression {

private Expression expr1 = null;


private Expression expr2 = null;

public AndExpression(Expression expr1, Expression expr2) {


this.expr1 = expr1;
this.expr2 = expr2;
}

public boolean interpret(String context) {


return expr1.interpret(context) && expr2.interpret(context);
}
}

BITS Pilani, Pilani Campus


Contd..
InterpreterPatternDemo uses Expression class to create rules and then parse them
public class InterpreterPatternDemo {

//Rule: Robert and John are male


public static void main(String[] args) {
public static Expression getMaleExpression(){ Expression isMale = getMaleExpression();
Expression robert = new TerminalExpression("Robert"); Expression isMarriedWoman =
Expression john = new TerminalExpression("John"); getMarriedWomanExpression();
return new OrExpression(robert, john); } System.out.println("John is male? " +
isMale.interpret("John"));
//Rule: Julie is a married women System.out.println("Julie is a married
public static Expression getMarriedWomanExpression(){ women? " +
isMarriedWoman.interpret("Married
Expression julie = new TerminalExpression("Julie"); Julie")); }
Expression married = new TerminalExpression("Married"); }
return new AndExpression(julie, married); } Output:
John is male? true
Julie is a married women? true

BITS Pilani, Pilani Campus


Chain of Responsibility Pattern

The chain of responsibility pattern creates a chain of receiver objects for a


request. This pattern decouples sender and receiver of a request based on
type of request. This pattern comes under behavioral patterns.
In this pattern, normally each receiver contains reference to another receiver. If
one object cannot handle the request then it passes the same to the next
receiver and so on.

BITS Pilani, Pilani Campus


Example
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
//next element in chain or responsibility
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger){
this.nextLogger = nextLogger;
}
public void logMessage(int level, String message){
if(this.level <= level){
write(message); }
if(nextLogger !=null){
nextLogger.logMessage(level, message);
}
}
abstract protected void write(String message);
}
BITS Pilani, Pilani Campus
Code

//Create concrete classes extending the logger.


public class ErrorLogger extends AbstractLogger
{
public class ConsoleLogger extends AbstractLogger { public ErrorLogger(int level){
this.level = level; }
public ConsoleLogger(int level){ protected void write(String message) {
this.level = level; System.out.println("Error Console::Logger: "
}
+ message); }
}
protected void write(String message) {
System.out.println("Standard Console::Logger: " public class FileLogger extends AbstractLogger {
+ message); public FileLogger(int level){
} this.level = level; }
protected void write(String message) {
} System.out.println("File::Logger: " + message); }
}

BITS Pilani, Pilani Campus


Contd..
public class ChainPatternDemo {
private static AbstractLogger getChainOfLoggers(){
AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);
public static void main(String[] args) {
return errorLogger; } AbstractLogger loggerChain = getChainOfLoggers();
loggerChain.logMessage(AbstractLogger.INFO,
Output:
"This is an information.");
Standard Console::Logger: This is an information.
loggerChain.logMessage(AbstractLogger.DEBUG,
File::Logger: This is an debug level information.
"This is an debug level information.");
Standard Console::Logger: This is an debug level information.
loggerChain.logMessage(AbstractLogger.ERROR,
Error Console::Logger: This is an error information.
"This is an error information."); }
File::Logger: This is an error information.
}
Standard Console::Logger: This is an error information.
BITS Pilani, Pilani Campus
BITS Pilani, Pilani Campus
BITS Pilani
Pilani Campus

You might also like