Teachers record management system project report..pdf
Behavioral pattern 4
1. Behavioral Pattern - 4
By,
D. B. Naga Muruga,
Dept of Mechanical Engineering,
Sriram Engineering College
2. CHAIN OF RESPONSIBILITY PATTERN
Define Chain of responsibility pattern
Let more than one object handle a request without their knowing each other. Pass the request
to chained objects until it has been handled.
The chain of responsibility pattern is based on the same principle as written above. It decouples
the sender of the request to the receiver. The only link between sender and the receiver is the
request which is sent. Based on the request data sent, the receiver is picked. This is called “data-
driven”. In most of the behavioral patterns, the data-driven concepts are used to have a loose
coupling.
Where to use & benefits
One request should be handled by more than one object.
Don't know which object should handle a request, probably more than one object will handle it
automatically.
Reduce coupling.
Flexible in handling a request.
3. EXAMPLE OF CHAIN OF RESPONSIBILITY PATTERN
The Java Servlet filter framework is an example of chain of resposibility design. Note that the chain.doFilter() is the method
that should be called to make the chain roll. If the subclass missed it, the whole chain would be stopped or blocked.
Java exception handling is another example of chain of responsibility design. When an error occurs, the exception call will
look for a handling class. If there is no handler, the super Exception class will be called to throw the exception. Otherwise,
the handler class will handle it.
--------------------------------------------------------------------------------
Here comes a simple example, just to show how chain of responsibility works. Whenever you spend company's money, you
need get approval from your boss, or your boss's boss. Let's say, the leadership chain is:
Manager-->Director-->Vice President-->President
The following is a command line program to check who is responsible to approve your expenditure.
Composite, which a chain of responsibility pattern is often applied in conjunction with
Related patterns include
4. import java.io.*;
abstract class PurchasePower {
protected final double base = 500;
protected PurchasePower successor;
public void setSuccessor(PurchasePower successor){
this.successor = successor;
}
abstract public void processRequest(PurchaseRequest request);
}
class Manager extends PurchasePower {
private final double ALLOWABLE = 10 * base;
public void processRequest(PurchaseRequest request ) {
if( request.getAmount() < ALLOWABLE )
System.out.println("Manager will approve $"+ request.getAmount());
else
if( successor != null)
successor.processRequest(request);
}
}
class Director extends PurchasePower {
private final double ALLOWABLE = 20 * base;
public void processRequest(PurchaseRequest request ) {
if( request.getAmount() < ALLOWABLE )
System.out.println("Director will approve $"+ request.getAmount());
else
if( successor != null)
successor.processRequest(request);
}
}
class VicePresident extends PurchasePower {
private final double ALLOWABLE = 40 * base;
public void processRequest(PurchaseRequest request) {
if( request.getAmount() < ALLOWABLE )
System.out.println("Vice President will approve $" +
request.getAmount());
else
if( successor != null )
successor.processRequest(request);
}
}
class President extends PurchasePower {
private final double ALLOWABLE = 60 * base;
public void processRequest(PurchaseRequest request){
if( request.getAmount() < ALLOWABLE )
System.out.println("President will approve $" + request.getAmount());
else
System.out.println( "Your request for $" + request.getAmount() + "
needs a board meeting!");
}
}
class PurchaseRequest {
private int number;
private double amount;
private String purpose;
public PurchaseRequest(int number, double amount, String purpose){
this.number = number;
this.amount = amount;
this.purpose = purpose;
}
public double getAmount() {
return amount;
}
public void setAmount(double amt){
amount = amt;
}
public String getPurpose() {
return purpose;
}
public void setPurpose(String reason) {
purpose = reason;
}
public int getNumber(){
return number;
}
public void setNumber(int num) {
number = num;
}
}
class CheckAuthority {
public static void main(String[] args) throws Exception{
Manager manager = new Manager();
Director director = new Director();
VicePresident vp = new VicePresident();
President president = new President();
manager.setSuccessor(director);
director.setSuccessor(vp);
vp.setSuccessor(president);
//enter ctrl+c to kill.
while (true) {
System.out.println("Enter the amount to check who should approve
your expenditure.");
System.out.print(">");
double d = Double.parseDouble(new BufferedReader(new
InputStreamReader(System.in)).readLine());
manager.processRequest(new PurchaseRequest(0, d, "General"));
}
}
}
5. Output :
Enter the amount to check who should approve your expenditure.
>500
Manager will approve $500.0
Enter the amount to check who should approve your expenditure.
>5000
Director will approve $5000.0
Enter the amount to check who should approve your expenditure.
>11000
Vice President will approve $11000.0
Enter the amount to check who should approve your expenditure.
>30000
Your request for $30000.0 needs a board meeting!
Enter the amount to check who should approve your expenditure.
>20000
President will approve $20000.0
Enter the amount to check who should approve your expenditure.
>
You may redo it using interface instead of abstract class.
The composite pattern is often used with chain of responsibility. That means a class may contain the
class that may handle the request.
6. Output :
Enter the amount to check who should approve your expenditure.
>500
Manager will approve $500.0
Enter the amount to check who should approve your expenditure.
>5000
Director will approve $5000.0
Enter the amount to check who should approve your expenditure.
>11000
Vice President will approve $11000.0
Enter the amount to check who should approve your expenditure.
>30000
Your request for $30000.0 needs a board meeting!
Enter the amount to check who should approve your expenditure.
>20000
President will approve $20000.0
Enter the amount to check who should approve your expenditure.
>
You may redo it using interface instead of abstract class.
The composite pattern is often used with chain of responsibility. That means a class may contain the
class that may handle the request.
7. COMMAND PATTERN
Define command pattern
Streamlize objects by providing an interface to encapsulate a request and make the interface
implemented by subclasses in order to parameterize the clients.
This is another of the data-driven pattern. The client invokes a particular module using a
command. The client passes a request, this request gets propagated as a command. The
command request maps to particular modules. According to the command, a module is
invoked.
Where to use & benefits
One action can be represented in many ways, like drop-down menu, buttons and popup
menu.
Need a callback function, i.e., register it somewhere to be called later.
Specify and execute the request at different time
Need to undo an action by storing its states for later retrieving.
Decouple the object with its trigger
Easily to be extensible by not touching the old structure.
8. RELATED PATTERNS INCLUDE
Composite, which aggregates an object. You may combine it into a composite
command pattern. In general, a composite command is an instance of the
composite.
Memento, which keeps state of an object. Command supports undo and
redo.
9. EXAMPLE OF COMMAND PATTERN
The simple example of Command pattern is to design a Command interface and with an
execute method like this:
public interface Command {
public void execute();
}
Then, design multiple implementation classes and see how powerful the execute() method
has been called dynamically.
In order to take advantage of Java built-in interfaces, we will design a window with a drop
down menu, button commands and popup menu with command pattern.
As we know, JButton, JMenuItem and JPopupMenu have constructors accept Action type
variable. Action interface extends ActionListener, which has the following hierarchy.
10. public interface EventLister {
...
}
public interface ActionListener extends EventListener {
...
}
public interface Action extends ActionListener {
...
}
There is an abstract class called AbstractAction which implements Action
interface. It has the following design.
public abstract class AbstractAction extends Object
implements Action, Cloneable, Serializable
We will create several command classes to subclass the AbstractAction class
and pass them to the constructors of JButton, JMenuItem and JPopupMenu
classes. There is a request method called actionPerformed(), every command
classes must implement it in order to make it work. To show the concept, we
just design two actions: submit and exit. You may expand such design to your
need in your future project.
Such action can be attached to any component, AWT or Swing. The caption,
and Icon have been designed as well as tooltips.
class ExitAction extends AbstractAction {
private Component target;
public ExitAction(String name, Icon icon, Component t){
putValue(Action.NAME, name);
putValue(Action.SMALL_ICON, icon);
putValue(Action.SHORT_DESCRIPTION, name + " the program");
target = t;
}
public void actionPerformed(ActionEvent evt) {
int answer = JOptionPane.showConfirmDialog(target, "Are you sure you
want to exit? ", "Confirmation",
JOptionPane.YES_NO_OPTION);
if ( answer == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
}
Similar to the above exit action, the submit action is as follows:
class SubmitAction extends AbstractAction {
private Component target;
public SubmitAction(String name, Icon icon, Component t){
putValue(Action.NAME, name);
putValue(Action.SMALL_ICON, icon);
putValue(Action.SHORT_DESCRIPTION, name + " the program");
target = t;
}
public void actionPerformed(ActionEvent evt) {
JOptionPane.showMessageDialog(target, "submit action clicked ");
}
}
You can modify the program to add more commands in. These command
classes are decoupled from any program. It is very good for maintenance.
The whole workable program is as follows. You can run it to see the powerful
command design pattern.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class ExitAction extends AbstractAction {
private Component target;
public ExitAction(String name, Icon icon, Component t){
putValue(Action.NAME, name);
putValue(Action.SMALL_ICON, icon);
putValue(Action.SHORT_DESCRIPTION, name + " the program");
target = t;
}
public void actionPerformed(ActionEvent evt) {
int answer = JOptionPane.showConfirmDialog(target, "Are you sure you
want to exit? ", "Confirmation",
JOptionPane.YES_NO_OPTION);
if ( answer == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
}
class SubmitAction extends AbstractAction {
private Component target;
public SubmitAction(String name, Icon icon, Component t){
putValue(Action.NAME, name);
putValue(Action.SMALL_ICON, icon);
putValue(Action.SHORT_DESCRIPTION, name + " the program");
target = t;
}
public void actionPerformed(ActionEvent evt) {
JOptionPane.showMessageDialog(target, "submit action clicked ");
}
}
11. class Test extends JFrame{
Test() {
Action ea = new ExitAction("Exit", null, this);
Action sa = new SubmitAction("Submit", null, this);
JMenuBar jbr = new JMenuBar();
JMenu dropmenu= new JMenu("File");
JMenuItem submitmenu = new JMenuItem(sa);
JMenuItem exitmenu = new JMenuItem(ea);
dropmenu.add(submitmenu);
dropmenu.add(exitmenu);
jbr.add(dropmenu);
setJMenuBar(jbr);
final JPopupMenu pop = new JPopupMenu("PopMenu");
pop.add(sa);
pop.add(ea);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
showPopup(e);
}
public void mouseReleased(MouseEvent e) {
showPopup(e);
}
private void showPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
pop.show(e.getComponent(),
e.getX(), e.getY());
}
}
});
JPanel jp = new JPanel();
JButton subbtn = new JButton(sa);
JButton exitbtn = new JButton(ea);
jp.add(subbtn);
jp.add(exitbtn);
Container con = getContentPane();
con.add(jp, "South");
setTitle("Command pattern example");
setSize(400,200);
setVisible(true);
}
public static void main(String[] args) {
new Test();
}
}
java Test
A windows pops up.
Pay attention to the action buttons. The instances can be parameterized to JButton, JMenuItem and JPopupMenu constructors. The powerful action design (Java built-in
Action interface) makes objects like ExitAction, SubmitAction be used everywhere. Design once, use everywhere.
12. INTERPRETER PATTERN
Define Interpreter pattern
Provides a definition of a macro language or syntax and parsing into objects in a program.
The Interpreter Pattern defines a grammatical representation for a language and an interpreter
to interpret the grammar. The best example you can get for this is Java itself which is an
interpreted language. It converts the code written in English to a byte code format so as to
make possible for all the operating systems to understand it. This quality of it makes it platform
independent.
Where to use & benefits
Need your own parser generator.
Translate a specific expression.
Handle a tree-related information
13. RELATED PATTERNS
INCLUDE
Composite, which is an instance in an interpreter.
Flyweight, which shows how to share symbols with abstract context.
Iterator, which is used to traverse the tree structure.
Visitor, which is used to maintain behavior of each note in tree
structure.
14. EXAMPLE OF INTERPRETER PATTERN
Given any string expression and a token, filter out the information
you want. The below is a simple parser program. the myParser
method can be used to parse any expression. The composite, visit
and iterator patterns have been used.
15. import java.util.*;
class Parser{
private String expression;
private String token;
private List result;
private String interpreted;
public Parser(String e, String t) {
expression = e;
token = t;
}
public void myParser() {
StringTokenizer holder = new StringTokenizer(expression, token);
String[] toBeMatched = new String[holder.countTokens()];
int idx = 0;
while(holder.hasMoreTokens()) {
String item = holder.nextToken();
int start = item.indexOf(",");
if(start==0) {
item = item.substring(2);
}
toBeMatched[idx] = item;
idx ++;
}
result = Arrays.asList(toBeMatched);
}
public List getParseResult() {
return result;
}
public void interpret() {
StringBuffer buffer = new StringBuffer();
ListIterator list = result.listIterator();
while (list.hasNext()){
String token = (String)list.next();
if (token.equals("SFO")){
token = "San Francisco";
}else if(token.equals("CA")) {
token = "Canada";
}
//...
buffer.append(" " + token);
}
interpreted = buffer.toString();
}
public String getInterpretedResult() {
return interpreted;
}
public static void main(String[] args) {
String source = "dest='SFO',origin='CA',day='MON'";
String delimiter = "=,'";
Parser parser = new Parser(source, delimiter);
parser.myParser();
parser.interpret();
String result = parser.getInterpretedResult();
System.out.println(result);
}
}
java Parser
dest San Francisco origin Canada day MON
16. ITERATOR PATTERN
Define Iterator pattern
Provide a way to move through a list of collection or aggregated objects without knowing its
internal representations.
The Iterator pattern is one, which allows you to navigate through a collection of data using a
common interface without knowing about the underlying implementation.
Where to use & benefits
Use a standard interface to represent data objects.
Use s standard iterator built in each standard collection, like List, Sort, or Map.
Need to distinguish variations in the traversal of an aggregate.
Similar to Enumeration class, but more effective.
Need to filter out some info from an aggregated collection.
17. RELATED PATTERNS INCLUDE
Composite, which supports recursive structures, whereas an iterator is
often applied on it.
Factory Method, which provides appropriate instances needed by an
iterator subclasses.
Memento, which is often used with an Iterator. The iterator stores the
memento internally.
18. EXAMPLE OF ITERATOR PATTERN
Employee is an interface, Manager, PieceWorker, HourlyWorker and
CommissionWorker are implementation classes of interface Employee.
EmployeeTest class will create a list and use a built-in iterator of
ArrayList class to traverse the members of the list.
19. import java.util.*;
interface Employee {
public abstract double earnings();
}
class Manager implements Employee {
private double weeklySalary;
private String name;
public Manager(String name, double s) {
this.name = name;
setWeeklySalary(s);
}
void setWeeklySalary(double s) {
if (s > 0) {
weeklySalary = s;
} else
weeklySalary = 0;
}
public double earnings() {
return weeklySalary;
}
public String getName() {
return name;
}
public String toString() {
return "Manager: " + getName();
}
}
class PieceWorker implements Employee {
private double wagePerPiece;
private int quantity;
private String name;
public PieceWorker(String name, double w, int q) {
this.name = name;
setWagePerPiece(w);
setQuantity(q);
}
void setWagePerPiece(double w) {
if (w > 0)
wagePerPiece = w;
else
wagePerPiece = 0;
}
void setQuantity(int q) {
if ( q > 0)
quantity = q;
else
quantity = 0;
}
public String getName() {
return name;
}
public double earnings() {
return quantity * wagePerPiece;
}
public String toString() {
return "Piece worker: " + getName();
}
}
class HourlyWorker implements Employee {
private double hourlyWage;
private double hours;
private String name;
public HourlyWorker(String name, double w, double h) {
this.name = name;
setHourlyWage(w);
setHours(h);
}
void setHourlyWage(double w) {
if (w > 0)
hourlyWage = w;
else
hourlyWage = 0;
}
void setHours(double h) {
if ( 0 <= h && h < 168)
hours = h;
else
hours = 0;
}
public String getName() {
return name;
}
public double earnings() {
return hourlyWage * hours;
}
public String toString() {
return "Hourly worker: " + getName();
}
}
20. class CommissionWorker implements Employee {
private double salary;
private double commission;
private double totalSales;
private String name;
public CommissionWorker(String name,
double salary, double commission, double totalSales) {
this.name = name;
setSalary(salary);
setCommission(commission);
setTotalSales(totalSales);
}
void setSalary(double s) {
if( s > 0)
salary = s;
else
salary = 0;
}
void setCommission(double c) {
if ( c > 0)
commission = c;
else
commission = 0;
}
void setTotalSales(double ts) {
if (ts > 0 )
totalSales = ts;
else
totalSales = 0;
}
public String getName() {
return name;
}
public double earnings() {
return salary + commission/100*totalSales;
}
public String toString() {
return "Commission worker:"
+ getName();
}
}
class EmployeeTest {
public static void main(String[] args) {
java.util.List list = new ArrayList();
list.add(new Manager("Bill", 800.00));
list.add(new CommissionWorker("Newt", 400.0, 3.75, 159.99));
list.add(new PieceWorker("Al", 2.5, 200));
list.add(new HourlyWorker("Babara", 13.75, 40));
list.add(new Manager("Peter", 1200.00));
list.add(new CommissionWorker("Margret", 600.0,5.5, 200.25));
list.add(new PieceWorker("Mark", 4.5, 333));
list.add(new HourlyWorker("William", 31.25, 50));
System.out.println("Use built-in iterator:");
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
Employee em = (Employee)iterator.next();
System.out.print(em + " earns $");
System.out.println(em.earnings());
}
}
}
%java EmployeeTest
Use built-in iterator:
Manager: Bill earns $800.0
Commission worker:Newt earns $405.999625
Piece worker: Al earns $500.0
Hourly worker: Babara earns $550.0
Manager: Peter earns $1200.0
Commission worker:Margret earns $611.01375
Piece worker: Mark earns $1498.5
Hourly worker: William earns $1562.5
The above example also shows a dynamic binding feature which is
popular in Object-Oriented realm.
If you want to pick up a specific object from the aggregated list, you
may use the following code.
while(iterator.hasNext()) {
Employee em = (Employee)iterator.next();
if (em instanceof Manager) {
System.out.print(em + " earns $");
System.out.println(em.earnings());
}
}
The above list can also be replaced by an array and achieve the same
result.
21. MEDIATOR PATTERN
Define mediator pattern
Define an object that encapsulates details and other objects interact with such object. The relationships are
loosely decoupled.
The mediator pattern deals with the complexity which comes in the coding when number of classes
increase. I will explain this. When we begin with development, we have a few classes and these classes
interact with each other producing results. Now, consider slowly, the logic becomes more complex and
functionality increases. Then what happens? We add more classes and they still interact with each other but
it gets really difficult to maintain this code now. Mediator pattern takes care of this problem. It makes the
code more maintainable. It promotes loose-coupling of classes such that only one class (Mediator) has the
knowledge of all the classes, rest of the classes have their responsibilities and they only interact with the
Mediator.
Where to use & benefits
Partition a system into pieces or small objects.
Centralize control to manipulate participating objects(a.k.a colleagues)
Clarify the complex relationship by providing a board committee.
Limit subclasses.
Improve objects reusabilities.
Simplify object protocols.
The relationship between the control class and other participating classes is multidirectional.
22. RELATED PATTERNS
INCLUDE
Facade, which abstracts a subsystem to provide a more convenient
interface, and its protocol is unidirectional, whereas a mediator
enables cooperative behavior and its protocol is multidirectional.
Command, which is used to coordinate functionality.
Observer, which is used in mediator pattern to enhance
communication.
23. EXAMPLE OF MEDIATOR PATTERN
If you have a complex GUI, whenever a button has been clicked,
the related actions should be disabled or enabled. You may design
a Mediator class to include all related classes:
24. interface Command {
void execute();
}
class Mediator {
BtnView btnView;
BtnSearch btnSearch;
BtnBook btnBook;
LblDisplay show;;
//....
void registerView(BtnView v) {
btnView = v;
}
void registerSearch(BtnSearch s) {
btnSearch = s;
}
void registerBook(BtnBook b) {
btnBook = b;
}
void registerDisplay(LblDisplay d) {
show = d;
}
void book() {
btnBook.setEnabled(false);
btnView.setEnabled(true);
btnSearch.setEnabled(true);
show.setText("booking...");
}
void view() {
btnView.setEnabled(false);
btnSearch.setEnabled(true);
btnBook.setEnabled(true);
show.setText("viewing...");
}
void search() {
btnSearch.setEnabled(false);
btnView.setEnabled(true);
btnBook.setEnabled(true);
show.setText("searching...");
}
}
Then, you may define classes which should be controlled by the Mediator class.
class BtnView extends JButton implements Command {
Mediator med;
BtnView(ActionListener al, Mediator m) {
super("View");
addActionListener(al);
med = m;
med.registerView(this);
}
public void execute() {
med.view();
}
}
class BtnSearch extends JButton implements Command {
Mediator med;
BtnSearch(ActionListener al, Mediator m) {
super("Search");
addActionListener(al);
med = m;
med.registerSearch(this);
}
public void execute() {
med.search();
}
}
class BtnBook extends JButton implements Command {
Mediator med;
BtnBook (ActionListener al, Mediator m) {
super("Book");
addActionListener(al);
med = m;
med.registerBook(this);
}
public void execute() {
med.book();
}
}
class LblDisplay extends JLabel{
Mediator med;
LblDisplay (Mediator m) {
super("Just start...");
med = m;
med.registerDisplay(this);
setFont(new Font("Arial",Font.BOLD,24));
}
}
From the above design, you can see that the relationships among the classes,
which also known as collegues or participating classes, are multidirectional.
Mediator class contains all the information about these classes and knows
what these classes are going to do. The participating classes have to register
themselves to the Mediator class.
25. The MediatorDemo class will show the cooperation among the classes.
class MediatorDemo extends JFrame implements ActionListener {
Mediator med = new Mediator();
MediatorDemo() {
JPanel p = new JPanel();
p.add(new BtnView(this,med));
p.add(new BtnBook(this,med));
p.add(new BtnSearch(this, med));
getContentPane().add(new LblDisplay(med), "North");
getContentPane().add(p, "South");
setSize(400,200);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Command comd = (Command)ae.getSource();
comd.execute();
}
public static void main(String[] args) {
new MediatorDemo();
}
}
The following is a complete code for the above program.
interface Command {
void execute();
}
class Mediator {
BtnView btnView;
BtnSearch btnSearch;
BtnBook btnBook;
LblDisplay show;;
//....
void registerView(BtnView v) {
btnView = v;
}
void registerSearch(BtnSearch s) {
btnSearch = s;
}
void registerBook(BtnBook b) {
btnBook = b;
}
void registerDisplay(LblDisplay d) {
show = d;
}
void book() {
btnBook.setEnabled(false);
btnView.setEnabled(true);
btnSearch.setEnabled(true);
show.setText("booking...");
}
void view() {
btnView.setEnabled(false);
btnSearch.setEnabled(true);
btnBook.setEnabled(true);
show.setText("viewing...");
}
void search() {
btnSearch.setEnabled(false);
btnView.setEnabled(true);
btnBook.setEnabled(true);
show.setText("searching...");
}
}
class BtnView extends JButton implements Command {
Mediator med;
BtnView(ActionListener al, Mediator m) {
super("View");
addActionListener(al);
med = m;
med.registerView(this);
}
public void execute() {
med.view();
}
}
class BtnSearch extends JButton implements Command {
Mediator med;
BtnSearch(ActionListener al, Mediator m) {
super("Search");
addActionListener(al);
med = m;
med.registerSearch(this);
}
public void execute() {
med.search();
}
}
class BtnBook extends JButton implements Command {
Mediator med;
BtnBook (ActionListener al, Mediator m) {
super("Book");
addActionListener(al);
med = m;
med.registerBook(this);
}
public void execute() {
med.book();
}
}
class LblDisplay extends JLabel{
Mediator med;
LblDisplay (Mediator m) {
super("Just start...");
med = m;
med.registerDisplay(this);
setFont(new Font("Arial",Font.BOLD,24));
}
}
26. class MediatorDemo extends JFrame implements ActionListener {
Mediator med = new Mediator();
MediatorDemo() {
JPanel p = new JPanel();
p.add(new BtnView(this,med));
p.add(new BtnBook(this,med));
p.add(new BtnSearch(this, med));
getContentPane().add(new LblDisplay(med), "North");
getContentPane().add(p, "South");
setSize(400,200);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Command comd = (Command)ae.getSource();
comd.execute();
}
public static void main(String[] args) {
new MediatorDemo();
}
}
java MediatorDemo
A window will pop up. Try the features.
27. MEMENTO PATTERN
Define memento pattern
To record an object internal state without violating encapsulation
and reclaim it later without knowledge of the original object.
Where to use & benefits
Let some info in an object to be available by another object by
using default access control.
Save some info for later uses.
Need undo/redo features.
Used in database transaction.
28. RELATED PATTERNS INCLUDE
Command, which supports undo or redo features, whereas a
memento keeps state of an object.
Iterator, which provides a way to access the elements of an
aggregate object sequentially without exposing its underlying
representation, whereas a memento can be used for iteration.
29. EXAMPLE OF MEMENTO PATTERN
To design a program with Memento feature is used to combine
several design patterns like Command, Mediator or Iterator.
Here is an example expanded from Mediator example.
To show the Memento design concept, we record a dice number.
This is very simple program. The Memento class just holds a
number.
30. class Memento {
int num;
Memento(int c) {
num = c;
}
int getNum() {
return num;
}
}
Then we combine Mediator and Command patterns to design three buttons
and one label.The first button throws dice, the second button shows the dice
number backward, and the third button clears number displayed. The label is
used to display the dice number thrown. We use Math.random() method to get
number from 1 to 6.
class BtnDice extends JButton implements Command {
Mediator med;
BtnDice(ActionListener al, Mediator m) {
super("Throw Dice");
addActionListener(al);
med = m;
med.registerDice(this);
}
public void execute() {
med.throwit();
}
}
class BtnClear extends JButton implements Command {
Mediator med;
BtnClear(ActionListener al, Mediator m) {
super("Clear");
addActionListener(al);
med = m;
med.registerClear(this);
}
public void execute() {
med.clear();
}
}
class BtnPrevious extends JButton implements Command {
Mediator med;
BtnPrevious(ActionListener al, Mediator m) {
super("Previous");
addActionListener(al);
med = m;
med.registerPrevious(this);
}
public void execute() {
med.previous();
}
}
class LblDisplay extends JLabel{
Mediator med;
LblDisplay (Mediator m) {
super("0",JLabel.CENTER);
med = m;
med.registerDisplay(this);
setBackground(Color.white);
setBorder(new EtchedBorder(Color.blue, Color.green));
Font font = new Font("Arial",Font.BOLD,40);
setFont(font);
}
}
The Mediator class will hold these participating objects and manipulate their
relationships.
class Mediator {
BtnDice btnDice;
BtnPrevious btnPrevious;
BtnClear btnClear;
LblDisplay show;
java.util.List list, undo;
boolean restart = true;
int counter = 0, ct = 0;
//....
Mediator() {
list = new ArrayList();
undo = new ArrayList();
}
void registerDice(BtnDice d) {
btnDice = d;
}
void registerClear(BtnClear c) {
btnClear = c;
}
void registerPrevious(BtnPrevious p) {
btnPrevious = p;
}
void registerDisplay(LblDisplay d) {
show = d;
}
void throwit() {
show.setForeground(Color.black);
int num = (int)(Math.random()*6 +1);
int i = counter++;
list.add(i, new Integer(num));
undo.add(i, new Memento(num));
show.setText(""+num);
}
void previous() {
show.setForeground(Color.red);
btnDice.setEnabled(false);
if (undo.size() > 0) {
ct = undo.size()-1;
Memento num = (Memento)undo.get(ct);
show.setText(""+num.getNum());
undo.remove(ct);
}
if (undo.size() == 0)
show.setText("0");
}
void clear() {
list = new ArrayList();
undo = new ArrayList();
counter = 0;
show.setText("0");
btnDice.setEnabled(true);
}
}
31.
Finally, write a demo class.
class MementoDemo extends JFrame implements ActionListener {
Mediator med = new Mediator();
MementoDemo() {
JPanel p = new JPanel();
p.add(new BtnDice(this,med));
p.add(new BtnPrevious(this,med));
p.add(new BtnClear(this,med));
JPanel dice = new JPanel();
LblDisplay lbl = new LblDisplay(med);
dice.add(lbl);
getContentPane().add(dice, "Center");
getContentPane().add(p, "South");
setTitle("Memento pattern example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400,200);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Command comd = (Command)ae.getSource();
comd.execute();
}
public static void main(String[] args) {
new MementoDemo();
}
}
The complete workable program is as follows. Copy it, compile it and run it.
import javax.swing.*;
import java.awt.event.*;
import java.awt.FontMetrics;
import java.awt.*;
import java.util.*;
import javax.swing.border.*;
interface Command {
void execute();
}
class Mediator {
BtnDice btnDice;
BtnPrevious btnPrevious;
BtnClear btnClear;
LblDisplay show;
java.util.List list, undo;
boolean restart = true;
int counter = 0, ct = 0;
//....
Mediator() {
list = new ArrayList();
undo = new ArrayList();
}
void registerDice(BtnDice d) {
btnDice = d;
}
void registerClear(BtnClear c) {
btnClear = c;
}
void registerPrevious(BtnPrevious p) {
btnPrevious = p;
}
void registerDisplay(LblDisplay d) {
show = d;
}
void throwit() {
show.setForeground(Color.black);
int num = (int)(Math.random()*6 +1);
int i = counter++;
list.add(i, new Integer(num));
undo.add(i, new Memento(num));
show.setText(""+num);
}
void previous() {
show.setForeground(Color.red);
btnDice.setEnabled(false);
if (undo.size() > 0) {
ct = undo.size()-1;
Memento num = (Memento)undo.get(ct);
show.setText(""+num.getNum());
undo.remove(ct);
}
if (undo.size() == 0)
show.setText("0");
}
void clear() {
list = new ArrayList();
undo = new ArrayList();
counter = 0;
show.setText("0");
btnDice.setEnabled(true);
}
}
class BtnDice extends JButton implements Command {
Mediator med;
BtnDice(ActionListener al, Mediator m) {
super("Throw Dice");
addActionListener(al);
med = m;
med.registerDice(this);
}
public void execute() {
med.throwit();
}
}
32. class BtnClear extends JButton implements Command {
Mediator med;
BtnClear(ActionListener al, Mediator m) {
super("Clear");
addActionListener(al);
med = m;
med.registerClear(this);
}
public void execute() {
med.clear();
}
}
class BtnPrevious extends JButton implements Command {
Mediator med;
BtnPrevious(ActionListener al, Mediator m) {
super("Previous");
addActionListener(al);
med = m;
med.registerPrevious(this);
}
public void execute() {
med.previous();
}
}
class Memento {
int num;
Memento(int c) {
num = c;
}
int getNum() {
return num;
}
}
class LblDisplay extends JLabel{
Mediator med;
LblDisplay (Mediator m) {
super("0",JLabel.CENTER);
med = m;
med.registerDisplay(this);
setBackground(Color.white);
setBorder(new EtchedBorder(Color.blue, Color.green));
Font font = new Font("Arial",Font.BOLD,40);
setFont(font);
}
}
class MementoDemo extends JFrame implements
ActionListener {
Mediator med = new Mediator();
MementoDemo() {
JPanel p = new JPanel();
p.add(new BtnDice(this,med));
p.add(new BtnPrevious(this,med));
p.add(new BtnClear(this,med));
JPanel dice = new JPanel();
LblDisplay lbl = new LblDisplay(med);
dice.add(lbl);
getContentPane().add(dice, "Center");
getContentPane().add(p, "South");
setTitle("Memento pattern example");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400,200);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Command comd = (Command)ae.getSource();
comd.execute();
}
public static void main(String[] args) {
new MementoDemo();
}
}
33. OBSERVER PATTERN
Define Observer pattern
One object changes state, all of its dependents are updated automatically.
Where to use & benefits
One change affects one or many objects.
Many object behavior depends on one object state.
Need broadcast communication.
AKA Publish-Subscribe.
Maintain consistency between objects
keep classes from becoming too tightly coupled, which would hamper
reusability.
34. RELATED PATTERNS
INCLUDESingleton, which is used to make observable object
unique and accessible globally.
Mediator, which is used to encapsulate updated objects.
35. EXAMPLE OF OBSERVER PATTERN
Observer pattern is often used in GUI application. For example,
defining a one-to-many dependency between objects so that when
one object changes state, all its dependents are notified and
updated automatically, like stock change affecting many data or
diagram updated accordingly.
Java API provides a built-in interface Observer and class
Observable for use.
To show how observer pattern works, two windows have been
created. One is for user input; another is for display. When the data
has been entered in the textfield, another window gets the message
and display it with a dialog. The private inner classes have been
used in this example.
36. import javax.swing.*;
import java.awt.event.*;
import java.util.*;
class DisplayForm extends JFrame {
InputFormObserver input = new InputFormObserver();
InputForm inputForm ;
Observable obsInput;
JTextField display;
//...
public DisplayForm() {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}});
inputForm = new InputForm();
obsInput = inputForm.getInputInfo();
obsInput.addObserver(input);
display = new JTextField(10);
display.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
getContentPane().add(display);
setTitle("Observer form");
setSize(200,100);
setLocation(200,100);
setVisible(true);
}
private class InputFormObserver implements Observer {
public void update(Observable ob, Object o) {
doSomeUpdate();
if (obsInput.countObservers()>0)
obsInput.deleteObservers();
obsInput = inputForm.getInputInfo();
obsInput.addObserver(input);
}
}
public void doSomeUpdate() {
display.setText(inputForm.getText());
JOptionPane.showMessageDialog(DisplayForm.this,
"This form has been updated");
}
public static void main(String args[]) {
DisplayForm df = new DisplayForm();
}
}
class InputForm extends JFrame {
public InformDisplay inform = new InformDisplay();
//...
JTextField input= new JTextField(10);
public InputForm() {
JPanel panel= new JPanel();
input.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
inform.notifyObservers();
}
});
panel.add(new JLabel("Enter: "));
panel.add(input);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}});
getContentPane().add(panel);
setTitle("Observable form");
setSize(200,100);
setVisible(true);
}
public Observable getInputInfo() {
return inform;
}
public String getText() {
return input.getText();
}
private class InformDisplay extends Observable {
public void notifyObservers() {
setChanged();
super.notifyObservers();
}
public String getChange() {
return input.getText();
}
}
//...
}
java DisplayForm
Two windows will come up:
one for user input, the other for observing user input.
Enter data in the input window, a dialog box from other window shows up
and the input data has been shown in the other window.
37. STATE PATTERN
Define State pattern
An object's behavior change is represented by its member classes, which share
the same super class.
Where to use & benefits
Need to control many states without using if-else or switch statements.
Use a class to represent a state, not a constant or something else.
Every state has to act in a similar manner.
Every state must be a subclass of the same super class.
Simplify and clarify the program.
38. RELATED PATTERNS INCLUDE
Flyweight, which explains when and how a state object can be
shared.
Singleton which is often used with state pattern to ensure some
state change is shared with class itself, not instances of the class.
39. EXAMPLE OF DESIGN PATTERN
To show the concept of State pattern, we use a simple command line program. If a GUI program is used, a
mediator pattern or a flyweight pattern may be applied on it.
Users connect to a database to do some jobs. Users from Management department may focus on
management. Users from Sales department may focus on sales information. Every connection has to
perform similar functions like open, log and close. Suppose we have an abstract Connection class and have
these functions listed. Thus, every subclass of Connection must implement these functions. We list three
subclasses Management, Sales and Accounting for example, just to show the State pattern concept. The
Controller class contains each state of connection. Its behavior is decided by another object, which is a Test
class. All the details have been hidden from the Test class. Suppose we have a server which is a singleton.
Which connection is made depends on the user. We use a Test class which makes a trigger from command
line. In the real program, the trigger should be made by the user.
The following is a skeleton program.
40. abstract class Connection {
public abstract void open();
public abstract void close();
public abstract void log();
}
class Accounting extends Connection {
public void open() {
System.out.println("open database for accounting");
}
public void close() {
System.out.println("close the database");
}
public void log() {
System.out.println("log activities");
}
//...
}
class Sales extends Connection {
public void open() {
System.out.println("open database for sales");
}
public void close() {
System.out.println("close the database");
}
public void log() {
System.out.println("log activities");
}
public void update() {
//
}
}
class Management extends Connection {
public void open() {
System.out.println("open database for management");
}
public void close() {
System.out.println("close the database");
}
public void log() {
System.out.println("log activities");
}
//...
}
class Controller {
public static Accounting acct;
public static Sales sales;
public static Management manage;
private static Connection current;
Controller() {
acct = new Accounting();
sales = new Sales();
manage = new Management();
}
public void makeAccountingConnection() {
current = acct;
}
public void makeSalesConnection() {
current = sales;
}
public void makeManagementConnection() {
current = manage;
}
public void open() {
current.open();
}
public void close() {
current.close();
}
public void log() {
current.log();
}
}
class Test {
String con;
Controller controller;
Test(String con) {
controller = new Controller();
//the following trigger should be made by the user
if(con.equalsIgnoreCase("management"))
controller.makeManagementConnection();
if(con.equalsIgnoreCase("sales"))
controller.makeSalesConnection();
if(con.equalsIgnoreCase("accounting"))
controller.makeAccountingConnection();
controller.open();
controller.log();
controller.close();
}
}
41. class Server {
public static Test test;
public static void main(String[] args) {
new Test(args[0]);
}
}
When we run the program with different connection, we will invoke the
program in the following printout:
%java Server management
open database for management
log activities
close the database
%java Server accounting
open database for accounting
log activities
close the database
%java Server sales
open database for sales
log activities
close the database
42. class Server {
public static Test test;
public static void main(String[] args) {
new Test(args[0]);
}
}
When we run the program with different connection, we will invoke the
program in the following printout:
%java Server management
open database for management
log activities
close the database
%java Server accounting
open database for accounting
log activities
close the database
%java Server sales
open database for sales
log activities
close the database
43. STRATEGY PATTERN
Define strategy pattern
Group several algorithms in a single module to provide alternatives. Also known as policy.
Where to use & benefits
Encapsulate various algorithms to do more or less the same thing.
Need one of several algorithms dynamically.
The algorithms are exchangeable and vary independently
Configure a class with one of many related classes (behaviors).
Avoid exposing complex and algorithm-specific structures.
Data is transparent to the clients.
Reduce multiple conditional statements.
Provide an alternative to subclassing.
44. RELATED PATTERNS INCLUDE
State, which can activate several states, whereas a strategy can
only activate one of the algorithms.
Flyweight, which provides a shared object that can be used in
multiple contexts simultaneously, whereas a strategy focuses on
one context.
Decorator, which changes the skin of an object, whereas a strategy
changes the guts of an object.
Composite, which is used to combine with a strategy to improve
efficiency.
45. EXAMPLE OF STRATEGY PATTERN
Compress files using different algorithms or save files in different
formats or draw graphic in different presentations. Here is a
simple example. Just to show the concept of a strategy pattern.
46. interface FortuneCookies {
public void print();
}
class Five implements FortuneCookies {
public void print() {
System.out.println("It is your turn to get it");
}
}
class Two implements FortuneCookies {
public void print() {
System.out.println("It is never too late to start");
}
}
class Null implements FortuneCookies {
public void print() {
System.out.println("You got nothing");
}
}
class Dice {
public int throwIt() {
return (int)(Math.random()*6)+1;
}
}
//more class...
class Test {
static void goodFortune() {
int luckyNum = new Dice().throwIt();
FortuneCookies fc;
switch (luckyNum) {
case 2: fc = new Two();
break;
case 5: fc = new Five();
break;
//more
default: fc = new Null();
}
fc.print();
}
public static void main(String[] args) {
goodFortune();
}
}
47. TEMPLATE METHOD PATTERN
Define Template method pattern
Provide an abstract definition for a method or a class and redefine its behavior
later or on the fly without changing its structure.
Where to use & benefits
To make many similar operations template.
From many specialized operations to a generalized operation.
Refactor common behavior to simplify code.
Algorithm related improvement.
Need good coding skill to conquer it.
May be hard to read for novice.
Easy to produce ambiguity if not written well.
48. RELATED PATTERNS INCLUDE
Factory Method, which is combined with template method.
Strategy, which is used to delegate or coordinate the
template method.
49. EXAMPLE OF TEMPLATE METHOD
PATTERN For example, a loan application process may take several steps to finish. Let's
assume the steps are as follows:
check client's bank balance history
check client's credit score from three different companies
check client's other loan information
check client's stock holding value
check client's income potential in the future
etc.
You may use a template method to hold the process steps together without
considering the real implementation in the subclass.
50. abstract class CheckBackground {
public abstract void checkBank();
public abstract void checkCredit();
public abstract void checkLoan();
public abstract void checkStock();
public abstract void checkIncome();
//work as template method
public void check() {
checkBank();
checkCredit();
checkLoan();
checkStock();
checkIncome();
}
}
class LoanApp extends CheckBackground {
private String name;
public LoanApp(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void checkBank() {
//ck acct, balance
System.out.println("check bank...");
}
public void checkCredit() {
//ck score from 3 companies
System.out.println("check credit...");
}
public void checkLoan() {
//ck other loan info
System.out.println("check other loan...");
}
public void checkStock() {
//ck how many stock values
System.out.println("check stock values...");
}
public void checkIncome() {
//ck how much a family make
System.out.println("check family income...");
}
//other methods
}
class TestTemplate {
public static void main(String[] args) {
LoanApp mortgageClient = new LoanApp("Judy");
System.out.println("nCheck client " + mortgageClient.getName()+ "
Mortgage loan application. ");
mortgageClient.check();
LoanApp equityloanClient = new LoanApp("Mark");
System.out.println("nCheck client " + equityloanClient.getName()+ "
equity loan application. ");
equityloanClient.check();
}
}
Output :
Check client Judy Mortgage loan application.
check bank...
check credit...
check other loan...
check stock values...
check family income...
Check client Mark equity loan application.
check bank...
check credit...
check other loan...
check stock values...
check family income...
--------------------------------------------------------------------------------
Method overloading and method overriding are good examples of template
method pattern. For example,
Coercion polymorphism -- refers to a single operation serving several types
through implicit type conversion.
Overloading polymorphism -- refers to using a single identifier for different
operations.
Parametric polymorphism -- refers to a class declaration that allows the same
field names and method signatures to associate with a different type in each
instance of that class.
The add() in the following code example is a template method. It can take any
numerical primitive types and the result can be casted to the type you want.
//coercion polymorphism
abstract class Add {
public abstract double add(double d1, double d2);//template
}
class AddAnyTypeNumber extends Add{
public double add(double d1, double d2) {
return d1 + d2;
}
}
51. class Test {
public static void main(String[] args) {
double d1 = 10.5, d2 = 9.5;
float f1 = 11.5f, f2 = 12.5f;
long l1 = 1, l2 = 2;
int i1 = 3, i2 = 4;
short s1 = 7, s2 = 8;
byte b1 = 5, b2 = 6;
AddAnyTypeNumber addNumber = new AddAnyTypeNumber();
System.out.println(addNumber.add(d1,d2));
System.out.println((float)addNumber.add(f1,f2));
System.out.println((long)addNumber.add(l1,l2));
System.out.println((int)addNumber.add(i1,i2));
System.out.println((short)addNumber.add(s1,s2));
System.out.println((byte)addNumber.add(b1,b2));
}
}
Output :
20.0
24.0
3
7
15
11
Note that the side effect of using coercion polymorphism is casting in and
casting out if you need specific type to do the work. If you forget to do so, you
may have unexpected result and it is hard to debug.
If you don't have template method pattern concept or don't know Java type
promotion technique, you may write code in the following way:
abstract class Add {
public abstract double add(double d1, double d2);
public abstract float add(float d1, float d2);
public abstract long add(long d1, long d2);
public abstract int add(int d1, int d2);
public abstract short add(short d1, short d2);
public abstract byte add(byte d1, byte d2);
}
class AddNumber extends Add{
public double add(double d1, double d2) {
return d1 + d2;
}
public float add(float f1, float f2) {
return f1 + f2;
}
public long add(long l1, long l2) {
return l1 + l2;
}
public int add(int i1, int i2) {
return i1 + i2;
}
public short add(short s1, short s2) {
return (short)(s1 + s2);
}
public byte add(byte b1, byte b2) {
return (byte)(b1 + b2);
}
}
class Test {
public static void main(String[] args) {
double d1 = 10.5, d2 = 9.5;
float f1 = 11.5f, f2 = 12.5f;
long l1 = 1, l2 = 2;
int i1 = 3, i2 = 4;
short s1 = 7, s2 = 8;
byte b1 = 5, b2 = 6;
AddNumber addNumber = new AddNumber();
System.out.println(addNumber.add(d1,d2));
System.out.println(addNumber.add(f1,f2));
System.out.println(addNumber.add(l1,l2));
System.out.println(addNumber.add(i1,i2));
System.out.println(addNumber.add(s1,s2));
System.out.println(addNumber.add(b1,b2));
}
}
Output :
20.0
24.0
3
7
15
11
Without using template method pattern, you may write more lines of code. The
good thing is that you don't have any side effect by using specific designed
method and you don't need to cast in or out.
52. VISITOR PATTERN
Define Visitor PatternDefine a new operation to deal with the
classes of the elements without changing their structures.
Where to use & benefits
Add operations on a bunch of classes which have different
interfaces.
Traverse the object structure to gather related operations
Easy to add new operations.
Crossing class hierarchies may break encapsulation.
53. RELATED PATTERNS INCLUDE
Composite, which may be applied in a visitor pattern.
Interpreter, which may be used to go through structure and
define new operation in a visitor pattern.
54. EXAMPLES OF VISITOR PATTERN
The following is a dummy program. Two interfaces involved: Visitor
and Pizza. The Pizza system is completely independent. "How to
get it" tries to add new operations to the Pizza system. It is done by
adding another interface Visitor and parameterizing Pizza interface
in the abstract method visit(composite pattern). The "how to get"
classes implement Visitor interface and make a connection with
Pizza system.
55. import java.util.*;
interface Visitor {
public void visit(Pizza p);
}
interface Pizza {
public String order();
}
class PopJohn implements Pizza {
final String name = "PopJohn";
public String order() {
return name;
}
}
class PizzaHut implements Pizza {
final String name = "PizzaHut";
public String order() {
return name;
}
}
class GodFather implements Pizza {
final String name = "GodFather";
public String order() {
return name;
}
}
class ByPickup implements Visitor {
private String name;
private final String method = "By pick up";
public void visit(Pizza p) {
name = p.order();
}
public String toString() {
return name + " " + method;
}
}
class ByEatin implements Visitor {
private String name;
private final String method = "By eat in";
public void visit(Pizza p) {
name = p.order();
}
public String toString() {
return name + " " + method;
}
}
class ByDelivery implements Visitor {
private String name;
private final String method = "By delivery";
public void visit(Pizza p) {
name = p.order();
}
public String toString() {
return name + " " + method;
}
}
class Dinner {
public Pizza getDinner() {
switch ((int)(Math.random()*3)){
case 0: return new PopJohn();
case 1: return new PizzaHut();
case 2: return new GodFather();
default: return null;
}
}
public Visitor howto() {
switch ((int)(Math.random()*3)){
case 0: return new ByPickup();
case 1: return new ByEatin();
case 2: return new ByDelivery();
default: return null;
}
}
}
class Test {
public static void main(String[] args) {
List pizzaList = new ArrayList();
pizzaList.add(new PopJohn());
pizzaList.add(new PizzaHut());
pizzaList.add(new GodFather());
Iterator it = pizzaList.iterator();
System.out.println("How many pizza restaurants in this area?");
while (it.hasNext()) {
System.out.println(((Pizza)it.next()).order());
}
Dinner d = new Dinner();
Pizza pza = d.getDinner();
Visitor v = d.howto();
v.visit(pza);
System.out.println("nWhich store for dinner?");
System.out.println(v);
}
}
//run it several times.
java Test
How many pizza restaurants in this area?
PopJohn
PizzaHut
GodFather
Which restaurant for dinner?
GodFather By delivery
java Test
How many pizza restaurants in this area?
PopJohn
PizzaHut
GodFather
Which restaurant for dinner?
PizzaHut By pick up
java Test
How many pizza restaurants in this area?
PopJohn
PizzaHut
GodFather
Which restaurant for dinner?
PizzaHut By delivery