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

Step 5 - DesignPatterns - Complete

learn java

Uploaded by

Priyanka Agarwal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

Step 5 - DesignPatterns - Complete

learn java

Uploaded by

Priyanka Agarwal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 110

Design Patterns

About Author

Sumit is a University Gold Medalist, holds master degree in computer application


(MCA) & have been working in IT industry more than eight years (since 2002).

He has extensive experience in ecommerce and EAI domain using J2EE based products like Hybris, ATG,
OFBiz, WCS, WebMethods and Jitterbit. He is currently working with HCL Technology in Multi Channel
Commerce Retail Center of Excellence (MCC Retail COE) domain as a java architect.

He also holds PG diploma in operations and also Sun, RUP (Rational Unified Process) and webMethods
certified.

Who should read this?


· Person who knows OOPs concepts but don’t know where and how to apply them.

· Person who gives some thoughts prior to developing an application.

· Person who is confused after reading n number of materials over internet and looking for a concise
and concrete one.

· Above all People who love Object Oriented Programming concepts.

1|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


Introduction to Design Patterns

What is a Pattern?

q Each pattern is a three-part rule, which expresses a relation between a certain context, a problem
and a solution.
q Hence, the common definition of a pattern: “A solution to a problem in a context.”
q Patterns can be applied to many different areas of human endeavor, including software
development.

What is a Design Pattern?

q The Design Patterns are description of communicating objects and classes that are customized to
solve a general design problem in a particular context.
q A design pattern names, abstracts, and identifies the key aspects of the common design structure
that make it useful for creating a reusable object oriented design.
q The design pattern identifies the participating classes and instances, their roles and collaborations,
and the distribution of responsibilities.
q Each design pattern focuses on a particular object-oriented design problem or issue. It describes
when it applies, whether it can be applied in view of other design constraints, and the consequences
and trade-offs of its use.

Benefits of Design Patterns

q Capture expertise and make it accessible to non-experts in a standard form.


q Facilitate communication among developers by providing a common language.
q Make it easier to reuse successful designs and avoid alternatives that diminish reusability.
q Facilitate design modifications.
q Improve design documentation.
q Improve design understandability.

Life without it - like constructing your dream house without any layout and realizing the problems in
middle or after construction.

Life with it – now you have a layout on which you worked a lot before actual construction, e.g. proper
spaces for ventilation, future expansion, vastu compliant, parking, entertaining guests, security systems and
many more.

The whole idea behind design patterns is to develop a standardized way to represent general solutions to
commonly encountered problems in software development.

2|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


GoF (Gang of Four) Classification of Design Patterns
The GoF classification classifies the Patterns based on purpose and scope. The term GoF refers to the four
authors of the first book written on this subject titled “Design Patterns: Elements of Reusable Object-
Oriented Software”.

q Purpose - what a pattern does

1. Creational Patterns - Concern the process of object creation


2. Structural Patterns - Deal with the composition of classes and objects
3. Behavioral Patterns -Deal with the interaction of classes and objects

q Scope - what the pattern applies to

q Class Patterns- Focus on the relationships between classes and their subclasses and involve
inheritance reuse
q Object Patterns- Focus on the relationships between objects and involve composition reuse

Design Patterns

Creational Structural Behavioral


Singleton Adapter Chain of Responsibility
Factory Bridge Command
Abstract Factory Composite Interpreter
Builder Decorator Iterator
Prototype Facade Mediator
Flyweight Memento
Proxy Observer
State
Strategy
Template Method
Visitor

*Bold ones are most commonly used patterns that you will come across in your day to day programming.

3|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


Creational Patterns
All the creational patterns define the best possible way in which an object can be instantiated. These
describe the best way to CREATE object instances. Now everyone knows the object instance in Java can
be created using a new operator.

Book book = new Book();

So, what’s the great stuff? Well, that’s true. The new Operator creates the instance of an object, but this is
hard-coding. Creating good software is difficult and so, hard coding is the last thing one should do. Also, at
times the very nature of the object, which is created, can change according to the nature of the program. In
such scenarios, we can make use of patterns to give this a more general and flexible approach.

There are five types of Creational Patterns.

1. Singleton Pattern
2. Factory Pattern
3. Abstract Factory Pattern
4. Builder Pattern
5. Prototype Pattern

1. Singleton pattern

In software engineering, the singleton design pattern is used to restrict instantiation of a class to one
object. This is useful when exactly one object is needed to coordinate actions across the system.
Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist.
It is also considered an anti-pattern since it is often used as a euphemism for global variable. Before
designing a class as a singleton, it is wise to consider whether it would be enough to design a normal class
and just use one instance.

The singleton pattern is implemented by creating a class with a method that creates a new instance of the
object if one does not exist. If an instance already exists, it simply returns a reference to that object. To
make sure that the object cannot be instantiated any other way, the constructor is made either private or
protected. Note the distinction between a simple static instance of a class and a singleton. Although a
singleton can be implemented as a static instance, it can also be lazily constructed, requiring no memory or
resources until needed.

The singleton pattern must be carefully constructed in multi-threaded applications. If two threads are to
execute the creation method at the same time when a singleton does not yet exist, they both must check for
an instance of the singleton and then only one should create the new one. If the programming language has
concurrent processing capabilities the method should be constructed to execute as a mutually exclusive
operation.

The classic solution to this problem is to use mutual exclusion on the class that indicates that the object is
being instantiated.

4|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


Example: A correct thread safe Java programming language lazy-loaded solution known as the
"Initialization On Demand Holder" idiom suggested by Bill Pugh follows:

package example.creational.singleton;

public class Singleton {


private static Singleton obj;

// Private constructor suppresses generation of a (public) default


// constructor
private Singleton() {
}

public synchronized static Singleton getInstance() {


if (obj == null)
//lazy,when this method will get called first time
obj = new Singleton();

return obj;
}
}

If we are opting for early loading then there is no issue of synchronization.

public class Singleton {


private static Singleton obj = new Singleton(); //early, when this class get loaded

//Private constructor suppresses generation of a (public) default constructor


private Singleton(){
}

public static Singleton getInstance() {


return obj;
}
}

Note – Now there will be one object in whole JVM, no one can create multiple instances in the same JVM.
We should not mark them Serializable and Cloneable also.

Singleton in Clustered Application


What about if our application is spanned across multiple JVMs (clustered application)? Yes this is another
thing that one has to take care. If still we want to maintain true Singleton object then either we have to plug
this singleton object reference in JNDI (central directory) or some other mechanism.

5|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


2. Factory Method
The Factory Method pattern is an object-oriented design pattern. Like other creational patterns, it deals
with the problem of creating objects (products) without specifying the exact class of object that will be
created. Factory Method handles this problem by defining a separate method for creating the objects,
which subclasses can then override to specify the derived type of product that will be created.
More generally, the term Factory Method is often used to refer to any method whose main purpose is
creation of objects.
The Factory Method Pattern is all about "Define an interface for creating an object, but let the subclasses
decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses" Thus,
as defined by Gamma et al, "The Factory Method lets a class defer instantiation to subclasses".
The most common structure of the factory method pattern is defined below:

Product Creator
product = factoryMethod()
factoryMethod()

ConcreteCreator
ConcreteProduct
factoryMethod() return new ConcreteProduct()

Participants
q Product – Defines the interface of objects the factory method creates.
q ConcreteProduct – Implements the product interface.
q Creator – Declares the factory method, which returns an object of type Product. Creator may also
define a default implementation of the factory method that returns a default ConcreteProduct
object.
q ConcreteCreator – Overrides the factory method to return an instance of a ConcreteProduct.

How a Factory Works


To understand a Factory Method Pattern, let’s look at another diagram below.

In this figure, x is a base class and classes xy and xz are derived from it. The Factory is a class that decides
which of these subclasses to return depending on the arguments you give it. On the right, we define a
getClass() method to be one that passes in some value abc, and that returns some instance of the class x.
Which one it returns doesn't matter to the programmer since they all have the same methods, but different

6|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


implementations. How it decides which one to return is entirely up to the factory. It could be some very
complex function but it is often quite simple.

Example: Let’s suppose an application asks for entering the name and sex of a person. If the sex is Male
(M), it displays welcome message saying Hello Mr. <Name> and if the sex is Female (F), it displays
message saying Hello Ms <Name>.

The skeleton of the code can be given here.

package example.creational.factory;

public class Person {


// name string
private String name;
// gender : M or F
private String gender;

public String getName() {


return name;
}

public String getGender() {


return gender;
}
}// End of class

This is a simple class Person having methods for name and gender. Now, we will have two sub-classes,
Male and Female which will print the welcome message on the screen.

package example.creational.factory;

public class Male extends Person {


public Male(String fullName) {
System.out.println("Hello Mr. " + fullName);
}
}// End of class

Also, the class Female


package example.creational.factory;

public class Female extends Person {


public Female(String fullNname) {
System.out.println("Hello Ms. " + fullNname);
}
}// End of class

Now, we have to create a client, or a SalutationFactory which will return the welcome message depending
on the data provided.

7|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


package example.creational.factory;

public class SalutationFactory {


public static void main(String args[]) {
SalutationFactory factory = new SalutationFactory();
factory.getPerson(args[0], args[1]);
}

public Person getPerson(String name, String gender) {


if (gender.equals("M"))
return new Male(name);
else if (gender.equals("F"))
return new Female(name);
else
return null;
}
}// End of class

This class accepts two arguments from the system at runtime and prints the names.

Running the program:


After compiling and running the code with the arguments Prashant and M:
java SalutationFactory Prashant M
The result returned is: “Hello Mr. Prashant”.

8|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


3. Abstract Factory pattern

A software design pattern, the Abstract Factory Pattern provides a way to encapsulate a group of
individual factories that have a common theme. In normal usage, the client software would create a
concrete implementation of the abstract factory and then use the generic interfaces to create the concrete
objects that are part of the theme. The client does not know (nor care) about which concrete objects it gets
from each of these internal factories since it uses only the generic interfaces of their products. This pattern
separates the details of implementation of a set of objects from its general usage.

In software development, a Factory is the location in the code at which objects are constructed. The intent
in employing the pattern is to insulate the creation of objects from their usage. This allows for new derived
types to be introduced with no change to the code that uses the base object.

Use of this pattern makes it possible to interchange concrete classes without changing the code that uses
them, even at runtime. However, employment of this pattern, as with similar design patterns, incurs the
risk of unnecessary complexity and extra work in the initial writing of code.

Application: Suppose you have the task of building a user interface framework that works on top of
multiple windowing systems, like MS-Windows, Motif, or Mac OS. It must work on each platform with
the platform's native look and feel. You organize it by creating an abstract class for each type of widget
(text field, push button, list box, etc.) and then writing a concrete subclass of each of those classes for each
supported platform. To make this robust, you need to ensure that the widget objects created are all for the
desired platform. That is where the abstract factory comes into play.
An abstract factory class defines methods to create an instance of each abstract class that represents a user
interface widget. Concrete factories are concrete subclasses of an abstract factory that implements its
methods to create instances of concrete widget classes for the same platform.

9|Sumit Agrawal | Java Architect | MCC Retail COE | HCLT


Structure: The class diagram of this design pattern is as shown below:

Participants
q Client -Classes in the Client role use various widget classes to request or receive services from the
product that the client is working with. Client classes only know about the abstract widget classes.
They should have no knowledge of any concrete widget classes.
q AbstractFactory - AbstractFactory classes define abstract methods for creating instances of
concrete widget classes. Abstract factory classes have a static method shown in the above diagram
as getFactory. Another common name for that method is getToolkit. A Client object calls that
method to get an instance of a concrete factory appropriate for working with a particular product.
q ConcreteFactory1, ConcreteFactory2 - Classes in this role implement the methods defined by
their abstract factory superclasses to create instances of concrete widget classes. Client classes that
call these methods should not have any direct knowledge of these concrete factory classes, but
instead access singleton instances of these classes by calling a method of their abstract factory
superclass.
q WidgetA, WidgetB - Interfaces in this role correspond to a feature of a product. Classes that
implement an interface in this role work with the product to which the interface corresponds.
q Product1WidgetA, Product2WidgetA - Classes in this role are concrete classes that correspond
to a feature of a product that they work with. You can generically refer to classes in this role as
concrete widgets.

10 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example:
/* GUIFactory example */
package example.creational.absfac;
public abstract class GUIFactory {
public static GUIFactory getFactory() {
int sys = readFromConfigFile("OS_TYPE");
if (sys == 0) {
return (new WinFactory());
} else {
return (new OSXFactory());
}
}

private static int readFromConfigFile(String osType) {


return 0;
}

public abstract Button createButton();


}

package example.creational.absfac;
class WinFactory extends GUIFactory {
public Button createButton() {
return (new WinButton());
}
}

package example.creational.absfac;
class OSXFactory extends GUIFactory {
public Button createButton() {
return (new OSXButton());
}
}

package example.creational.absfac;
public abstract class Button {

private String caption;

public abstract void paint();

public String getCaption() {


return caption;
}

public void setCaption(String caption) {


this.caption = caption;
}
}

package example.creational.absfac;

class WinButton extends Button {


public void paint() {
System.out.println("I'm a WinButton: " + getCaption());
}
}

11 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
package example.creational.absfac;
class OSXButton extends Button {
public void paint() {
System.out.println("I'm a OSXButton: " + getCaption());
}
}

package example.creational.absfac;
public class Application {
public static void main(String[] args) {
GUIFactory aFactory = GUIFactory.getFactory();
Button aButton = aFactory.createButton();
aButton.setCaption("Play");
aButton.paint();
}
}

Output is : I'm a WinButton: Play

12 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
4. Builder pattern
Builder is used to separate the construction of complex objects from their representation so the
construction process can be used to create different representations. The construction logic is isolated from
the actual steps used to create the complex object and, therefore, the construction process can be reused to
create different complex objects from the same set of simple objects. This tends to reduce the size of
classes by factoring out methods that are responsible for constructing complex objects into a single class
(called a Director) that is responsible for knowing how to build complex objects. In addition, Builder can
be used when you want to create objects in a step-wise manner depending on parameters you acquire along
the way.
The class diagram shown in the next figure shows the client instantiates the Builder and Director classes.
The Builder represents the complex object in terms of simpler objects and primitive types. The client then
passes the Builder object, as a parameter, to the Director's constructor, which is responsible for calling the
appropriate Builder methods. An abstract AbstractBuilder class is created to provide the Director with a
uniform interface for all concrete Builder classes. Thus, you can add new types of complex objects by
defining only the structure (Builder) and reuse the logic for the actual construction process (Director). Only
the client needs to know about the new types. The Director simply needs to know which Builder methods
to call.
Builder, as the name suggests builds complex objects from simple ones step-by-step. It separates the
construction of complex objects from their representation.

Participants
q Builder - Abstract interface for creating products.
q Concrete Builder - Provides implementation for Builder and constructs and assembles parts to
build the products.
q Director - Construct an object using the Builder pattern.
q Product - The complex object under construction

13 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example:
/** "Product" */
package example.creational.builder;
public class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";

public void setDough(String dough) {


this.dough = dough;
}

public void setSauce(String sauce) {


this.sauce = sauce;
}

public void setTopping(String topping) {


this.topping = topping;
}
}

/** "Abstract Builder" */


package example.creational.builder;
public abstract class PizzaBuilder {
protected Pizza pizza;

public Pizza getPizza() {


return pizza;
}

public void createNewPizzaProduct() {


pizza = new Pizza();
}

public abstract void buildDough();

public abstract void buildSauce();

public abstract void buildTopping();


}
/** "ConcreteBuilder" */
package example.creational.builder;
class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildDough() {
pizza.setDough("cross");
}

public void buildSauce() {


pizza.setSauce("mild");
}

public void buildTopping() {


pizza.setTopping("ham+pineapple");
}
}

14 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
/** "ConcreteBuilder" */
package example.creational.builder;
class SpicyPizzaBuilder extends PizzaBuilder {
public void buildDough() {
pizza.setDough("pan baked");
}

public void buildSauce() {


pizza.setSauce("hot");
}

public void buildTopping() {


pizza.setTopping("pepperoni+salami");
}
}

/** "Director" */
package example.creational.builder;

class Waiter {
private PizzaBuilder pizzaBuilder;

public void setPizzaBuilder(PizzaBuilder pb) {


pizzaBuilder = pb;
}

public Pizza getPizza() {


return pizzaBuilder.getPizza();
}

public void constructPizza() {


pizzaBuilder.createNewPizzaProduct();
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
}
}
/** A customer ordering a pizza. */
package example.creational.builder;

class BuilderExample {
public static void main(String[] args) {
Waiter waiter = new Waiter();
PizzaBuilder hawaiian_pizzabuilder = new HawaiianPizzaBuilder();
PizzaBuilder spicy_pizzabuilder = new SpicyPizzaBuilder();
waiter.setPizzaBuilder(hawaiian_pizzabuilder);
waiter.constructPizza();
Pizza pizza = waiter.getPizza();
}
}

15 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
5. Prototype Pattern
The prototype means making a clone. This implies cloning of an object to avoid creation. If the cost of
creating a new object is large and creation is resource intensive, we clone the object. We use the interface
Cloneable and call its method clone() to clone the object.

It assumes that an initialized and instantiated class is available and clones it to make new instances rather
than creating new instances.

When we are not in a position to call a constructor for an object directly, we could alternatively clone a
pre-existing object (a prototype) of the same class.
Structure: The class diagram of this design pattern is as shown below:

Participants
q Prototype - Declares an interface for cloning itself.
q Concrete Prototypes – Implement an operation for cloning itself.
q Client – Creates a new object by asking a prototype to clone itself.
Example: Version-1 which uses method myClone() of prototype class SwimData. The method’s
implementation is provided by the concrete prototype class TimeSwimData.

//Client Class: SwimInfo


package example.creational.prototype;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SwimInfo extends Frame implements ActionListener {


SwimData sdata, sxdata = null;
List swList, cloneList;
Button Clone, Refresh, Quit;
Swimmer sw;

public SwimInfo() {
super("Prototype example");
sdata = new TimeSwimData("swimmers.txt");
setGUI();
loadswList();
}

16 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// -----------------------------------
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == Clone)
try {
cloneAndLoad();
} catch (CloneNotSupportedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (obj == Refresh)
loadswList();
if (obj == Quit)
System.exit(0);
}

// -----------------------------------
private void cloneAndLoad() throws CloneNotSupportedException {
// sxdata = sdata.myClone(); //deep cloning
sxdata = (SwimData) sdata.cloneMe(); // shallow cloning
sxdata.sort();
cloneList.removeAll();
// now print out sorted values from clone
for (int i = 0; i < sxdata.size(); i++) {
sw = sxdata.getSwimmer(i);
cloneList.add(sw.getName() + " " + sw.getTime());
}
}

// -----------------------------------
private void loadswList() {
swList.removeAll();
for (int i = 0; i < sdata.size(); i++) {
sw = sdata.getSwimmer(i);
swList.add(sw.getName() + " " + sw.getTime());
}
}

// -----------------------------------

private void setGUI() {


setLayout(new GridLayout(1, 3));
setBackground(Color.lightGray);
swList = new List(15);
cloneList = new List(15);
Panel cp = new Panel();
add(swList);
add(cp);
add(cloneList);
Clone = new Button("Clone -->");
Refresh = new Button("<--Refresh");
Quit = new Button("Quit");
cp.setLayout(new GridLayout(3, 1));
Panel p1 = new Panel();
cp.add(p1);
p1.add(Clone);
Panel p2 = new Panel();
cp.add(p2);
p2.add(Refresh);

17 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Panel p3 = new Panel();
cp.add(p3);
p3.add(Quit);
Clone.addActionListener(this);
Refresh.addActionListener(this);
Quit.addActionListener(this);
setBounds(100, 100, 500, 400);
setVisible(true);
}

// -----------------------------------
static public void main(String argv[]) {
new SwimInfo();
}
}
//Prototype Class: SwimData
package example.creational.prototype;

import java.io.*;
import java.util.*;

class Swimmer implements Serializable {


String name;
int age;
String club;
float time;
boolean female;

public Swimmer(String dataline) {


StringTokenizer st = new StringTokenizer(dataline, ",");
name = st.nextToken();
age = new Integer(st.nextToken().trim()).intValue();
club = st.nextToken().trim();
time = new Float(st.nextToken().trim()).floatValue();
String sx = st.nextToken().trim().toUpperCase();
female = sx.equals("F");
}

public boolean isFemale() {


return female;
}

public int getAge() {


return age;
}

public float getTime() {


return time;
}

public String getName() {


return name;
}
public String getClub() {
return club;
}
}

18 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//InputFile: Class for Reading Swimmers’ data from text file (Swimmers.txt)
package example.creational.prototype;

import java.awt.*;
import java.io.*;

public class InputFile {


RandomAccessFile f = null;
boolean errflag;
String s = null;

public InputFile(String fname) {


errflag = false;
try {
// open file
f = new RandomAccessFile(fname, "r");
} catch (IOException e) {
// print error if not found
System.out.println("no file found");
errflag = true; // and set flag
}
}

// -----------------------------------------
public boolean checkErr() {
return errflag;
}

// -----------------------------------------
public String read() {
// read a single field up to a comma or end of line
String ret = "";
if (s == null) // if no data in string
{
s = readLine(); // read next line
}
if (s != null) // if there is data
{
s.trim(); // trim off blanks
int i = s.indexOf(","); // find next comma
if (i <= 0) {
ret = s.trim(); // if no commas go to end of line
s = null; // and null out stored string
} else {
ret = s.substring(0, i).trim(); // return left of comma
s = s.substring(i + 1); // save right of comma
}
} else
ret = null;
return ret; // return string
}

// -----------------------------------------
public String readLine() {
// read in a line from the file
s = null;
try {
s = f.readLine(); // could throw error
} catch (IOException e) {

19 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
errflag = true;
System.out.println("File read error");
}
return s;
}

// -----------------------------------------
public void close() {
try {
f.close(); // close file
} catch (IOException e) {
System.out.println("File close error");
errflag = true;
}
}
// -----------------------------------------
}

//Swimmers.txt : Text File Containing swimmers’ data.


Kristen Frost, 9, CAT, 26.31, F
Kimberly Watcke, 10, CDEV,27.37, F
Jaclyn Carey, 10, ARAC, 27.53, F
Megan Crapster, 10, LEHY, 27.68, F
Kaitlyn Ament, 10, HNHS, 28.20, F
Jackie Rogers, 10, WCA, 28.68, F
Erin McLaughlin, 9, HMST, 28.80, F
Emily Ferrier, 10, NMIL, 28.85, F
Aurora Lee, 8, FFLY, 28.88, F
Kate Isselee, 9, NMIL, 28.91, F
Luke Mester, 10, GYWD, 24.88, M
Stephen Cosme, 9, OAK, 27.89, M
Jeffrey Sudbury, 10, WYW, 28.24, M
Ernest Verrico, 9, SHKS, 28.46, M
David Liebovitz, 10, WYW, 28.78, M
Ryan Rynazewski, 10, AJSC, 28.83, M
Matthew Donch, 9, PSDY, 28.95, M
Christopher Prus, 10, RAYS, 29.02, M
Charles Baker, 10, PSDY, 29.06, M
Matthew Sweitzer, 10, SHKS, 29.10, M
//Concrete Prototype Class: TimeSwimData
package example.creational.prototype;

import java.util.*;
import java.io.*;

public class TimeSwimData extends SwimData implements Cloneable, Serializable {


protected ArrayList swimmers;

public TimeSwimData(String filename) {


String s = "";
swimmers = new ArrayList();
InputFile f = new InputFile(filename);
s = f.readLine();

20 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
while (s != null) {
swimmers.add(new Swimmer(s));
s = f.readLine();
}
f.close();
}

// -------------------------------------------
public TimeSwimData(ArrayList sw) {
// this constructor copies vector as clone
swimmers = new ArrayList();
for (int i = 0; i < sw.size(); i++) {
swimmers.add(sw.get(i));
}
}

// -------------------------------------------
public SwimData myClone() {
return new TimeSwimData(swimmers);
}

// -------------------------------------------
public int size() {
return swimmers.size();
}

// -------------------------------------------
public String getName(int i) {
Swimmer sw = getSwimmer(i);
if (sw != null)
return sw.getName();
else
return "";
}

// -------------------------------------------
public Swimmer getSwimmer(int i) {
Swimmer sw;
if ((i >= 0) && (i < swimmers.size())) {
sw = (Swimmer) swimmers.get(i);
return sw;
} else
return null;
}

// -------------------------------------------
public void sort() {
Swimmer sw;
int i, j;
int max = swimmers.size();
Swimmer sd[] = new Swimmer[max];
for (i = 0; i < max; i++)
sd[i] = (Swimmer) swimmers.get(i);
for (i = 0; i < max; i++) {
for (j = i; j < max; j++) {
if (sd[i].getTime() > sd[j].getTime()) {
sw = sd[i];
sd[i] = sd[j];
sd[j] = sw;

21 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
}
}
}
swimmers.removeAll(swimmers);
for (i = 0; i < max; i++)
swimmers.add(sd[i]);
}
}
In the original class, the names are sorted by sex and then by time, while in the cloned class, they are
sorted only by time. In the figure below, we see the simple user interface that allows us to display the
original data on the left and the sorted data in the cloned class on the right:

The left-hand list box is loaded when the program starts and the right-hand list box is loaded when you click on the
Clone button. Now, let’s click on the Refresh button to reload the left-hand list box from the original data.

Why have the names in the left-hand list box also been re-sorted? This occurs in Java because the clone
method provides a shallow copy of the original object. In other words, the references to the data objects are
copies, but they refer to the same underlying data. Thus, any operation we perform on the copied data will
also occur on the original data in the Prototype class.

In some cases, this shallow copy may be acceptable, but if you want to make a deep copy of the data, there
is a clever trick using the serializable interface. A class is said to be serializable if you can write it out as a
stream of bytes and read those bytes back in to reconstruct the class. This is how Java remote method
22 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
invocation (RMI) is implemented. However, if we declare both the Swimmer and SwimData classes as
Serializable, we can write the bytes to an output stream and reread them to create a
complete data copy of that instance of a class.
Example: Version-2 which uses method cloneMe() of prototype class SwimData. This
method makes use of the clone() method of the Object class for shallow cloning. The
SwimData class also provides method deepClone() for deep cloning. Only modified part
of the classes in the previous example is reproduced here.

//Client Class: SwimInfo


// Only method cloneAndLoad is modified as compared to previous example.
private void cloneAndLoad() {
try{ sxdata = (SwimData)sdata.cloneMe(); //shallow cloning
sxdata.sort();
}
catch(CloneNotSupportedException e){}
cloneList.removeAll();
//now print out sorted values from clone
for (int i=0; i< sxdata.size(); i++) {
sw = sxdata.getSwimmer(i);
cloneList.add(sw.getName()+" "+sw.getTime());
}
}
//Prototype Class: SwimData
import java.util.*;
import java.io.*;
//abstract class defining interface and deep clone routine
public abstract class SwimData implements Cloneable {
public abstract int size();
public abstract Swimmer getSwimmer(int i);
public abstract String getName(int i);
public abstract void sort();
public Object cloneMe() throws CloneNotSupportedException {
return super.clone();
}
//-------------------------------------------
public SwimData deepClone() {
try {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(b);
out.writeObject(this);
ByteArrayInputStream bIn = new ByteArrayInputStream(b.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bIn);
return((SwimData)oi.readObject());
} catch (Exception e) {
System.out.println("exception:"+e.getMessage());
e.printStackTrace();
return null;
}
}
}
//Swimmer: No Change

//InputFile: No Change

23 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Concrete Prototype Class: TimeSwimData

The following code has been removed as compared to previous example:

public TimeSwimData(ArrayList sw) {


//this constructor copies vector as clone
swimmers = new ArrayList ();
for (int i=0; i < sw.size (); i++) {
swimmers.add (sw.get (i));
}
}
//-------------------------------------------
public SwimData myClone() {
return new TimeSwimData(swimmers);
}

Example: Version-3 is almost same as Version-2. The only change is that the method
cloneAndLoad() makes use of the method deepClone() of the SwimData class for deep
cloning.

//Client Class: SwimInfo


// Only method cloneAndLoad is modified as compared to previous examples
private void cloneAndLoad() {
sxdata = (SwimData)sdata.deepClone(); //deep cloning
sxdata.sort ();
cloneList.removeAll();
//now print out sorted values from clone
for (int i=0; i< sxdata.size(); i++) {
sw = sxdata.getSwimmer(i);
cloneList.add(sw.getName()+" "+sw.getTime());
}
}

//Prototype Class: SwimData (No Change)

//Swimmer: No Change
//InputFile: No Change
//Concrete Prototype Class: TimeSwimData (No Change)

24 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Structural Patterns
Structural patterns describe how classes and objects can be combined to form larger structures. The
difference between class patterns and object patterns is that class patterns describe how inheritance can be
used to provide more useful program interfaces. Object patterns, on the other hand, describe how objects
can be composed into larger structures using object composition, or the inclusion of objects within other
objects.

GoF defined following structural patterns:

1. Adapter Pattern
2. Bridge Pattern
3. Composite Pattern
4. Decorator Pattern
5. Facade Pattern
6. Flyweight Pattern
7. Proxy Pattern

1. Adapter Pattern

The Adapter pattern is used to convert the programming interface of one class into that of another. We use
adapters whenever we want unrelated classes to work together in a single program. The concept of an
adapter is thus pretty simple; “Adapter pattern can let two incompatible systems communicate”

The adapter pattern is also known as Wrapper.

25 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Our job - design a class that will establish communication between two different types or we can say that
will bridge the gap among two.

//PetToWild.java
public class PetToWild implements WildAnimal{
PetAnimal pet;
public PetToWild(PetAnimal pet){
this.pet = pet;
}
public void roar(){
pet.speek();
}
public void run(){
for(int i=0;i<5;i++)
pet.walk();
}
}
//Test.java
class Test{
public static void main(String s[]){
Lion l = new Lion();
Cat c = new Cat();
WildAnimal petToWild = new PetToWild( c);
testWild(l);
testWild(petToWild);
}
static void testWild(WildAnimal wild){
wild.roar();
wild.run();
}
}

Participants
q Target – Defines the domain specific language that Client uses.
q Client – Collaborates with objects conforming to the Target interface.
q Adaptee – Defines an existing interface that needs adapting.
q Adapter – Adapts the interface of adaptee to the target interface.

26 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
2. Bridge Pattern

The bridge pattern is a design pattern used in software engineering which is meant to "decouple an
abstraction from its implementation so that the two can vary independently" (Gamma et. al.).

Structure of Bridge Pattern:

Participants

q Abstraction – Defines the abstraction's interface; maintains a reference to the Implementor and
forwards request to the Impementor.
q RefinedAbstraction – Extends the interface defined by the abstraction.
q Implementor – Defines the interface for implementation classes. This interface does not have to
correspond exactly to Abstraction’s interface; in fact the two interfaces can be quite different.
Typically the Implementor interface provides only primitive operations, and Abstraction defines
higher-level operations based on these primitives.
q ConcreteImplementor – Implements the Implementor interface and defines its concrete
implementation.

Example:

This example divides complex behavior among two categories - the abstraction and the implementation.

Abstraction provided by – BaseList, OrnamentedList and NumberedList.


The BaseList provides core funtionality, the OrnamentedList expands on the model by adding a list
character and the Numbered List expands on the model by adding serial number starting from one.

Implementation provided by -
The OrderedListImpl class provides the underlying storage capability for the list, and can be flexibly
paired with either of the classes which provide the abstraction.

27 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Implementation
package example.structural.bridge;
interface ListImpl {
public void addItem(String item);

public void addItem(String item, int position);

public void removeItem(String item);

public int getNumberOfItems();

public String getItem(int index);

public boolean supportsOrdering();


}
//Concrete Implementation
package example.structural.bridge;

import java.util.ArrayList;

class OrderedListImpl implements ListImpl {


private ArrayList items = new ArrayList();

public void addItem(String item) {


if (!items.contains(item)) {
items.add(item);
}
}

public void addItem(String item, int position) {


if (!items.contains(item)) {
items.add(position, item);
}
}

public void removeItem(String item) {


if (items.contains(item)) {
items.remove(items.indexOf(item));
}
}

public boolean supportsOrdering() {


return true;
}

public int getNumberOfItems() {


return items.size();
}

public String getItem(int index) {


if (index < items.size()) {
return (String) items.get(index);
}
return null;
}
}

28 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Abstraction
package example.structural.bridge;

class BaseList {
protected ListImpl implementor;

public void setImplementor(ListImpl impl) {


implementor = impl;
}

public void add(String item) {


implementor.addItem(item);
}

public void add(String item, int position) {


if (implementor.supportsOrdering()) {
implementor.addItem(item, position);
}
}

public void remove(String item) {


implementor.removeItem(item);
}

public String get(int index) {


return implementor.getItem(index);
}

public int count() {


return implementor.getNumberOfItems();
}
}
//Refined Abstraction
package example.structural.bridge;
class NumberedList extends BaseList {
public String get(int index) {
return (index + 1) + ". " + super.get(index);
}
}
//Refined Abstraction
package example.structural.bridge;
class OrnamentedList extends BaseList {
private char itemType;

public char getItemType() {


return itemType;
}

public void setItemType(char newItemType) {


if (newItemType > ' ') {
itemType = newItemType;
}
}
public String get(int index) {
return itemType + " " + super.get(index);
}
}

//Client

29 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
package example.structural.bridge;

public class RunBridgePattern {


public static void main(String[] arguments) {
ListImpl implementation = new OrderedListImpl();
BaseList listOne = new BaseList();
listOne.setImplementor(implementation);

listOne.add("One");
listOne.add("Two");
listOne.add("Three");
listOne.add("Four");

OrnamentedList listTwo = new OrnamentedList();


listTwo.setImplementor(implementation);
listTwo.setItemType('+');

NumberedList listThree = new NumberedList();


listThree.setImplementor(implementation);

for (int i = 0; i < listOne.count(); i++) {


System.out.println("\t" + listOne.get(i));
}

for (int i = 0; i < listTwo.count(); i++) {


System.out.println("\t" + listTwo.get(i));
}

for (int i = 0; i < listThree.count(); i++) {


System.out.println("\t" + listThree.get(i));

}
}
}
Output:

Printing out first list (BaseList)


One
Two
Three
Four
Printing out second list (OrnamentedList)
+ One
+ Two
+ Three
+ Four
Printing our third list (NumberedList)
1. One
2. Two
3. Three
4. Four

30 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
3. Composite Pattern

Frequently programmers develop systems in which a component may be an individual object or it may
represent a collection of objects. The Composite pattern is designed to accommodate both cases. You can
use the Composite to build part-whole hierarchies or to construct data representations of trees. In summary,
a composite is a collection of objects, any one of which may be either a composite, or just a primitive
object. In tree nomenclature, some objects may be nodes with additional branches and some may be leaves.
The problem that develops is the dichotomy between having a single, simple interface to access all the
objects in a composite, and the ability to distinguish between nodes and leaves. Nodes have children and
can have children added to them, while leaves do not at the moment have children, and in some
implementations may be prevented from having children added to them.

Structure of Composite Pattern:

Participants
q Component - Declares the interface for objects in composition; implements default behaviour for
the interface common to all classes, as appropriate; declares an interface for accessing and
managing its child components.
q Leaf - Represents leaf objects in the composition and defines behaviour for primitive objects in the
composition.
q Composite - Defines behaviour for components having children; stores child components and
implements child-related operations in the Component interface.
q Client - manipulates objects in the composition through the Component interface.

31 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// Component
package example.structure.composite;

import java.util.ArrayList;

interface Component {
public String defaultMethod();

public ArrayList<Component> getChildren();

public boolean addComponent(Component c);

public boolean removeComponent(Component c);


}

//Composite
package example.structure.composite;

import java.util.ArrayList;

class Composite implements Component {


private String id;
private ArrayList<Component> components = new ArrayList<Component>();

public Composite(String identification) {


id = identification;
}

public String defaultMethod() {


String s = "(" + id + ":";
for (Component child : getChildren())
s = s + " " + child.defaultMethod();
return s + ")";
}

public ArrayList<Component> getChildren() {


return components;
}

public boolean addComponent(Component c) {


return components.add(c);
}

public boolean removeComponent(Component c) {


return components.remove(c);
}
}

32 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Leaf
package example.structure.composite;

import java.util.ArrayList;

class Leaf implements Component {


private String id;

public Leaf(String identification) {


id = identification;
}

public String defaultMethod() {


return id;
}

public ArrayList<Component> getChildren() {


return null;
}

public boolean addComponent(Component c) {


return false;
}

public boolean removeComponent(Component c) {


return false;
}
}
// Client
package example.structure.composite;

class CompositePattern {
public static void main(String[] args) {
Composite england = new Composite("England");
Leaf york = new Leaf("York");
Leaf london = new Leaf("London");
england.addComponent(york);
england.addComponent(london);
england.removeComponent(york);
Composite france = new Composite("France");
france.addComponent(new Leaf("Paris"));
Composite europe = new Composite("Europe");
europe.addComponent(england);
europe.addComponent(france);
System.out.println(europe.defaultMethod());
}
}
The output is: (Europe: (England: London) (France: Paris))

33 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
4. Decorator Pattern

The Decorator Pattern is used for adding additional functionality to a particular object as opposed to a class
of objects. It is easy to add functionality to an entire class of objects by sub-classing an object, but it is
impossible to extend a single object this way. With the Decorator Pattern, you can add functionality to a
single object and leave others like it unmodified.

A Decorator, also known as a Wrapper, is an object that has an interface identical to an object that it
contains. Any calls that the decorator gets, it relays to the object that it contains, and adds its own
functionality along the way, either before or after the call. This gives you a lot of flexibility, since you can
change what the decorator does at runtime, as opposed to having the change be static and determined at
compile time by sub-classing. Since a Decorator complies with the interface that the object that it contains,
the Decorator is indistinguishable from the object that it contains. That is, a Decorator is a
concrete instance of the abstract class, and thus is indistinguishable from any other concrete instance,
including other decorators. This can be used to great advantage, as you can recursively nest decorators
without any other objects being able to tell the difference, allowing a near infinite amount of
customization.

Structure of Decorator Pattern

Participants

q Component – Defines the interface for objects that can have responsibilities added to them
dynamically.
q ConcreteComponent - Defines an object to which additional responsibilities can be attached.
q Decorator – Maintains a reference to a Component object and defines an interface that conforms to
component’s interface.
q ConcreteDecorator – Adds responsibilities to the component.

34 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example 1:
// the Window interface (Component )
package example.structure.decorator.ex1;
public interface Window {
public void draw(); // draws the Window

public String getDescription(); // Window description


}

// implementation of a simple Window without any scrollbars (ConcreteComponent)


package example.structure.decorator.ex1;
class SimpleWindow implements Window {
public void draw() {
// draw window
}

public String getDescription() {


return "simple window";
}
}

The following classes contain the decorators for all Window classes, including the decorator classes
themselves.

// abstract decorator class - note that it implements Window (Decorator)


package example.structure.decorator.ex1;
abstract class WindowDecorator implements Window {
protected Window decoratedWindow; // the Window being decorated

public WindowDecorator(Window decoratedWindow) {


this.decoratedWindow = decoratedWindow;
}
}
// the first Concrete Decorator which adds vertical scrollbar functionality
package example.structure.decorator.ex1;
class VerticalScrollBarDecorator extends WindowDecorator {
public VerticalScrollBarDecorator(Window decoratedWindow) {
super(decoratedWindow);
}

public void draw() {


drawVerticalScrollBar();
decoratedWindow.draw();
}

private void drawVerticalScrollBar() {


// draw the vertical scrollbar
}

public String getDescription() {


return decoratedWindow.getDescription()
+ ", including vertical scrollbars";
}
}

35 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// the second Concrete Decorator which adds horizontal scrollbar functionality
package example.structure.decorator.ex1;

class HorizontalScrollBarDecorator extends WindowDecorator {


public HorizontalScrollBarDecorator(Window decoratedWindow) {
super(decoratedWindow);
}

public void draw() {


drawHorizontalScrollBar();
decoratedWindow.draw();
}

private void drawHorizontalScrollBar() {


// draw the horizontal scrollbar
}

public String getDescription() {


return decoratedWindow.getDescription()
+ ", including horizontal scrollbars";
}
}

Here's a test program that creates a Window instance which is fully decorated (i.e., with vertical and
horizontal scrollbars), and prints its description:

package example.structure.decorator.ex1;

public class DecoratorWindowTest {


public static void main(String[] args) {
// create a decorated Window with horizonal and vertical scrollbars
Window decoratedWindow = new HorizontalScrollBarDecorator(
new VerticalScrollBarDecorator(new SimpleWindow()));

// print the Window's description


System.out.println(decoratedWindow.getDescription());
}
}

The output of this program is "simple window, including vertical scrollbars, including horizontal
scrollbars".
Notice how the getDescription method of the two decorators first retrieve the decorated Window's
description and "decorates" it with a suffix.

36 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example 2: The JComponent class (abstract class) is assumed to be the Component class and JLabel
class is assumed to be the ConcreteComponent class.

//Client
package example.structure.decorator.ex2;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DecoWindow extends JFrame implements ActionListener {


JButton Quit;

public DecoWindow() {
super("Deco Button");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JPanel jp = new JPanel();
getContentPane().add(jp);
jp.add(new CoolDecorator(new JButton("Cbutton")));
jp.add(new SlashDecorator(new CoolDecorator(new JButton("Dbutton"))));
jp.add(Quit = new JButton("Quit"));
Quit.addActionListener(this);
setSize(new Dimension(200, 100));
setVisible(true);
Quit.requestFocus();
}

public void actionPerformed(ActionEvent e) {


System.exit(0);
}

static public void main(String argv[]) {


new DecoWindow();
}
}
}
//Decorator
package example.structure.decorator.ex2;

import java.awt.BorderLayout;
import javax.swing.JComponent;

class Decorator extends JComponent {


public Decorator(JComponent c) {
setLayout(new BorderLayout());
add("Center", c);
}
}

37 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Concrete Decorator 1
package example.structure.decorator.ex2;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;

class SlashDecorator extends Decorator {


public SlashDecorator(JComponent c) {
super(c);
}

public void paint(Graphics g) {


super.paint(g);
g.setColor(Color.red);
g.drawLine(0, 0, getSize().width, getSize().height);
}
}
//Concrete Decorator 2
package example.structure.decorator.ex2;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JComponent;
class CoolDecorator extends Decorator {
boolean mouse_over; // true when mouse over button
JComponent thisComp;
public CoolDecorator(JComponent c) {
super(c);
mouse_over = false;
thisComp = this; // save this component
// catch mouse movements in inner class
c.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
mouse_over = true; // set flag when mouse over
thisComp.repaint();
}

public void mouseExited(MouseEvent e) {


mouse_over = false; // clear flag when mouse not over
thisComp.repaint();
}
});
}
// paint the button
public void paint(Graphics g) {
super.paint(g); // first draw the parent button
if (!mouse_over){
// if the mouse is not over the button erase the borders
Dimension size = super.getSize();
g.setColor(Color.lightGray);
g.drawRect(0, 0, size.width - 1, size.height - 1);
g.drawLine(size.width - 2, 0, size.width - 2, size.height - 1);
g.drawLine(0, size.height - 2, size.width - 2, size.height - 2);
}
}
}

38 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example 3 –
TODO - You have used java IO package several times. But this time we want to create a stream
class that will convert all uppercase characters into lowercase characters and this class must respect
the IO API, means we must be able to wrap this class into BufferedInputStream or others.

package example.structure.decorator.ex3;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public class LowercaseInputStream extends FilterInputStream {


public LowercaseInputStream(InputStream in) {
super(in);
}

public int read() throws IOException {


int c = super.read();
return (c == -1 ? c : Character.toLowerCase((char) c));
}

public int read(byte[] b, int offset, int len) throws IOException {


int result = super.read(b, offset, len);
for (int i = offset; i < offset + result; i++) {
b[i] = (byte) Character.toLowerCase((char) b[i]);
}
return result;
}
}

Yes, FilterInputStream in IO package is an abstract Decorator, BufferedInputStream,


DataInputStream etc are concrete decorators, while InputStream is component and FileInputStream,
and ByteArrayInputStream etc are concrete component.

39 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
5. Facade Pattern

Facade as the name suggests means the face of the building. The people walking past the road can only see
this glass face of the building. They do not know anything about it, the wiring, the pipes and other
complexities. The face hides all the complexities of the building and displays a friendly face.

This is how facade pattern is used. It hides the complexities of the system and provides an interface to the
client from where the client can access the system. In Java, the interface JDBC can be called a facade. We
as users or clients create connection using the “java.sql.Connection” interface, the implementation of
which we are not concerned about. The implementation is left to the vendor of driver.

A façade is an object that provides a simplified interface to a larger body of code, such as a class library. A
façade can:

1. make a software library easier to use and understand, since the façade has convenient methods for
common tasks;
2. make code that uses the library more readable, for the same reason;
3. reduce dependencies of outside code on the inner workings of a library, since most code uses the
façade, thus allowing more flexibility in developing the system;
4. Wrap a poorly designed collection of APIs with a single well-designed API.

Structure of Facade Pattern:

40 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Participants

q Facade (Databas Class)


- Knows which subsystem classes are responsible for a request.
- Delegates client requests to appropriate subsystem objects.

q Subsystem classes (Connection, DatabaseMetaData, Results: ResultSet, ResultSetMetaData)


- Implement subsystem functionality.
- Handle work assigned by the Facade object.
- Have no knowledge of the facade and keep no reference to it.

Example:
//Client
package example.structure.facade;

import java.awt.*;
import java.awt.event.*;

public class DBFrame extends Frame implements ActionListener, ItemListener {


Database db;
List Tables, Columns, Data;
TextArea query;
Button Search, Quit;

public DBFrame() {
super("Database demonstration");
setGUI();
db = new Database("org.gjt.mm.mysql.Driver");
db.Open("jdbc:mysql://127.0.0.1:3306/student", "root", "root");
String tnames[] = db.getTableNames();
loadList(Tables, tnames);
String queryText = "SELECT * FROM Employee";
query.setText(queryText);
}

// ------------------------------------
private void setGUI() {
setBackground(Color.lightGray);
setLayout(new BorderLayout());
Panel pn = new Panel();
add("North", pn);
pn.setLayout(new GridLayout(1, 3));
pn.add(new Label("Tables"));
pn.add(new Label("Columns"));
pn.add(new Label("Data"));
Panel pc = new Panel();
add("Center", pc);
pc.setLayout(new GridLayout(1, 3));
pc.add(Tables = new java.awt.List(15));
pc.add(Columns = new java.awt.List(15));
pc.add(Data = new java.awt.List(15));
Tables.addItemListener(this);
Columns.addItemListener(this);
Panel ps = new Panel();
add("South", ps);

41 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
ps.add(query = new TextArea("", 3, 40));
addPanel(ps, Search = new Button("Run Query"));
addPanel(ps, Quit = new Button("Quit"));
Search.addActionListener(this);
Quit.addActionListener(this);
setBounds(100, 100, 500, 300);
setVisible(true);
}

// ------------------------------------
private void addPanel(Panel ps, Component c) {
Panel p = new Panel();
ps.add(p);
p.add(c);
}

// ------------------------------------
private void loadList(java.awt.List list, String[] s) {
list.removeAll();
for (int i = 0; i < s.length; i++)
list.add(s[i]);
}

// ------------------------------------
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == Quit)
System.exit(0);
if (obj == Search)
clickedSearch();
}

// ------------------------------------
public void itemStateChanged(ItemEvent e) {
Object obj = e.getSource();
if (obj == Tables)
showColumns();
if (obj == Columns)
showData();
}

// ------------------------------------
private void showColumns() {
String cnames[] = db.getColumnNames(Tables.getSelectedItem());
loadList(Columns, cnames);
}

// ------------------------------------
private void showData() {
String colname = Columns.getSelectedItem();
String colval = db.getColumnValue(Tables.getSelectedItem(), colname);
Data.setVisible(false);
Data.removeAll();
Data.setVisible(true);
// System.out.println("Col Val:" + colval);
while (colval.length() > 0) {
Data.add(colval);
colval = db.getNextValue(Columns.getSelectedItem());
}

42 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
}

// ------------------------------------
private void clickedSearch() {
Results rs = db.Execute(query.getText());
queryDialog q = new queryDialog(this, rs);
q.show();
}

// ------------------------------------
static public void main(String argv[]) {
new DBFrame();
}
}

//Class for displaying Query Output


package example.structure.facade;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

class QueryDialog extends Dialog implements ActionListener {


Results results;
Button OK;
textPanel pc;
ArrayList tables;

public QueryDialog(Frame f, Results r) {


super(f, "Query Result");
results = r;
setLayout(new BorderLayout());
OK = new Button("OK");
Panel p = new Panel();
add("South", p);
p.add(OK);
OK.addActionListener(this);
pc = new textPanel();
pc.setBackground(Color.white);
add("Center", pc);
makeTables();
setBounds(100, 100, 500, 300);
setVisible(true);
repaint();
}

// -------------------------------------
private void makeTables() {
tables = new ArrayList();
String t[] = results.getMetaData();// to get column names
tables.add(t);
while (results.hasMoreElements()) // to get column values
{
tables.add(results.nextElement());
}
}

43 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// -------------------------------------
public void actionPerformed(ActionEvent e) {
setVisible(false);
}

// -------------------------------------
class textPanel extends Panel {
public void paint(Graphics g) {
String s[];
int x = 0;
int y = g.getFontMetrics().getHeight();
int deltaX = (int) 1.5f * (g.getFontMetrics().stringWidth("wwwwwwwwwwwwww"));
for (int i = 0; i < tables.size(); i++) {
s = (String[]) tables.get(i);
for (int j = 0; j < s.length; j++) {
String st = s[j];
g.drawString(st, x, y);
x += deltaX;
}
x = 0;
y += g.getFontMetrics().getHeight();
if (i == 0)
y += g.getFontMetrics().getHeight();
}
}
}
}
//Façade Class : Database
package example.structure.facade;

import java.sql.*;
import java.util.ArrayList;

class Database {
Connection con;
Results results;
DatabaseMetaData dma;
String catalog = null;
String types[];
String database_url;

public Database(String driver) {


types = new String[1];
types[0] = "TABLE"; // initialize type array
try {
Class.forName(driver);
} // load the driver
catch (Exception e) {
System.out.println(e.getMessage());
}
}

// -----------------------------------
public void close() {
try {
con.close();
} catch (Exception e) {
System.out.println("close error");
}

44 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
}

// -----------------------------------

public void Open(String url, String user, String password) {

database_url = url;
try {
con = DriverManager.getConnection(url, user, password);
dma = con.getMetaData(); // get the meta data
} catch (Exception e) {
System.out.println(e.getMessage());
}
}

// -----------------------------------
public void reOpen() {
try {
con = DriverManager.getConnection(database_url);
dma = con.getMetaData(); // get the meta data
} catch (Exception e) {
System.out.println(e.getMessage());
}
}

// -----------------------------------
public String[] getTableNames() {
String[] tbnames = null;
ArrayList tname = new ArrayList();
// add the table names to a Vector
// since we don't know how many there are
try {
// getTables(String catalog, String schemaPattern,
// String tableNamePattern, String[] types)
results = new Results(dma.getTables(catalog, null, "%", types));
} catch (Exception e) {
System.out.println(e);
}
while (results.hasMoreElements())
tname.add(results.getColumnValue("TABLE_NAME"));

// copy the table names into a String array


tbnames = new String[tname.size()];
for (int i = 0; i < tname.size(); i++)
tbnames[i] = (String) tname.get(i);
return tbnames;
}

// -----------------------------------
public String[] getTableMetaData() {
// return the table type information
results = null;
try {
results = new Results(dma.getTables(catalog, null, "%", types));
} catch (Exception e) {
System.out.println(e.getMessage());
}
return results.getMetaData();
}

45 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// -----------------------------------
public String[] getColumnMetaData(String tablename) {
// return the data on a column
results = null;
try { // getColumns(String catalog, String schemaPattern,
// String tableNamePattern, String columnNamePattern)
results = new Results(dma
.getColumns(catalog, null, tablename, null));
} catch (Exception e) {
System.out.println(e.getMessage());
}
return results.getMetaData();
}

// -----------------------------------
public String[] getColumnNames(String table) {
// return an array of Column names
String[] tbnames = null;
ArrayList tname = new ArrayList();
try {
results = new Results(dma.getColumns(catalog, null, table, null));
while (results.hasMoreElements())
tname.add(results.getColumnValue("COLUMN_NAME"));
} catch (Exception e) {
System.out.println(e);
}
tbnames = new String[tname.size()];
for (int i = 0; i < tname.size(); i++)
tbnames[i] = (String) tname.get(i);
return tbnames;
}

// -----------------------------------
public String getColumnValue(String table, String columnName) {
// return the value of a given column
String res = null;
try {
if (table.length() > 0)
results = Execute("Select " + columnName + " from " + table
+ " order by " + columnName);
if (results.hasMoreElements())
res = results.getColumnValue(columnName);
} catch (Exception e) {
System.out.println("Column value error" + columnName
+ e.getMessage());
}
return res;
}

// -----------------------------------
public String getNextValue(String columnName) {
// return the next value in that column
// using the remembered Results
String res = "";
try {
if (results.hasMoreElements())
res = results.getColumnValue(columnName);
} catch (Exception e) {

46 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
System.out.println("next value error" + columnName + e.getMessage());
}
return res;
}

// -----------------------------------
public Results Execute(String sql) {
// execute an SQL query on this database
results = null;
try {
Statement stmt = con.createStatement();
results = new Results(stmt.executeQuery(sql));
} catch (Exception e) {
System.out.println("execute error: " + e.getMessage());
}
return results;
}
}

//Façade Class : Results


package example.structure.facade;

import java.sql.*;

class Results {
// this class is a higher level abstraction
// of the JDBC ResultSet object
ResultSet rs;
ResultSetMetaData rsmd;
int numCols;

public Results(ResultSet rset) {


rs = rset;
try {
// get the meta data and column count at once
rsmd = rs.getMetaData();
numCols = rsmd.getColumnCount();
} catch (Exception e) {
System.out.println("resultset error" + e.getMessage());
}
}

// -----------------------------------
public String[] getMetaData() {
// returns an array of all the column names
// or other meta data
String md[] = new String[numCols];
try {
for (int i = 1; i <= numCols; i++)
md[i - 1] = rsmd.getColumnName(i);
} catch (Exception e) {
System.out.println("meta data error" + e.getMessage());
}
return md;
}
// -----------------------------------
public boolean hasMoreElements() {
try {
return rs.next();
47 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
} catch (Exception e) {
System.out.println("next error " + e.getMessage());
return false;
}
}
// -----------------------------------
public String[] nextElement() {
// copies contents of row into string array
String[] row = new String[numCols];
try {
for (int i = 1; i <= numCols; i++)
row[i - 1] = rs.getString(i);
} catch (Exception e) {
System.out.println("next element error" + e.getMessage());
}
return row;
}
// -------------------------------------
public String getColumnValue(String columnName) {
String res = "";
try {
res = rs.getString(columnName);
} catch (Exception e) {
System.out.println("Column value error:" + columnName
+ e.getMessage());
}
return res;
}

// -------------------------------------
public String getColumnValue(int i) {
String res = "";
try {
res = rs.getString(i);
} catch (Exception e) {
System.out.println("Column value error: " + i + " "
+ e.getMessage());
}
return res;
}

// ----------------------------------------------
public void finalize() {
try {
rs.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

These simple classes allow us to write a program for opening a database, displaying its table names,
column names and contents, and running simple SQL query on the database.

48 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
49 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
6. Flyweight Pattern
This pattern states about a mechanism by which you can avoid creating a large number of object instances
to represent the entire system. To decide if some part of your program is a candidate for using Flyweights,
consider whether it is possible to remove some data from the class and make it extrinsic. If this makes it
possible to reduce greatly the number of different class instances your program needs to maintain, this
might be a case where Flyweights will help.

The typical example you can see on this in every book will be of folders. The folder with name of each of
the company employee on it, so, the attributes of class Folder are: ‘Selected’ , ‘Not Selected’ and the third
one is ‘employeeName’. With this methodology, we will have to create 2000 folder class instances for
each of the employees. This can be costly, so we can create just two class instances with attributes
‘selected’ and ‘not selected’ and set the employee’s name by a method like:
setNameOnFolder(String name);

This way, the instances of class folder will be shared and you will not have to create multiple instances for
each employee.

Structure of Flyweight Pattern:

50 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Participants
q Flyweight
o Declares an interface through which flyweights can receive and act on extrinsic state.
q ConcreteFlyweight
o Implements the Flyweight interface and adds storage for intrinsic state, if any. A
ConcreteFlyweight object must be sharable. Any state it stores must be intrinsic, that is, it
must be independent of the ConcreteFlyweight object's context.
q UnsharedConcreteFlyweight
o Not all Flyweight subclasses need to be shared. The Flyweight interface enables sharing,
but it doesn't enforce it. It is common for UnsharedConcreteFlyweight objects to have
ConcreteFlyweight objects as children at some level in the flyweight object structure.

q FlyweightFactory
o Creates and manages flyweight objects.
o Ensures that flyweight are shared properly. When a client requests a flyweight, the
FlyweightFactory objects supplies an existing instance or creates one, if none exists.
q Client
o Maintains a reference to flyweight(s).
o computes or stores the extrinsic state of flyweight(s).

Example:

Suppose we want to draw a small folder icon with a name under it for each person in a an organization. If
this is a large organization, there could be a large number of such icons, but they are actually all the same
graphical image. Even if we have two icons, one for “is Selected” and one for “not Selected” the number
of different icons is small.

In such a system, having an icon object for each person, with its own coordinates, name and selected state
is a waste of resources. Instead, we’ll create a FolderFactory that returns either the selected or the
unselected folder drawing class, but does not create additional instances once one of each has been created.
Since this is such a simple case, we just create them both at the outset and then return one or the other:

For cases where more instances could exist, the factory could keep a table of the ones it had already
created and only create new ones if they weren’t already in the table.

The unique thing about using Flyweights, however, is that we pass the coordinates and the name to be
drawn into the folder when we draw it. These coordinates are the extrinsic data that allow us to share the
folder objects, and in this case create only two instances. The complete folder class shown below simply
creates a folder instance with one background color or the other and has a public Draw method that draws
the folder at the point you specify.

To use a Flyweight class like this, your main program must calculate the position of each folder as part of
its paint routine and then pass the coordinates to the folder instance. This is actually rather common, since
you need a different layout depending on the window’s dimensions, and you would not want to have to
keep telling each instance where its new location is going to be. Instead, we compute it dynamically during
the paint routine.

51 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// Flyweight interface
package example.structure.flyweight;
import java.awt.*;

public interface FolderInterface {


public void draw(Graphics g, int tx, int ty, String name);
}
//Flyweight Factory
package example.structure.flyweight;

import java.awt.*;

class FolderFactory {
Folder unSelected, selected;

public FolderFactory() {
Color brown = new Color(0x5f5f1c);
selected = new Folder(brown);
unSelected = new Folder(Color.yellow);
}

// -------------------------------
public Folder getFolder(boolean isSelected) {
if (isSelected)
return selected;
else
return unSelected;
}

}
}
// Concrete Flyweight class
package example.structure.flyweight;

import java.awt.*;
import javax.swing.*;

class Folder implements FolderInterface {


private Color color;
final int W = 50, H = 30;
final int tableft = 0, tabheight = 4, tabwidth = 20, tabslant = 3;

public Folder(Color c) {
color = c;
}

// -------------------------------
public void draw(Graphics g, int tx, int ty, String name) {
g.setColor(Color.black); // outline
g.drawRect(tx, ty, W, H);
g.drawString(name, tx, ty + H + 15); // title
g.setColor(Color.white);
g.drawLine(tx, ty, tx + W, ty);
Polygon poly = new Polygon();
poly.addPoint(tx + tableft, ty);
poly.addPoint(tx + tableft + tabslant, ty - tabheight);
poly.addPoint(tx + tabwidth - tabslant, ty - tabheight);
poly.addPoint(tx + tabwidth, ty);
g.setColor(Color.black);

52 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
g.drawPolygon(poly);
g.setColor(color); // fill rectangle
g.fillRect(tx + 1, ty + 1, W - 1, H - 1);
g.fillPolygon(poly);
g.setColor(Color.white);
g.drawLine(tx, ty, tx + W, ty);
g.setColor(Color.lightGray); // bend line
g.drawLine(tx + 1, ty + H - 5, tx + W - 1, ty + H - 5);
g.setColor(Color.black); // shadow lines
g.drawLine(tx, ty + H + 1, tx + W - 1, ty + H + 1);
g.drawLine(tx + W + 1, ty, tx + W + 1, ty + H);
g.setColor(Color.white); // highlight lines
g.drawLine(tx + 1, ty + 1, tx + W - 1, ty + 1);
g.drawLine(tx + 1, ty + 1, tx + 1, ty + H - 1);
}
}
// Client class
package example.structure.flyweight;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;

public class FlyCanvas extends JFrame implements MouseMotionListener,


WindowStateListener {
Folder folder;
ArrayList names;
ArrayList folders;
FolderFactory fact;
final int Top = 30, Left = 30;
final int W = 50, H = 30;
final int VSpace = 80, HSpace = 70, HCount = 3;
String selectedName = "";

// -------------------------------
public FlyCanvas() {
super("Flyweight Canvas");
loadNames();
loadFolders();
JPanel jp = new JPanel();
getContentPane().add(jp);
setSize(new Dimension(300, 300));
addMouseMotionListener(this);
addWindowStateListener(this);
setVisible(true);
repaint();
}

// -------------------------------
private void loadFolders() {
folders = new ArrayList();
for (int i = 0; i < names.size(); i++) {
folders.add(fact.getFolder(false));
}
}

// -------------------------------
private void loadNames() {

53 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
names = new ArrayList();
fact = new FolderFactory();
names.add("Sumit");
names.add("Amit");
names.add("Pankaj");
names.add("Abhay");
names.add("Raj Kumar");
names.add("Shadab");
names.add("Vishal");
names.add("Pragya");
names.add("Daya Shanker");
names.add("Manoj");

selectedName = "";

// -------------------------------
public void paint(Graphics g) {
Folder f;
String name;

int j = 0; // count number in row


int row = Top; // start in upper left
int x = Left;

// go through all the names and folders


for (int i = 0; i < names.size(); i++) {
name = (String) names.get(i);
f = (Folder) folders.get(i);
if (name.equals(selectedName))
f = fact.getFolder(true);

// have that folder draw itself at this spot


f.draw(g, x, row, name);
x = x + HSpace; // change to next posn
j++;
if (j >= HCount) { // reset for next row
j = 0;
row += VSpace;
x = Left;
}
}
}

// -------------------------------
public void mouseMoved(MouseEvent e) {
int j = 0; // count number in row
int row = Top; // start in upper left
int x = Left;
// go through all the names and folders
for (int i = 0; i < names.size(); i++) {
// see if this folder contains the mouse
Rectangle r = new Rectangle(x, row, W, H);
if (r.contains(e.getX(), e.getY())) {
selectedName = (String) names.get(i);
repaint();
}
x = x + HSpace; // change to next posn

54 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
j++;
if (j >= HCount) { // reset for next row
j = 0;
row += VSpace;
x = Left;
}
}

public void mouseDragged(MouseEvent e) {


}

public void windowStateChanged(WindowEvent we) {


System.out.println("in change");
repaint();
}

// -------------------------------
static public void main(String[] argv) {
new FlyCanvas();
}
}

The output of the above program is shown below:

55 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
7. Proxy Pattern

The Proxy pattern is used when you need to represent a complex object by a simpler one. If creating an
object is expensive in time or computer resources, Proxy allows you to postpone this creation until you
need the actual object. A Proxy usually has the same methods as the object it represents, and once the
object is loaded, it passes on the method calls from the Proxy to the actual object.

There are several cases where a Proxy can be useful:

1. If an object, such as a large image, takes a long time to load.


2. If the object is on a remote machine and loading it over the network may be slow, especially during
peak network load periods.
3. If the object has limited access rights, the proxy can validate the access permissions for that user.

Proxies can also be used to distinguish between requesting an instance of an object and the actual need to
access it. For example, program initialization may set up a number of objects, which may not all be used
right away. In that case, the proxy can load the real object only when it is needed.

Let’s consider the case of a large image that a program needs to load and display. When the program starts,
there must be some indication that an image is to be displayed so that the screen lays out correctly, but the
actual image display can be postponed until the image is completely loaded. This is particularly important
in programs such as word processors and web browsers that lay out text around the images even before the
images are available.
An image proxy can note the image and begin loading it in the background, while drawing a simple
rectangle or other symbol to represent the image’s extent on the screen before it appears. The proxy can
even delay loading the image at all until it receives a paint request, and only then begin the process.
Structure of Proxy Pattern :

56 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Participants:

q Proxy
o Maintains a reference that lets the proxy access the real subject. Proxy may refer to a
Subject if the RealSubject and Subject interfaces are the same.
o Provides an interface identical to Subject's so that a proxy can be substituted for the real
subject.
o Controls access to the real subject and may be responsible for creating and deleting it.

other responsibilites depend on the kind of proxy:

o Remote proxies are responsible for encoding a request and its arguments and for sending the
encoded request to the real subject in a different address space.
o Virtual proxies may cache additional information about the real subject so that they can
postpone accessing it. For example, the ImageProxy caches the real images's extent.
o Protection proxies check that the caller has the access permissions required to perform a
request.

q Subject
o Defines the common interface for RealSubject and Proxy so that a Proxy can be used
anywhere a RealSubject is expected.
q RealSubject
o Defines the real object that the proxy represents.
Example: In this example program, we create a simple program to display an image on a JPanel when it is
loaded. Rather than loading the image directly, we use a class we call ImageProxy to defer loading and
draw a rectangle around the image area until loading is completed.

//ImageProxy
package example.structure.proxy;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;

import javax.swing.JPanel;

public class ImageProxy extends JPanel implements Runnable {


private int height, width;
private MediaTracker tracker;
private Image img;
private Thread imageCheck; // to monitor loading
// ----------------------------------

public ImageProxy(String filename, int w, int h) {


height = h;
width = w;
tracker = new MediaTracker(this);
img = Toolkit.getDefaultToolkit().getImage(filename);
tracker.addImage(img, 0); // watch for image loading
imageCheck = new Thread(this);

57 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
imageCheck.start(); // start 2nd thread monitor
// this begins actual image loading
try {
tracker.waitForID(0, 1);
} catch (InterruptedException e) {
}
}
// ------------------------------------
public void paint(Graphics g) {
if (tracker.checkID(0)) {
height = img.getHeight(null); // get height
width = img.getWidth(null); // and width
g.setColor(Color.lightGray); // erase box
g.fillRect(0, 0, width, height);
g.drawImage(img, 0, 0, this); // draw loaded image
} else {
// draw box outlining image if not loaded yet
g.setColor(Color.black);
g.drawRect(1, 1, width - 2, height - 2);
System.out.println("sss");
}
}
// ------------------------------------
public Dimension getPreferredSize() {
return new Dimension(width, height);
}

// public int getWidth() {return width;}


// public int getHeight(){return height;}
// ------------------------------------
public void run() {
/**
* this thread monitors image loading and repaints when done the 1000
* msec is artifically long to allow demo to display with delay
*/
try {
Thread.sleep(10000);
while (!tracker.checkID(0))
Thread.sleep(1000);
} catch (Exception e) {
}
repaint();
}
}

//Client
package example.structure.proxy;
import javax.swing.*;
import java.awt.*;
public class ProxyDisplay extends JFrame {
public ProxyDisplay() {
super("Display proxied image");
JPanel p = new JPanel();
getContentPane().add(p);
p.setLayout(new BorderLayout());
ImageProxy image = new ImageProxy("puppy.jpg", 321, 271);
p.add("Center", image);
p.add("North", new Label(" "));
p.add("West", new Label(" "));
58 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
setSize(370, 350);
setVisible(true);
}
// ------------------------------------
static public void main(String[] argv) {
new ProxyDisplay();
}
}
We create the instance of the ImageProxy just as we would have for an Image, and that we add it to the
enclosing JPanel as we would an actual image. The ImageProxy class sets up the image loading and creates
a MediaTracker object to follow the loading process within the constructor:

The waitForID method of the MediaTracker actually initiates loading. In this case, we put in a minimum
wait time of 1 msec so that we can minimize apparent program delays. The constructor also creates a
separate thread imageCheck that checks the loading status every few milliseconds, and starts that thread
running.

For the purposes of this illustration program, we slowed the polling time down to 1 second so you can see
the program draw the rectangle and then refresh the final image.

Finally, the Proxy is derived from the JPanel component, and therefore, naturally has a paint method. In
this method, we draw a rectangle if the image is not loaded. If the image has been loaded, we erase the
rectangle and draw the image instead.

The program’s two states are illustrated below.

59 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Behavioral Patterns
Behavioral patterns are those, which are concerned with interactions between the objects. The interactions
between the objects should be such that they are talking to each other and still are loosely coupled. The
loose coupling is the key to n-tier architectures. In this, the implementation and the client should be loosely
coupled in order to avoid hard-coding and dependencies.

GoF defined following structural patterns:

1. Chain of Responsibility Pattern


2. Command Pattern
3. Interpreter Pattern
4. Iterator Pattern
5. Mediator Pattern
6. Memento Pattern
7. Observer Pattern
8. State Pattern
9. Strategy Pattern
10. Template Method Pattern
11. Visitor Pattern

1. Chain of Responsibility Pattern


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.

The responsibility of handling the request data is given to any of the members (object) of the “chain”. If
the first link of the chain cannot handle the responsibility, it passes the request data to the next level in the
chain, i.e. to the next link. The process continues till some object in the chain handles the responsibility or
the request reaches to the last object in the chain. If even last object does not handle the responsibility then
request is ignored.

For readers, familiar with concepts of Java, this is similar to what happens in an Exception Hierarchy.
Another example of this is handling KeyPressed event. Suppose the event occurs when a component is
selected, which is part of a panel and panel is part of the Frame. The event is received successively by:

1. The Selected Component


2. The Panel containing the component, and
3. The Frame.

60 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Structure of Chain of Responsibility Pattern:

Participants
q Handler
o Defines an interface for handling the requests.
o Optionally implements the successor link.
q ConcreteHandler
o Handles requests it is responsible for.
o Can access its successor
o If the ConcreteHandler can handle the request, it does so; otherwise it forwards the request
to its successor.
q Client
o Initiates the request to a ConcreteHandler object on the chain
Example:
Let’s consider a simple system for displaying the results of typed in requests. These requests can be
· Image filenames
· General filenames
· Color Names
· Other commands

In the first three cases, we can display a concrete result of the request, and in the last case, we can only display the
request text itself.

61 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
The System responds to commands as follows:

We type in “Mandrill.jpg” and see a display of the image Mandrill.jpg.


We type in “FileList.java” and that filename is highlighted in the center list box.
We type in “blue” and that color is displayed in the lower center panel.

If we type in anything that is neither a filename nor a color, that text is displayed in the right-hand list box. This
sequence of steps is shown below:

The classes/interfaces to implement this simple chain of responsibility program are described below.

//Handler Interface: Chain


package example.behavioural.chain;
public interface Chain {
public abstract void addChain(Chain c);

public abstract void sendToChain(String mesg);

public Chain getChain();


}
The addChain method adds another class to the chain of classes. The getChain method returns the next object in the
chain to which the request is forwarded if not handled by the current object in the chain. These two methods allow us
to modify the chain dynamically and add additional objects in the middle of an existing chain. The sendToChain
method forwards a request to the next object in the chain if not handled by the current object.

//Client: Chainer
//It sets up the GUI and the chain of responsibility
package example.behavioural.chain;

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class Chainer extends JFrame {


// list of chain members
Sender sender; // gets commands
Imager imager; // displays images
FileList fileList; // highlights file names
ColorImage colorImage; // shows colors
RestList restList; // shows rest of list

// --------------------------------------
public Chainer() {
super("Chain demo");
JPanel jp = new JPanel();
jp.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(jp);
jp.setLayout(new GridLayout(1, 3));
JPanel left = new JPanel();
jp.add(left);
left.setLayout(new GridLayout(2, 1));

62 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// create send panel and image display panel
sender = new Sender();
imager = new Imager();
left.add(imager);
left.add(sender);
// create file list and color panels
JPanel mid = new JPanel();
jp.add(mid);
mid.setBorder(new EmptyBorder(5, 5, 5, 5));
mid.setLayout(new GridLayout(2, 1));
fileList = new FileList();

colorImage = new ColorImage();


mid.add(fileList);
mid.add(colorImage);

// put list for rest of commands in right panel


restList = new RestList();
jp.add(restList);
// set up the chain of responsibility
sender.addChain(imager);
imager.addChain(colorImage);
colorImage.addChain(fileList);
fileList.addChain(restList);
// set up visual shape
setSize(new Dimension(500, 300));
setVisible(true);
}

// -----------------------------------------
static public void main(String argv[]) {
new Chainer();
}
}

//Concrete Handler: Sender


// It is the first concrete handler but does not handle the request. It simply passes the request to the next
handler in the chain.
package example.behavioural.chain;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import javax.swing.border.TitledBorder;

public class Sender extends JPanel implements Chain, ActionListener {


private Chain nextChain;
private JTextField tx;
private JButton Send;

// ----------------------------------
public Sender() {
setLayout(new GridLayout(2, 1));
JPanel tp = new JPanel();
JPanel bp = new JPanel();
add(tp);
add(bp);

63 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
tx = new JTextField(10);
tp.add(tx);
Send = new JButton("Send");
bp.add(Send);
Send.addActionListener(this);
setBorder(new TitledBorder("Send commands"));
}

// ----------------------------------
public void actionPerformed(ActionEvent e) {
String file = tx.getText();
if ((file.length() > 0) && (nextChain != null))
nextChain.sendToChain(file);
}

// ----------------------------------
public void addChain(Chain c) {
nextChain = c;
}

// ----------------------------------
public void sendToChain(String mesg) {
} // this one does nothing

// ----------------------------------

public Chain getChain() {


return nextChain;
}
}

//Concrete Handler: Imager


package example.behavioural.chain;

import java.awt.*;
import java.io.File;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;

public class Imager extends JPanel implements Chain {


private Chain nextChain;
private Image img;
private boolean loaded;

public Imager() {
super();
loaded = false;
setBorder(new BevelBorder(BevelBorder.RAISED));
}

// ------------------------------------------
public void addChain(Chain c) {
nextChain = c; // next in chain of resp
}

// ------------------------------------------
public void sendToChain(String mesg) {
// if mesg is a JPEG file
// load it and display it.
64 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
if (mesg.endsWith(".jpg") && findImage(mesg))
loadImage(mesg);
else
// Otherwise, pass request along chain
nextChain.sendToChain(mesg);
}

// ------------------------------------------
public Chain getChain() {
return nextChain;
}

// ------------------------------------------
public void paint(Graphics g) {
if (loaded) {
g.drawImage(img, 0, 0, this);
}
}

// ------------------------------------------
private void loadImage(String file) {
loaded = false;
MediaTracker tracker = new MediaTracker(this);
img = Toolkit.getDefaultToolkit().getImage(file);
tracker.addImage(img, 0); // watch for image loading
// this begins actual image loading
try {
tracker.waitForID(0, 1);
} catch (InterruptedException e) {
}
loaded = true;
validate();
repaint();
}

// ------------------------------------------
private boolean findImage(String file) {
File dir = new File(System.getProperty("user.dir"));
boolean found = false;
String files[] = dir.list();
int i = 0;
while ((!found) && (i < files.length)) {
found = file.equals(files[i]);
if (!found)
i++;
}
return (found);
}
}

65 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Concrete Handler: ColorImage
package example.behavioural.chain;

import java.awt.Color;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

public class ColorImage extends JPanel implements Chain {


private Chain nextChain;

// -----------------------------------
public ColorImage() {
super();
setBorder(new LineBorder(Color.black));
}

// -----------------------------------
public void addChain(Chain c) {
nextChain = c;
}

// -----------------------------------
public void sendToChain(String mesg) {
Color c = getColor(mesg);
if (c != null) {
setBackground(c);
repaint();
} else {
if (nextChain != null) {
nextChain.sendToChain(mesg);
}
}
}

// -----------------------------------
private Color getColor(String mesg) {
String lmesg = mesg.toLowerCase();
Color c = null;
if (lmesg.equals("red"))
c = Color.red;
if (lmesg.equals("blue"))
c = Color.blue;
if (lmesg.equals("green"))
c = Color.green;
return c;
}

// -----------------------------------
public Chain getChain() {
return nextChain;
}
}

66 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Concrete Handler: FileList
// Selects the specified file if it is present in the list
package example.behavioural.chain;

import java.io.File;

public class FileList extends RestList {


String files[];
private Chain nextChain;

public FileList() {
super();
String tmp = "";
File dir = new File(System.getProperty("user.dir"));
files = dir.list();
for (int i = 0; i < files.length; i++) {
for (int j = i; j < files.length; j++) {
if (files[i].toLowerCase().compareTo(files[j].toLowerCase()) > 0) {
tmp = files[i];
files[i] = files[j];
files[j] = tmp;
}
}
}
for (int i = 0; i < files.length; i++)
add(files[i]);
}

// ---------------------------------------
public void sendToChain(String mesg) {
System.out.println("in filelist");
boolean found = false;
int i = 0;
while ((!found) && (i < files.length)) {
found = files[i].equals(mesg);
if (!found)
i++;
}
System.out.println("i =" + i);
if (found) {
this.select(i);
} else {
if (nextChain != null)
nextChain.sendToChain(mesg);
}
}

// ------------------------------------------
public void addChain(Chain c) {
nextChain = c; // next in chain of resp
}
}

67 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Concrete Handler: RestList
// Unhandled command is siply added to the rightmost list.

package example.behavioural.chain;

import java.awt.List;

public class RestList extends List implements Chain {


private Chain nextChain = null;

public RestList() {
super(10); // arg to JawtList
}

public void addChain(Chain c) {


nextChain = c;
}

public void sendToChain(String mesg) {


add(mesg); // this is the end of the chain
repaint();
if (nextChain != null)
nextChain.sendToChain(mesg);
}

public Chain getChain() {


return nextChain;
}
}

1.1.1 Consequences of the Chain of Responsibility

The main purpose for this pattern, like a number of others, is to reduce coupling between objects. An
object only needs to know how to forward the request to other objects.

This approach also gives you added flexibility in distributing responsibilities between objects. Any object
can satisfy some or all of the requests, and you can change both the chain and the responsibilities at run
time.

An advantage is that there may not be any object that can handle the request, however, the last object in the
chain may simply discard any requests it can’t handle.

Finally, since Java can not provide multiple inheritance, the basic Chain class needs to be an interface
rather than an abstract class, so that the individual objects can inherit from another useful hierarchy, as we
did here by deriving them all from JPanel. The disadvantage of this approach is that you often have to
implement the linking, sending and forwarding code in each module separately.

68 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
2. Command Pattern
This is another of the data-driven pattern. The client invokes a particular module using a command (which
is an object). 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.

This pattern is different from the Chain of Responsibility in a way that, in the earlier one, the request
passes through each of the object before finding an object that can take the responsibility. The command
pattern however finds the particular object according to the command and invokes only that one.

It’s like there is a server having a lot of services to be given, and on Demand (or on command), it caters to
that service for that particular client.

A classic example of this is a restaurant. A customer goes to restaurant and orders the food according to
his/her choice. The waiter/waitress takes the order (command, in this case) and hands it to the cook in the
kitchen. The cook can make several types of food and so, he/she prepares the ordered item and hands it
over to the waiter/waitress who in turn serves to the customer.

3.1 Uses for the Command Pattern

Command objects are useful for implementing:


Multi-level undo
If all user actions in a program are implemented as command objects, the program can keep a stack
of the most recently executed commands. When the user wants to undo a command, the program
simply pops the most recent command object and executes its undo() method.
1.1.1.1 Transactional behavior
Undo is perhaps even more essential when it's called rollback and happens automatically when an
operation fails partway through. Installers need this. So do databases. Command objects can also be
used to implement two-phase commit.
1.1.1.2 Thread pools
A typical, general-purpose thread pool class might have a public addTask() method that adds a
work item to an internal queue of tasks waiting to be done. It maintains a pool of threads that
execute commands from the queue. The items in the queue are command objects. Typically these
objects implement a common interface such as java.lang.Runnable that allows the thread pool to
execute the command even though the thread pool class itself was written without any knowledge
of the specific tasks for which it would be used.
1.1.1.3 Macro recording
If all user actions are represented by command objects, a program can record a sequence of actions
simply by keeping a list of the command objects as they are executed. It can then "play back" the
same actions by executing the same command objects again in sequence. If the program embeds a
scripting engine, each command object can implement a toScript() method, and user actions can
then be easily recorded as scripts.
1.1.1.4 Networking
It is possible to send whole command objects across the network to be executed on the other machines,
for example player actions in computer games.

69 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
3.2 Structure of Command Pattern

Participants
q Command
o Declares an interface for executing an operation.
q ConcreteCommand
o Defines a binding between a Receiver object and an action.
o Implements execute by invoking the corresponding operation(s) on Receiver.
q Client
o Creates a ConcreteCommand object and sets its receiver.
q Invoker
o Asks the command to carry out the request.
q Receiver
o knows how to perform the operations associated with carrying out a request. Any class may
server as receiver

70 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example 1:
//Command Interface
package example.behavioural.command.ex1;
interface Command {
public void execute();
}

//Client
package example.behavioural.command.ex1;

import java.awt.*;
import java.awt.event.*;

public class ExtrnCommand extends Frame implements ActionListener {


Menu mnuFile;
FileOpenCommand mnuOpen;
FileExitCommand mnuExit;
BtnRedCommand btnRed;

Panel p;
Frame fr;

// -----------------------------------------
public ExtrnCommand() {
super("Frame with external commands");
fr = this; // save frame object
MenuBar mbar = new MenuBar();
setMenuBar(mbar);
mnuFile = new Menu("File", true);
mbar.add(mnuFile);
mnuOpen = new FileOpenCommand("Open...", this);
mnuFile.add(mnuOpen);
mnuExit = new FileExitCommand("Exit");
mnuFile.add(mnuExit);
mnuOpen.addActionListener(this);
mnuExit.addActionListener(this);
p = new Panel();
add(p);
btnRed = new BtnRedCommand("Red", p);
p.add(btnRed);
btnRed.addActionListener(this);
setBounds(100, 100, 200, 100);
setVisible(true);
}

// -----------------------------------------
public void actionPerformed(ActionEvent e) {
Command obj = (Command) e.getSource();
obj.execute();
}

// -----------------------------------------
static public void main(String argv[]) {
new ExtrnCommand();
}
}

71 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//ConcreteCommand as well as Invoking Client
package example.behavioural.command.ex1;
import java.awt.*;

class BtnRedCommand extends Button implements Command {


Panel p;

public BtnRedCommand(String caption, Panel pnl) {


super(caption);
p = pnl;
}

public void execute() {


p.setBackground(Color.red); // Panel is receiver
}
}

//------------------------------------------
//ConcreteCommand as well as Invoking Client
package example.behavioural.command.ex1;
import java.awt.*;

class FileOpenCommand extends MenuItem implements Command {


Frame fr;

public FileOpenCommand(String caption, Frame frm) {


super(caption);
fr = frm;
}

public void execute() {


// FileDialog is receiver
FileDialog fDlg = new FileDialog(fr, "Open file");
fDlg.setVisible(true);
}
}

//ConcreteCommand as well as Invoking Client


package example.behavioural.command.ex1;
import java.awt.MenuItem;

class FileExitCommand extends MenuItem implements Command {


public FileExitCommand(String caption) {
super(caption);
}

public void execute() {


System.exit(0); // System class is receiver
}
}

72 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example 2: The above example is refined so as to ensure that the command objects are different from the
invoking clients. Rather than having the command is part of the menu or button, we make the menu and
button classes containers for a Command object that exists separately. We thus make UI elements that
implement a CommandHolder interface. This interface indicates that there is a method to put a command
object into the invoking object and a method to fetch that Command object and call its execute method.

//Command interface
package example.behavioural.command.ex2;
public interface Command {
public void execute();
}

//CommandHolder interface
package example.behavioural.command.ex2;
public interface CommandHolder {
public void setCommand(Command comd);

public Command getCommand();


}

// Invoker
import java.awt.*;
import javax.swing.*;
package example.behavioural.command.ex2;

import javax.swing.JFrame;
import javax.swing.JMenuItem;

public class CmdMenu extends JMenuItem implements CommandHolder {


protected Command menuCommand;
protected JFrame frame;

// -----------------------
public CmdMenu(String name, JFrame frm) {
super(name);
frame = frm;
}

// -----------------------
public void setCommand(Command comd) {
menuCommand = comd;
}

// -----------------------
public Command getCommand() {
return menuCommand;
}
}

73 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
// Invoker
package example.behavioural.command.ex2;

import java.awt.*;
import javax.swing.*;

public class CmdButton extends JButton implements CommandHolder {


private Command btnCommand;
private JFrame frame;

public CmdButton(String name, JFrame fr) {


super(name);
frame = fr;
}

public void setCommand(Command comd) {


btnCommand = comd;
}

public Command getCommand() {


return btnCommand;
}
}

//ConcreteCommand
package example.behavioural.command.ex2;

public class ExitCommand implements Command {


public void execute() {
System.exit(0);
}
}

//ConcreteCommand
package example.behavioural.command.ex2;

import java.awt.*;
import javax.swing.*;

public class FileCommand implements Command {


JFrame frame;

public FileCommand(JFrame fr) {


frame = fr;
}

// ------------------------------
public void execute() {
FileDialog fDlg = new FileDialog(frame, "Open file");
fDlg.setVisible(true);
}
}

74 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//ConcreteCommand
package example.behavioural.command.ex2;

import java.awt.*;
import javax.swing.*;

public class RedCommand implements Command {


private JFrame frame;
private JPanel pnl;

public RedCommand(JFrame fr, JPanel p) {


frame = fr;
pnl = p;
}

public void execute() {


pnl.setBackground(Color.red);
}
}

//Client
package example.behavioural.command.ex2;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

//In this version, we fully decouple the Commands from


//the menu and Button subclasses.
//the Command objects are external classes
//and we pass them copies of the Frame instance
//in their constructor
public class FullCommand extends JFrame implements ActionListener {
JMenu mnuFile;
CmdMenu mnuOpen, mnuExit;
CmdButton btnRed;
JPanel p, jp;
JFrame fr;
FileCommand flc;
ExitCommand extc;
RedCommand redc;

// -----------------------------------------
public FullCommand() {
super("Frame with external commands");
fr = this; // save frame object
JPanel jp = new JPanel();
getContentPane().add(jp);
JMenuBar mbar = new JMenuBar();
setJMenuBar(mbar);

mnuFile = new JMenu("File", true);


mbar.add(mnuFile);

mnuOpen = new CmdMenu("Open...", this);


mnuFile.add(mnuOpen);

mnuOpen.setCommand(new FileCommand(this));
75 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
mnuExit = new CmdMenu("Exit", this);
mnuExit.setCommand(new ExitCommand());

mnuFile.add(mnuExit);

mnuOpen.addActionListener(this);
mnuExit.addActionListener(this);

btnRed = new CmdButton("Red", this);


redc = new RedCommand(this, jp);
btnRed.setCommand(redc);

jp.add(btnRed);

btnRed.addActionListener(this);
setBounds(100, 100, 200, 100);
setVisible(true);
}

// -----------------------------------------
public void actionPerformed(ActionEvent e) {
CommandHolder obj = (CommandHolder) e.getSource();
obj.getCommand().execute();
}

// -----------------------------------------
static public void main(String argv[]) {
new FullCommand();
}
}

76 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
3. Iterator Pattern
]In object-oriented programming, the Iterator pattern is a design pattern in which iterators are used to
access the elements of an aggregate object sequentially without exposing its underlying representation. An
Iterator object encapsulates the internal structure of how the iteration occurs.

Iterator should be implemented as an interface. This allows the user to implement it anyway its easier for
him/her to return data.

Structure of Iterator Pattern

Participants
q Iterator
o Defines an interface for accessing and traversing elements.
q ConcreteIterator
o Implements the Iterator interface.
o Keeps track of the current position in the traversal of the aggregate.
q Aggregate
o Defines an interface for creating an Iterator object.
q ConcreteAggregate
o Implements the Iterator creation interface to return an instance of the proper ConcreteIterator.

Example:
//Iterator Interface
public interface Iterator {
void first();
void next();
boolean isDone();
Object currentItem();
}

77 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Aggregate Interface
import java.util.Vector;
package example.behavioural.iterator;

import java.util.Vector;

public abstract class Aggregate {


private Vector elements = new Vector(5);

public abstract Iterator createIterator();

public void append(Object anObj) {


elements.addElement(anObj);
}

public void remove(Object anObj) {


elements.removeElement(anObj);
}

public Object currentItem(int n) {


return elements.elementAt(n);
}

public int count() {


return elements.size();
}
}
//ConcreateIteratorA
package example.behavioural.iterator;
public class ConcreteIteratorA implements Iterator {
private int state;
private Aggregate obj;

public ConcreteIteratorA(Aggregate anObj) {


obj = anObj;
}
public void first() {
state = 0;
}

public void next() {


if (!isDone()) {
state++;
}
}
public boolean isDone() {
if (state > obj.count() - 1) {
return true;
}
return false;
}

public Object currentItem() {


return obj.currentItem(state);
}
}

78 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//ConcreteAggregateA
package example.behavioural.iterator;

public class ConcreteAggregateA extends Aggregate {


public ConcreteAggregateA() {
}

public Iterator createIterator() {


return new ConcreteIteratorA(this);
}
}

//ConcreateIteratorB
package example.behavioural.iterator;

public class ConcreteIteratorB implements Iterator {


private int state;
private Aggregate obj;

public ConcreteIteratorB(Aggregate anObj) {


obj = anObj;
}

public void first() {


state = obj.count() - 1;
}

public void next() {


if (!isDone()) {
state--;
}
}

public boolean isDone() {


if (state < 0) {
return true;
}
return false;
}

public Object currentItem() {


return obj.currentItem(state);
}
}
//ConcreteAggregateB
package example.behavioural.iterator;

public class ConcreteAggregateB extends Aggregate {


public ConcreteAggregateB() {
}

public Iterator createIterator() {


return new ConcreteIteratorB(this);
}
}

79 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Client
package example.behavioural.iterator;
public class IteratorExample {
public static void main(String[] args) {
Aggregate testA = new ConcreteAggregateA();
testA.append(new Integer(1));
testA.append(new Integer(2));
testA.append(new Integer(3));
testA.append(new Integer(4));
testA.append(new Integer(5));
Aggregate testB = new ConcreteAggregateB();
testB.append(new Integer(1));
testB.append(new Integer(2));
testB.append(new Integer(3));
testB.append(new Integer(4));
testB.append(new Integer(5));
System.out.println("Print Test A:");
Iterator iterA = testA.createIterator();
iterA.first();
while (!iterA.isDone()) {
Integer n = (Integer) iterA.currentItem();
iterA.next();
System.out.println("Value: " + n);
}
System.out.println("Print Test B:");
Iterator iterB = testB.createIterator();
iterB.first();
while (!iterB.isDone()) {
Integer n = (Integer) iterB.currentItem();
iterB.next();
System.out.println("Value: " + n);
}
}
}
Output:
Print Test A: Print Test B:
Value: 1 Value: 5
Value: 2 Value: 4
Value: 3 Value: 3
Value: 4 Value: 2
Value: 5 Value: 1

Internal Iterators: Internal iterators move through the entire collection, performing some
operation on each element directly, without any specific request from the user. Internal iterators
may perform operations like normalizing a collection of data values to lie between 0 and 1 or
converting all of the strings to a particular case.

Data modification. The most significant question iterators may raise is the question of iterating through
data while it is being changed. If your code is wide ranging and only occasionally moves to the next
element, it is possible that an element might be added or deleted from the underlying collection while you
are moving through it. It is also possible that another thread could change the collection. There are no
simple answers to this problem. You can make an enumeration thread-safe by declaring the loop to be
synchronized, but if you want to move through a loop using an Enumeration, and delete certain items, you
must be careful of the consequences. Deleting or adding an element might mean that a particular element is
skipped or accessed twice, depending on the storage mechanism you are using.

80 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
4. Mediator Pattern
Object oriented design encourages the distribution of behavior among objects. Such distribution can result
in an object structure with many connections between objects; in the worst case, every object ends up
knowing about every other.

Though partitioning a system into many objects generally enhances reusability, proliferating
interconnections tend to reduce it again. Lots of interconnection s make it less likely that an object can
work without the support of others- the system acts as though as though it were monolithic. Moreover, it
can be difficult to change the system’s behavior in any significant way, since behavior is distributed among
many objects.

You can avoid these problems by encapsulating collective behavior in a separate mediator object. A
mediator is responsible for controlling and coordinating the interactions of a group of objects. The
mediator serves as an intermediary that keeps objects in the group from referring to each other explicitly.
The objects only know the mediator, thereby reducing the number of interconnections.

A very common example can be airplanes interacting with the control tower and not among themselves.
The control tower knows exactly, where each of the airplanes is, and guides them whereas the airplanes
have their own responsibilities of landing and takeoff.

1.1.2 Structure of Mediator Pattern

Participants
q Mediator
o Defines an interface for communicating with Colleague objects.
q ConcreteMediator
o Implements cooperative behavior by coordinating Colleague objects.
o Knows and maintains its colleagues.
q Colleague classes
o Each Colleague class knows its Mediator object
o Each colleague communicates with its mediator whenever it would have otherwise
communicated with another colleague

81 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Mediator
package example.behavioural.mediator;
interface Mediator {
public void send(String id, String message);
}
//ConcreteMediator
class ConcreteMediator implements Mediator {
private Map<String, Colleague> colleagues = new HashMap<String, Colleague>();
public void registerColleague(Colleague c) {
c.registerMediator(this);
colleagues.put(c.getId(), c);
}
public void send(String id, String message) {
colleagues.get(id).receive(message);
}
}
// Colleague
package example.behavioural.mediator;
public class Colleague {
private Mediator mediator;
private String id;
public Colleague(String id) {
this.id = id;
}
public void registerMediator(Mediator mediator) {
this.mediator = mediator;
}
public String getId() {
return id;
}
public void send(String id, String message) {
System.out.println("Sending message from " + this.id + " to " + id
+ ": " + message);
mediator.send(id, message);
// Dispatch the actual communication to the mediator!!!
}
public void receive(String message) {
System.out.println("Received message by " + id + ": " + message);
}
}
//Client
package example.behavioural.mediator;
class MediatorExample {
public static void main(String[] args) {
Colleague rene = new Colleague("rene");
Colleague toni = new Colleague("toni");
Colleague kim = new Colleague("kim");
ConcreteMediator m = new ConcreteMediator();
m.registerColleague(rene);
m.registerColleague(toni);
m.registerColleague(kim);
kim.send("toni", "Hello world.");
rene.send("kim", "Greetings!");
}
}

82 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
5. Memento Pattern
The memento pattern is a software design pattern that provides the ability to restore an object to its
previous state (undo by rollback). The objective of this pattern is to capture and externalize an object’s
internal state without violating encapsulation so that the object can be restores to this state later. This is
required when implementing checkpoints and undo mechanisms that let users back out of tentative
operations or recover from errors.

The memento pattern is used by two objects: the originator and a caretaker. The originator is some object
that has an internal state. The caretaker is going to do something to the originator, but wants to be able to
undo the change. The caretaker first asks the originator for a memento object. Then it does whatever
operation (or sequence of operations) it was going to do. To rollback to the state before the operations, it
returns the memento object to the originator. The memento object itself is an opaque object (one which the
caretaker can not, or should not, change). When using this pattern, care should be taken if the originator
may change other objects or resources - the memento pattern operates on a single object.

Structure of Memento Pattern

Participants
q Memento
o Stores internal state of the Originator object. The memento may store as much or as little of
the originator's internal state as necessary at its originator's discretion.
o Protects against access by objects other than the originator. Mementos have effectively two
interfaces. Caretaker sees a narrow interface to the Memento -- it can only pass the
memento to the other objects. Originator, in contrast, sees a wide interface, one that lets it
access all the data necessary to restore itself to its previous state. Ideally, only the originator
that produces the memento would be permitted to access the memento's internal state.
q Originator
o Creates a memento containing a snapshot of its current internal state.
o Uses the memento to restore its internal state.
q Caretaker
o Is responsible for the memento's safekeeping.
o Never operates on or examines the contents of a memento.

83 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example:
//Memento
package example.behavioural.memento;
class Memento {
private String state;

public Memento(String stateToSave) {


state = stateToSave;
}

public String getSavedState() {


return state;
}
}

//Originator
package example.behavioural.memento;

class Originator {
private String state;

public void set(String state) {


System.out.println("Originator: Setting state to " + state);
this.state = state;
}

public Memento saveToMemento() {


System.out.println("Originator: Saving to Memento.");
return new Memento(state);
}

public void restoreFromMemento(Memento m) {


state = m.getSavedState();
System.out.println("Originator: State after restoring from Memento: "
+ state);
}
}
//Caretaker
package example.behavioural.memento;

import java.util.ArrayList;

class Caretaker {
private ArrayList<Memento> savedStates = new ArrayList<Memento>();

public void addMemento(Memento m) {


savedStates.add(m);
}

public Memento getMemento(int index) {


return savedStates.get(index);
}
}

84 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
//Client
package example.behavioural.memento;

public class MementoExample {


public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Originator originator = new Originator();
originator.set("State1");
originator.set("State2");
caretaker.addMemento(originator.saveToMemento());
originator.set("State3");
caretaker.addMemento(originator.saveToMemento());
originator.set("State4");
originator.restoreFromMemento(caretaker.getMemento(1));
}
}
Output:
Originator: Setting state to State1
Originator: Setting state to State2
Originator: Saving to Memento.
Originator: Setting state to State3
Originator: Saving to Memento.
Originator: Setting state to State4
Originator: State after restoring from Memento: State3

85 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
6. Observer Pattern
The observer pattern (sometimes known as publish/subscribe) is a design pattern used to observe the
state of an object in a program. The pattern assumes one-to-many dependency between objects so that
when one object changes stste, all its dependent are notified and updates automatically.

The Observer pattern assumes that the object containing the data is separate from the objects that display
the data, and that these display objects observe changes in that data. When we implement the Observer
pattern, we usually refer to the data as the Subject and each of the displays as Observers. Each of these
observers registers its interest in the data by calling a public method in the Subject.

This pattern is commonly used in event handling system. In some programming languages, the issues
addressed by this pattern are handled in the native event handling syntax. The essence of this pattern is that
one or more objects (called observers or listeners or event handlers) are registered (or register
themselves) to observe an event which may be raised by the observed object (the subject). The object
(subject) which may raise an event generally maintains a collection of the observers.

When the event is raised each observer receives a callback i.e. the notify method of the object (observer)
passed as an argument to the listener registration method is invoked. The notify method may also be
passed some parameters (generally information about the event that is occurring) which can be used by the
observer.

Each concrete observer implements the notify method and as a consequence defines its own behavior when
the notification occurs.

The subject normally has a register method for adding a new listener and an unregister method for
removing an observer from the list of objects to be notified when the event is raised.

The typical usages of the observer pattern:

· Listening for an external event (such as a user action).


· Listening for changes of the value of a property of an object.
· In a mailing list, where everytime an event happens (a new product, a gathering, etc.) a message is
sent to the people subscribed to the list.

The observer pattern is also very often associated with the Model-view-controller (MVC) paradigm. In
MVC, the observer pattern is used to create a loose coupling between the model and the view. Typically, a
modification in the model triggers the notification of model observers which are actually the views.

This is used extensively in Swing. The JList, JTable, and JTree objects all operate as observers of a data
model. In fact, all of the visual components derived from JComponent can have this same division of labor
between the data and the visual representation.

86 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Structure of Observer Pattern

Participants
q Subject
o Knows its observers. Any number of Observer objects may observe a subject.
o Provides an interface for attaching and detaching Observer objects.
q ConcreteSubject
o Stores state of interest to ConcreteObserver objects.
o Sends a notification to its observers when its state changes.
q Observer
o Defines an updating interface for objects that should be notified of changes in a subject.
q ConcreteObserver
o Maintains a reference to a ConcreteSubject object.
o Stores state that should stay consistent with the subject's.
o Implements the Observer updating interface to keep its state consistent with the subject's.

Example: Watching Colors Change:


The following program shows a display frame containing 3 radio buttons named Red, Blue and Green as shown
below

This main window is the Subject or data repository object.


Clicking a radio button on the main window generates data, which is a string containing name of the
selected color. Subject notifies the two observers as soon as a radio button is clicked.Clicking event. The

87 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
two observers are: a colored panel and a list box. The color of the panel changes to the selected color and
the selected color gets added in the list box as shown below:

//Subject Interface
package example.behavioural.observer;

public interface Subject {


public void registerInterest(Observer obs);
}

//Observer Interface
package example.behavioural.observer;

public interface Observer {


/** notify observers a change has taken place */
public void sendNotify(String s);
}
//AbstractListModel
package example.behavioural.observer;

import javax.swing.*;
import java.util.*;
public class JListData extends AbstractListModel {
private Vector data;

public JListData() {
data = new Vector();
}

public int getSize() {


return data.size();
}

public Object getElementAt(int index) {


return data.elementAt(index);
}

public void addElement(String s) {


data.addElement(s);
fireIntervalAdded(this, data.size() - 1, data.size());
}
}
//ConcreteObserver1
package example.behavioural.observer;

import javax.swing.*;
import java.awt.*;

88 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
public class ListFrame extends JFrame implements Observer {
private JList list;
private JPanel p;
private JScrollPane lsp;
private JListData listData;
public ListFrame(Subject s) {
super("Color List");
// put panel into the frmae
p = new JPanel(true);
getContentPane().add("Center", p);
p.setLayout(new BorderLayout());
// Tell the Subject we are interested
s.registerInterest(this);
// Create the list
listData = new JListData(); // the list model
list = new JList(listData); // the visual list
lsp = new JScrollPane(); // the scroller
lsp.getViewport().add(list);
p.add("Center", lsp);
lsp.setPreferredSize(new Dimension(100, 100));
setBounds(250, 100, 100, 100);
setVisible(true);
}
// --------------------------------
public void sendNotify(String s) {
listData.addElement(s);
}
}
//ConcreteObserver2
package example.behavioural.observer;

import javax.swing.*;
import java.awt.*;

public class ColorFrame extends JFrame implements Observer {


private Color color;
private String color_name = "black";
private Font font;
private JPanel p = new JPanel(true);

public ColorFrame(Subject s) {
super("Colors");
getContentPane().add("Center", p);
s.registerInterest(this);
setBounds(100, 100, 100, 100);
font = new Font("Sans Serif", Font.BOLD, 14);
setVisible(true);
}

public void sendNotify(String s) {


color_name = s;
if (s.equalsIgnoreCase("RED"))
color = Color.red;
if (s.equalsIgnoreCase("BLUE"))
color = Color.blue;
if (s.equalsIgnoreCase("GREEN"))
color = Color.green;
// p.repaint();
setBackground(color);

89 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
}
public void paint(Graphics g) {
g.setFont(font);
g.drawString(color_name, 20, 50);
}
}
//ConcreteSubject
package example.behavioural.observer;

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;

public class Watch2Windows extends JFrame implements ActionListener,


ItemListener, Subject {
private JButton Close;
private JRadioButton red, green, blue;
private Vector observers;
private ColorFrame cframe;
private ListFrame lframe;

// ------------------------------------------
public Watch2Windows() {
super("Change 2 other frames");
observers = new Vector(); // list of observing frames
JPanel p = new JPanel(true); // add panel to content pane
p.setLayout(new BorderLayout());
getContentPane().add("Center", p);
Box box = new Box(BoxLayout.Y_AXIS); // vertical box layout
p.add("Center", box);
box.add(red = new JRadioButton("Red")); // and 3 radio buttons
box.add(green = new JRadioButton("Green"));
box.add(blue = new JRadioButton("Blue"));
blue.addItemListener(this); // listen for clicks
red.addItemListener(this); // on radion buttons
green.addItemListener(this);
// make all part of same button group
ButtonGroup bgr = new ButtonGroup();
bgr.add(red);
bgr.add(green);
bgr.add(blue);
// put a Close button at the bottom of the frame
JPanel p1 = new JPanel();
p.add("South", p1);
p1.add(Close = new JButton("Close"));
Close.addActionListener(this); // listen for clicks on it
setBounds(200, 200, 200, 200);
pack();
// ---------create observers---------
cframe = new ColorFrame(this);
lframe = new ListFrame(this);
setVisible(true);
}

// -----------------------------------------
public void itemStateChanged(ItemEvent e) {
// responds to radio button clicks
// if the button is selected

90 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
if (e.getStateChange() == ItemEvent.SELECTED)
notifyObservers((JRadioButton) e.getSource());
}

// -----------------------------------------
private void notifyObservers(JRadioButton rad) {
// sends text of selected button to all observers
String color = rad.getText();
for (int i = 0; i < observers.size(); i++) {
((Observer) (observers.elementAt(i))).sendNotify(color);
}
}

// -----------------------------------------
public void registerInterest(Observer obs) {
// adds observer to list
observers.addElement(obs);
}

// -----------------------------------------
public void actionPerformed(ActionEvent e) {
// responds to close button
Object obj = e.getSource();
if (obj == Close)
System.exit(0);
}

// -----------------------------------------
static public void main(String[] argv) {
new Watch2Windows();
}
}

91 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
7. State Pattern
The state pattern is also known as the objects for states pattern. This pattern is used to represent the
states of an object. This allows an object to alter its behavior when its internal state changes. The object
will appear to change its class. This is a clean way for an object to partially change its type at runtime.

Known Usage

Most popular interactive drawing programs provide “tools” for performing operations by direct
manipulation. For example, a line drawing tool lets a user click and drag to create a new line. A selection
tool lets the user select shapes. We can use the state pattern to change the editor’s behavior depending on
the current tool.

We can define an abstract Tool class from which to define subclasses that implement tool specific
behavior. The drawing editor maintains a current Tool object and delegates requests to it. It replaces this
object when the user chooses a new tool, causing the behavior of drawing tool to change accordingly.

1.1.3 Structure of State Pattern

Participants
q Context
o Defines the interface of interest to clients.
o Maintains an instance of a ConcreteState subclass that defines the current state.
q State
o Defines an interface for encapsulating the behavior associated with a particular state of the
Context.
q Concrete State
o Each subclass implements a behavior associated with a state of the Context.

92 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example:
//State
package example.behavioural.state;

abstract class Actor {


public abstract void act();
}

//ConcreteState1
package example.behavioural.state;

class HappyActor extends Actor {


public void act() {
System.out.println("HappyActor");
}
}
//ConcreteState2
class SadActor extends Actor {
public void act() {
System.out.println("SadActor");
}
}
//Context
package example.behavioural.state;

class Stage {
private Actor actor = new HappyActor();
public void change() {
actor = new SadActor();
}
public void performPlay() {
actor.act();
}
}
//Client
package example.behavioural.state;

public class Transmogrify {


public static void main(String[] args) {
Stage stage = new Stage();
stage.performPlay();
stage.change();
stage.performPlay();
}
}

93 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
8. Strategy Pattern

The Strategy Pattern (also known as Policy Pattern) is a particular software design pattern, whereby
algorithms can be selected on-the-fly at runtime.

In some programming languages, such as those without polymorphism, the issues addressed by this pattern
are handled through forms of reflection, such as the native function pointer or function delegate syntax.

The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used
in an application. The strategy pattern is intended to provide a means to define a family of algorithms,
encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms
vary independently from clients that use them.

The Strategy pattern is much like the State pattern in outline, but a little different in intent. The Strategy
pattern consists of a number of related algorithms encapsulated in a driver class called the Context. Your
client program can select one of these differing algorithms or in some cases the Context might select the
best one for you. The intent, like the State pattern, is to switch easily between algorithms without any
monolithic conditional statements. The difference between State and Strategy is that the user generally
chooses which of several strategies to apply and that only one strategy at a time is likely to be instantiated
and active within the Context class. By contrast, as we have seen, it is likely that all of the different States
will be active at once and switching may occur frequently between them. In addition, Strategy ncapsulates
several algorithms that do more or less the same thing, while State encapsulates related classes that each do
something somewhat different. Finally, the concept of transition between different states is completely
missing in the Strategy pattern.

Structure of Strategy Pattern

Participants
q Strategy (SortStrategy)
o Declares an interface common to all supported algorithms. Context uses this interface to call
the algorithm defined by a ConcreteStrategy.
q ConcreteStrategy (QuickSort, ShellSort, MergeSort)
o Implements the algorithm using the Strategy interface
q Context (SortedList)
o Is configured with a ConcreteStrategy object.
o Maintains a reference to a Strategy object.
o May define an interface that lets Strategy access its data.

94 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
package example.behavioural.strategy;

interface TaxStrategy {
public double extortCash(double income);
}
class CompanyTaxStrategy implements TaxStrategy {
private static final double RATE = 0.30;
public double extortCash(double income) {
return income * RATE ;
}
}
class EmployeeTaxStrategy implements TaxStrategy {
private static final double RATE = 0.45;
public double extortCash(double income) {
return income * RATE;
}
}
class TrustTaxStrategy implements TaxStrategy {
private static final double RATE = 0.40;
public double extortCash(double income) {
return income * RATE;
}
}
class TaxPayer {
public static final TaxStrategy EMPLOYEE = new EmployeeTaxStrategy();
public static final TaxStrategy COMPANY = new CompanyTaxStrategy();
public static final TaxStrategy TRUST = new TrustTaxStrategy();
private final TaxStrategy strategy;
private final double income;
public TaxPayer(TaxStrategy strategy, double income) {
this.strategy = strategy; this.income = income;
}
public double getIncome() {
return income;
}
public double extortCash() {
return strategy.extortCash(income);
}
}
public class ReceiverOfRevenue {
public static void main(String[] args) {
TaxPayer heinz = new TaxPayer(TaxPayer.EMPLOYEE, 50000);
TaxPayer maxsol = new TaxPayer(TaxPayer.COMPANY, 100000);
TaxPayer family = new TaxPayer(TaxPayer.TRUST, 30000);
System.out.println(heinz.extortCash());
System.out.println(maxsol.extortCash());
System.out.println(family.extortCash());
}
}

95 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
9. Template Method Pattern
In software engineering, the template method pattern is a design pattern. It is a so-called Behavioral
pattern, and is unrelated to C++ templates.

A template method defines the skeleton of an algorithm. The algorithm itself is made abstract, and the
subclasses of the method override the abstract methods to provide concrete behaviour.

First a class is created that provides the basic steps of an algorithm. These steps are implemented using
abstract methods. Later on, subclasses change the abstract methods to implement real actions. Thus the
general algorithm is saved in one place but the concrete steps may be changed by the subclasses.

The template method is used to:


· let subclasses implement behaviour that can vary
· avoid duplication in the code: you look for the general code in the algorithm, and implement the
variants in the subclasses

Structure of Template Method Pattern

Participants
q AbstractClass
o Defines abstract primitive operations that concrete subclasses define to implement steps of
an algorithm.
o Implements a template method defining the skeleton of an algorithm. The template method
calls primitive operations as well as operations defined in AbstractClass or those of other
objects.
q ConcreteClass
o Implements the primitive operations to carry out subclass-specific steps of the algorithm

96 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example:
package example.behavioural.template;
import java.util.ArrayList;
import java.util.Iterator;
public class RunTemplateMethodPattern {
public static void main(String [] arguments){
System.out.println("Example for the Template Method pattern");
System.out.println("This code demonstrates how the template method can");
System.out.println(" be used to define a variable implementation for a");
System.out.println(" common operation. In this case, the ProjectItem");
System.out.println(" abstract class defines the method getCostEstimate,");
System.out.println(" which is a combination of the cost for time and");
System.out.println(" materials. The two concrete subclasses used here,");
System.out.println(" Task and Deliverable, have different methods of");
System.out.println(" providing a cost estimate.");
System.out.println("Creating a demo Task and Deliverable");
System.out.println();
Task primaryTask = new Task("Put a JVM on the moon", "Lunar mission as part of
the JavaSpace program ;)", 240.0, 100.0);
primaryTask.addProjectItem(new Task("Establish ground control", "", 1000.0,
10.0));
primaryTask.addProjectItem(new Task("Train the Javanaughts", "", 80.0,
30.0));
Deliverable deliverableOne = new Deliverable("Lunar landing module", "Ask the
local garage if they can make a few minor modifications to one of their cars", 2800,
40.0, 35.0);
System.out.println("Calculating the cost estimates using the Template Method,
getCostEstimate.");
System.out.println("Total cost estimate for: " + primaryTask);
System.out.println("\t" + primaryTask.getCostEstimate());
System.out.println();
System.out.println("Total cost estimate for: " + deliverableOne);
System.out.println("\t" + deliverableOne.getCostEstimate());
}
}
//AbstractClass containing Template Method
package example.behavioural.template;
abstract class ProjectItem {
private String name;
private String description;
private double rate;

public ProjectItem() {
}

public ProjectItem(String newName, String newDescription, double newRate) {


name = newName;
description = newDescription;
rate = newRate;
}

public void setName(String newName) {


name = newName;
}

public void setDescription(String newDescription) {


description = newDescription;
}

97 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
public void setRate(double newRate) {
rate = newRate;
}

public String getName() {


return name;
}

public String getDescription() {


return description;
}

public final double getCostEstimate() {


return getTimeRequired() * getRate() + getMaterialsCost();
}

public double getRate() {


return rate;
}

public String toString() {


return getName();
}

public abstract double getTimeRequired();

public abstract double getMaterialsCost();


}

//ConcreteClass1 providing implementation of abstract methods invoked in Template method


package example.behavioural.template;

import java.util.ArrayList;
import java.util.Iterator;

class Task extends ProjectItem {


private ArrayList projectItems = new ArrayList();
private double taskTimeRequired;

public Task() {
}

public Task(String newName, String newDescription,


double newTaskTimeRequired, double newRate) {
super(newName, newDescription, newRate);
taskTimeRequired = newTaskTimeRequired;
}

public void setTaskTimeRequired(double newTaskTimeRequired) {


taskTimeRequired = newTaskTimeRequired;
}

public void addProjectItem(ProjectItem element) {


if (!projectItems.contains(element)) {
projectItems.add(element);
}
}
public void removeProjectItem(ProjectItem element) {
projectItems.remove(element);

98 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
}
public double getTaskTimeRequired() {
return taskTimeRequired;
}
public Iterator getProjectItemIterator() {
return projectItems.iterator();
}
public double getMaterialsCost() {
double totalCost = 0;
Iterator items = getProjectItemIterator();
while (items.hasNext()) {
totalCost += ((ProjectItem) items.next()).getMaterialsCost();
}
return totalCost;
}

public double getTimeRequired() {


double totalTime = taskTimeRequired;
Iterator items = getProjectItemIterator();
while (items.hasNext()) {
totalTime += ((ProjectItem) items.next()).getTimeRequired();
}
return totalTime;
}
}
//ConcreteClass2 providing implementation of abstract methods invoked in Template method
package example.behavioural.template;
class Deliverable extends ProjectItem {
private double materialsCost;
private double productionTime;

public Deliverable() {
}
public Deliverable(String newName, String newDescription,
double newMaterialsCost, double newProductionTime, double newRate) {
super(newName, newDescription, newRate);
materialsCost = newMaterialsCost;
productionTime = newProductionTime;
}
public void setMaterialsCost(double newCost) {
materialsCost = newCost;
}
public void setProductionTime(double newTime) {
productionTime = newTime;
}
public double getMaterialsCost() {
return materialsCost;
}
public double getTimeRequired() {
return productionTime;
}
}

99 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
10. Structure of Visitor Pattern
In object-oriented programming and software engineering, the visitor design pattern is a way of separating
an algorithm from an object structure. A practical result of this separation is the ability to add new
operations to existing object structures without modifying those structures.

The idea is to use a structure of element classes, each of which has an accept method that takes a visitor
object as an argument. Visitor is an interface that has a visit() method for each element class. The accept()
method of an element class calls back the visit() method for its class. Separate concrete visitor classes can
then be written that perform some particular operations.

One of these visit() methods of a concrete visitor can be thought of as methods not of a single class, but
rather methods of a pair of classes: the concrete visitor and the particular element class. Thus the visitor
pattern simulates double dispatch in a conventional single-dispatch object-oriented language such as Java,
Smalltalk, and C++.

The visitor pattern also specifies how iteration occurs over the object structure. In the simplest version,
where each algorithm needs to iterate in the same way, the accept() method of a container element, in
addition to calling back the visit() method of the visitor, also passes the visitor object to the accept()
method of all its constituent child elements.

Because the Visitor object has one principal function (manifested in a plurality of specialized methods) and
that function is called visit(), the Visitor can be readily identified as a potential function object or functor.
Likewise, the accept() function can be identified as a function applicator, a mapper, which knows how to
traverse a particular type of object and apply a function to its elements.

100 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Structure of Visitor Pattern

Participants
q Visitor
o Declares a Visit operation for each class of ConcreteElement in the object structure. The
operation's name and signature identifies the class that sends the Visit request to the visitor.
That lets the visitor determine the concrete class of the element being visited. Then the
visitor can access the elements directly through its particular interface.
q ConcreteVisitor (IncomeVisitor, VacationVisitor)
o Implements each operation declared by Visitor. Each operation implements a fragment of
the algorithm defined for the corresponding class or object in the structure. ConcreteVisitor
provides the context for the algorithm and stores its local state. This state often accumulates
results during the traversal of the structure.
q Element
o Defines an Accept operation that takes a visitor as an argument.
q ConcreteElement
o Implements an Accept operation that takes a visitor as an argument.
q ObjectStructure
o Can enumerate its elements.
o May provide a high-level interface to allow the visitor to visit its elements.
o May either be a Composite (pattern) or a collection such as a list or a set.

101 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
Example:
package example.behavioural.visitor;

//Visitor Interface
interface Visitor {
void visit(Wheel wheel);

void visit(Engine engine);

void visit(Body body);

void visit(Car car);


}

// Element Interface
interface Visitable {
public void accept(Visitor visitor);
}

// ConcreteElementA
class Wheel implements Visitable {
private String name;

Wheel(String name) {
this.name = name;
}

String getName() {
return this.name;
}

public void accept(Visitor visitor) {


visitor.visit(this);
}
}

// ConcreteElementB
class Engine implements Visitable {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

// ConcreteElementC
class Body implements Visitable {
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

// ObjectStructure
class Car implements Visitable {
private Engine engine = new Engine();
private Body body = new Body();
private Wheel[] wheels = { new Wheel("front left"),
new Wheel("front right"), new Wheel("back left"),
new Wheel("back right") };

public void accept(Visitor visitor) {

102 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
visitor.visit(this);
engine.accept(visitor);
body.accept(visitor);
for (int i = 0; i < wheels.length; ++i)
wheels[i].accept(visitor);
}
}

// ConcreteVisitor1
class PrintVisitor implements Visitor {
public void visit(Wheel wheel) {
System.out.println("Visiting " + wheel.getName() + " wheel");
}

public void visit(Engine engine) {


System.out.println("Visiting engine");
}

public void visit(Body body) {


System.out.println("Visiting body");
}

public void visit(Car car) {


System.out.println("Visiting car");
}
}

// ConcreteVisitor2
class WashingVisitor implements Visitor {
public void visit(Wheel wheel) {
System.out.println("Washing " + wheel.getName() + " wheel");
}

public void visit(Engine engine) {


System.out.println("Washing engine");
}

public void visit(Body body) {


System.out.println("Washing body");
}

public void visit(Car car) {


System.out.println("Washing car");
}
}

// Client
public class VisitorDemo {
static public void main(String[] args) {
Car car = new Car();
Visitor printVisitor = new PrintVisitor();
car.accept(printVisitor);
Visitor washVisitor = new WashingVisitor();
car.accept(washVisitor);
}
}

103 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
11. Interpreter Pattern
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.

Uses for the Interpreter Pattern


· Specialized database query languages such as SQL.
· Specialized computer languages which are often used to describe communication protocols.
· Most general-purpose computer languages actually incorporate several specialized languages:
o one to define data,
o one to define operations on the data,
o one to define when to perform the operations,
o and at least one to define how to translate the computer program to machine language.
Structure of Interpreter Pattern

Participants
q AbstractExpression
o Declares an abstract Interpret operation that is common to all nodes in the abstract syntax
tree.
q TerminalExpression
o Implements an Interpret operation associated with terminal symbols in the grammar.
o An instance is required for every terminal symbol in a sentence.
q NonterminalExpression
o One such class is required for every rule R ::= R1R2...Rn in the grammar.
o Maintains instance variables of type AbstractExpression for each of the symbols R1 through
Rn.
o Implements an Interpret operation for nonterminal symbols in the grammar. Interpret
typically calls itself recursively on the variables representing R1 through Rn.
q Context
o Contains information that is global to the interpreter.

104 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
q Client
o Builds (or is given) an abstract syntax tree representing a particular sentence in the language
that the grammar defines. The abstract syntax tree is assembled from instances of the
NonterminalExpression and TerminalExpression classes.
o Invokes the Interpret operation

Example 1:
package example.behavioural.interpreter;

import java.util.*;

interface Expression {
public void interpret(Stack<Integer> s);
}

class TerminalExpression_Number implements Expression {


private int number;

public TerminalExpression_Number(int number) {


this.number = number;
}

public void interpret(Stack<Integer> s) {


s.push(number);
}
}

class TerminalExpression_Plus implements Expression {


public void interpret(Stack<Integer> s) {
s.push(s.pop() + s.pop());
}
}

class TerminalExpression_Minus implements Expression {


public void interpret(Stack<Integer> s) {
int tmp = s.pop();
s.push(s.pop() - tmp);
}
}

class Parser {
private ArrayList<Expression> parseTree = new ArrayList<Expression>(); // only

// one NonTerminal Expression here

public Parser(String s) {
for (String token : s.split(" ")) {
if (token.equals("+"))
parseTree.add(new TerminalExpression_Plus());
else if (token.equals("-"))
parseTree.add(new TerminalExpression_Minus());
// ...
else
parseTree.add(new TerminalExpression_Number(Integer
.valueOf(token)));
}
}

105 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
public int evaluate() {
Stack<Integer> context = new Stack<Integer>();
for (Expression e : parseTree)
e.interpret(context);
return context.pop();
}
}

public class InterpreterExample {


public static void main(String[] args) {
System.out.println("'44 2 1 - +' equals "
+ new Parser("44 2 1 - +").evaluate());
}
}
}
Example 2 :
package example.behavioural.interpreter.ex2;

import java.util.HashMap;
import java.util.Stack;

public class Calculator {


private String expression;
private HashMap operators;
private Context ctx;

public static void main(String[] args) {


Calculator calc = new Calculator();
// instantiate the context
Context ctx = new Context();
// set the expression to evaluate
calc.setExpression("(a+b)*(c-d)");
// configure the calculator with the
// Context
calc.setContext(ctx);
// Display the result
System.out.println(" Variable Values: " + "a=" + ctx.getValue("a")
+ ", b=" + ctx.getValue("b") + ", c=" + ctx.getValue("c")
+ ", d=" + ctx.getValue("d"));
System.out.println(" Expression = (a+b)*(c-d)");
System.out.println(" Result = " + calc.evaluate());
}

public Calculator() {
operators = new HashMap();
operators.put("+", "1");
operators.put("-", "1");
operators.put("/", "2");
operators.put("*", "2");
operators.put("(", "0");
}

public void setContext(Context c) {


ctx = c;
}

public void setExpression(String expr) {


expression = expr;
}
106 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
public int evaluate() {
// infix to Postfix
String pfExpr = infixToPostFix(expression);
// build the Binary Tree
Expression rootNode = buildTree(pfExpr);
// Evaluate the tree
return rootNode.evaluate(ctx);
}

private NonTerminalExpression getNonTerminalExpression(String operation,


Expression l, Expression r) {
if (operation.trim().equals("+")) {
return new AddExpression(l, r);
}
if (operation.trim().equals("-")) {
return new SubtractExpression(l, r);
}
if (operation.trim().equals("*")) {
return new MultiplyExpression(l, r);
}
return null;
}

private Expression buildTree(String expr) {


Stack s = new Stack();
for (int i = 0; i < expr.length(); i++) {
String currChar = expr.substring(i, i + 1);
if (isOperator(currChar) == false) {
Expression e = new TerminalExpression(currChar);
s.push(e);
} else {
Expression r = (Expression) s.pop();
Expression l = (Expression) s.pop();
Expression n = getNonTerminalExpression(currChar, l, r);
s.push(n);
}
}// for
return (Expression) s.pop();
}

private String infixToPostFix(String str) {


Stack s = new Stack();
String pfExpr = "";
String tempStr = "";
String expr = str.trim();
for (int i = 0; i < str.length(); i++) {
String currChar = str.substring(i, i + 1);
if ((isOperator(currChar) == false) && (!currChar.equals("("))
&& (!currChar.equals(")"))) {
pfExpr = pfExpr + currChar;
}
if (currChar.equals("(")) {
s.push(currChar);
}
// for ')' pop all stack contents until '('
if (currChar.equals(")")) {
tempStr = (String) s.pop();
while (!tempStr.equals("(")) {

107 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
pfExpr = pfExpr + tempStr;
tempStr = (String) s.pop();
}
tempStr = "";
}
// if the current character is an
// operator
if (isOperator(currChar)) {
if (s.isEmpty() == false) {
tempStr = (String) s.pop();
String strVal1 = (String) operators.get(tempStr);
int val1 = new Integer(strVal1).intValue();
String strVal2 = (String) operators.get(currChar);
int val2 = new Integer(strVal2).intValue();
while ((val1 >= val2)) {
pfExpr = pfExpr + tempStr;
val1 = -100;
if (s.isEmpty() == false) {
tempStr = (String) s.pop();
strVal1 = (String) operators.get(tempStr);
val1 = new Integer(strVal1).intValue();
}
}
if ((val1 < val2) && (val1 != -100))
s.push(tempStr);
}
s.push(currChar);
}// if
}// for
while (s.isEmpty() == false) {
tempStr = (String) s.pop();
pfExpr = pfExpr + tempStr;
}
return pfExpr;
}

private boolean isOperator(String str) {


if ((str.equals("+")) || (str.equals("-")) || (str.equals("*"))
|| (str.equals("/")))
return true;
return false;
}
} // End of class

interface Expression {
public int evaluate(Context c);
}

class Context {
private HashMap varList = new HashMap();

public void assign(String var, int value) {


varList.put(var, new Integer(value));
}

public int getValue(String var) {


Integer objInt = (Integer) varList.get(var);
return objInt.intValue();
}

108 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
public Context() {
initialize();
}

// Values are hardcoded to keep the example simple


private void initialize() {
assign("a", 20);
assign("b", 40);
assign("c", 30);
assign("d", 10);
}
}

class TerminalExpression implements Expression {


private String var;

public TerminalExpression(String v) {
var = v;
}

public int evaluate(Context c) {


return c.getValue(var);
}
}

abstract class NonTerminalExpression implements Expression {


private Expression leftNode;
private Expression rightNode;

public NonTerminalExpression(Expression l, Expression r) {


setLeftNode(l);
setRightNode(r);
}

public void setLeftNode(Expression node) {


leftNode = node;
}

public void setRightNode(Expression node) {


rightNode = node;
}

public Expression getLeftNode() {


return leftNode;
}

public Expression getRightNode() {


return rightNode;
}
}// NonTerminalExpression

class AddExpression extends NonTerminalExpression {


public int evaluate(Context c) {
return getLeftNode().evaluate(c) + getRightNode().evaluate(c);
}

public AddExpression(Expression l, Expression r) {


super(l, r);

109 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T
}
}// AddExpression

class SubtractExpression extends NonTerminalExpression {


public int evaluate(Context c) {
return getLeftNode().evaluate(c) - getRightNode().evaluate(c);
}

public SubtractExpression(Expression l, Expression r) {


super(l, r);
}
}// SubtractExpression

class MultiplyExpression extends NonTerminalExpression {


public int evaluate(Context c) {
return getLeftNode().evaluate(c) * getRightNode().evaluate(c);
}

public MultiplyExpression(Expression l, Expression r) {


super(l, r);
}
}// MultiplyExpression

110 | S u m i t A g r a w a l | J a v a A r c h i t e c t | M C C R e t a i l C O E | H C L T

You might also like