0% found this document useful (0 votes)
3 views67 pages

Chapter On 5 Design Patterns

Chapter 7 discusses design patterns and software refactoring, focusing on their definitions, elements, and templates. It emphasizes the importance of design patterns as formalized solutions to recurring design problems and introduces the Singleton pattern as a practical example. The chapter also categorizes design patterns into creational, structural, and behavioral types, providing a foundation for understanding and applying these concepts in software development.

Uploaded by

Rodrigue ndzana
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views67 pages

Chapter On 5 Design Patterns

Chapter 7 discusses design patterns and software refactoring, focusing on their definitions, elements, and templates. It emphasizes the importance of design patterns as formalized solutions to recurring design problems and introduces the Singleton pattern as a practical example. The chapter also categorizes design patterns into creational, structural, and behavioral types, providing a foundation for understanding and applying these concepts in software development.

Uploaded by

Rodrigue ndzana
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Chapter 7

Design Patterns and Software


Refactoring

7.1 Chapter Objectives

1. Be able to know what design patterns are.

2. From a given list, select the most appropriate pattern for a given scenario and
demonstrate its applicability

3. From a list, select the most appropriate pattern for a given scenario. Patterns
are limited to those documented in the book - Gamma, Erich; Richard Helm,
Ralph Johnson, and John Vlissides (1995). Design Patterns: Elements of Reusable
Object-Oriented Software and are named using the names given in that book.

4. Understand the idea of refactoring and re-factor software code to Design Patterns

7.2 What are Patterns

Christopher Alexander talking about buildings and towns ”Each pattern describes a
problem which occurs over and over again in our environment, and then describes the
core of the solution to that problem, in such a way that you can use this solution a
million times over, without ever doing it the same way twice ” Alexander, et al., A
Pattern Language. Oxford University Press, 1977

Patterns can have different levels of abstraction. In Design Patterns (the book), Patterns
are not classes, Patterns are not frameworks. Instead, Patterns are descriptions of
communicating objects and classes that are customized to solve a general design problem
in a particular context

So, patterns are formalized solutions to design problems. They describe techniques for
maximizing flexibility, extensibility, abstraction, etc. These solutions can typically be
translated to code in a straight forward manner.

It is important to note the fact that Patterns makes our life easy by giving guidelines
to apply in a given context and for a specific problem.
67
Design Patterns and Software Refactoring 68

7.3 Elements of Patterns

Pattern Name

This is more than just a handle for referring to the pattern. Each name adds to a
designers vocabulary. It enables the discussion of design at a higher abstraction.

The Problem

This gives a detailed description of the problem addressed by the pattern. It describes
when to apply a pattern, often with a list of preconditions.

The Solution This describes the elements that make up the design, their relation-
ships,responsibilities, and collaborations. It does not describe a concrete solution. In-
stead a template to be applied in many situations

The consequences

This describes the results and tradeoffs of applying the pattern. It is critical for evalu-
ating design alternatives Typically include impact on flexibility, extensibility, or porta-
bility, Space and Time tradeoffs, Language and Implementation issues

7.4 Design Patterns Templates

1. Pattern Name and Classification

� Creational
� Structural
� Behavioural

2. Intent Also Known As Motivation and Applicability

3. Structure and Participants

4. Collaborations

5. Consequences

6. Implementation

7. Sample Code

8. Known Uses

9. Related Patterns

7.5 Documenting Design Patterns Selected Example Us-


ing a Singleton

The selected pattern is Singleton because of its simplicity to grasp and understand.
Design Patterns and Software Refactoring 69

7.5.1 Singleton

Intent

Ensure a class has only one instance, and provide a global point of access to it

Motivation

Some classes represent objects where multiple instances do not make sense or can lead
to a security risk (e.g. Java security managers) and memory or heap overload

Applicability

Use the Singleton pattern when there must be exactly one instance of a class, and it must
be accessible to clients from a well-known access point, when the sole instance should
be extensible by subclassing, and clients should be able to use an extended instance
without modifying their code

Structure

Participants

Just the Singleton class

Collaborations

Clients access a Singleton instance solely through Singletons Instance operation

Consequences

Controlled access to sole instance. Reduced name space (versus global variables) Permits
a variable number of instances (if desired)

Implementation

import java . util . Date ;

public class Singleton {


private static Singleton theOnlyOne ;
p r i v a t e D a t e d = new D a t e ( ) ;

private Singleton () {
}

public synchronized s t a t i c Singleton instance () {


if ( t h e O n l y O n e == n u l l ) {
t h e O n l y O n e = new S i n g l e t o n ( ) ;
}
return theOnlyOne ;
}

public Date getDate () {


return d ;
}
}

Listing 7.1: Singleton Implementation

Usage
Design Patterns and Software Refactoring 70

public class UseSingleton {


public s t a t i c void main ( S t r i n g [ ] args ) {
Singleton a = Singleton . instance () ;
Singleton b = Singleton . instance () ;
S y s t e m . out . p r i n t l n ( ”” + a . g e t D a t e ( ) ) ;
S y s t e m . out . p r i n t l n ( ”” + b . g e t D a t e ( ) ) ;
S y s t e m . out . p r i n t l n ( ”” + a ) ;
S y s t e m . out . p r i n t l n ( ”” + b ) ;
}
}

Listing 7.2: Singleton Usage

Output:

Sun Apr 17 13:03:34 MDT 2011


Sun Apr 17 13:03:34 MDT 2011
Singleton@136646
Singleton@136646

7.6 GOF patterns and Their Classification

There are totally 23 design patterns in GoF ( Gang of Four). All these 23 design patterns
are mapped to 3 main categories:

1. Creational patterns : Makes Object creation/instantiation job easy.

2. Structural patterns : Makes Objects available to other class by changing the in-
terfaces or contract.

3. Behavioral patterns: Deals with object state changes and it’s interaction with
other classes/objects.
Design Patterns and Software Refactoring 71

7.7 GOF Design Patterns Examples in Java

The following section has exercise for the 23 GOF patterns. Create a java application
and folders as shown in the diagram below.

And then do the exercises below. Record your output in the log book or word document.
zip your application together with your output and upload to WEBCT

7.7.1 Creational Design Patterns

The basic form of object creation could result in design problems or added complexity
to the design. Creational design patterns solve this problem by somehow controlling this
object creation.

Creational patterns involve the construction of new objects by often hiding the construc-
tors in the classes being created, and provides alternate methods to return instances of
the desired class.

All the creational patterns define the best possible way in which an object can be created
considering reuse and changeability. These describes the best way to handle instantia-
tion.

Hard coding the actual instantiation is a pitfall and should be avoided if reuse and
changeability are desired. In such scenarios, we can make use of creational patterns to
give this a more general and flexible approach.

1. Singleton
Design Patterns and Software Refactoring 72

2. Factory Method

3. Abstract Factory

4. Builder Pattern

5. Prototype

[Link] Singleton Pattern

This is another version of the simplest Design Pattern you will ever come across. Essen-
tially. a singleton is a class that is instantiated only once.

This is typically accomplished by creating a static field in the class representing the
class. A static method exists on the class to obtain the instance of the class and is
typically named something such as getInstance(). The creation of the object referenced
by the static field can be done either when the class is initialized or the first time that
getInstance() is called. The singleton class typically has a private constructor to prevent
the singleton class from being instantiated via a constructor. Rather, the instance of
the singleton is obtained via the static getInstance() method.

The SingletonExample class is an example of a typical singleton class. It contains a


private static SingletonExample field. It has a private constructor so that the class
can’t be instantiated by outside classes. It has a public static getInstance() method that
returns the one and only SingletonExample instance. If this instance doesn’t already
exist, the getInstance() method creates it. The SingletonExample class has a public
sayHello() method that can be used to test the singleton.

/�
� To c h a n g e t h i s t e m p l a t e , c h o o s e T o o l s | T e m p l a t e s
� and open t h e t e m p l a t e i n t h e e d i t o r .
�/
package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . s i n g l e t o n ;

/� �

� @author b o n i f a c e
�/
public class SingletonExample {

private static SingletonExample singletonExample = null ;

private SingletonExample () {
}

public static SingletonExample getInstance () {


if ( s i n g l e t o n E x a m p l e == n u l l ) {
s i n g l e t o n E x a m p l e = new S i n g l e t o n E x a m p l e ( ) ;
}
return singletonExample ;
}

public void s a y H e l l o () {
System . out . println (” Hello ”) ;
}
}
Design Patterns and Software Refactoring 73

The MainDriver class obtains a SingletonExample singleton class via the call to the
static [Link](). We call the sayHello() method on the singleton
class.

/�
� To c h a n g e t h i s t e m p l a t e , c h o o s e T o o l s | T e m p l a t e s
� and open t h e t e m p l a t e i n t h e e d i t o r .
�/
package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . s i n g l e t o n ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public s t a t i c void main ( S t r i n g [ ] args ) {


SingletonExample singletonExample = SingletonExample . getInstance () ;
singletonExample . sayHello () ;
}
}

Record output in your log.

[Link] Factory Method Pattern

The Factory Pattern (also known as the Factory Method Pattern ) is a creational
design pattern. A factory is a Java class that is used to encapsulate object creation
code. A factory class instantiates and returns a particular type of object based on data
passed to the factory. The different types of objects that are returned from a factory
typically are subclasses of a common parent class.

The data passed from the calling code to the factory can be passed either when the
factory is created or when the method on the factory is called to create an object. This
creational method is often called something such as getInstance or getClass .

As a simple example, let’s create an AnimalFactory class that will return an animal
object based on some data input. To start, here is an abstract Animal class. The
factory will return an instantiated subclass of Animal. Animal has a single abstract
method, makeSound().

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;

/� �

� @author b o n i f a c e
�/
public abstract class Animal {
public abstract String makeSound () ;
Design Patterns and Software Refactoring 74

The Dog class is a subclass of Animal. It implements makeSound() to return ”Woof”.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class Dog extends Animal {

@Override
public String makeSound () {
r e t u r n ”Woof” ;
}
}

The Cat class is a subclass of Animal. It implements makeSound() to return ”Meow”.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class Cat extends Animal {

@Override
public String makeSound () {
r e t u r n ”Meow” ;
}
}

Now, let’s implement our factory. We will call our factory’s object creation method
getAnimal. This method takes a String as a parameter. If the String is ”canine”, it
returns a Dog object. Otherwise, it returns a Cat object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;

/� �

� @author b o n i f a c e
�/
public class AnimalFactory {

public Animal getAnimal ( String type ) {


if ( ” canine ” . equals ( type ) ) {
r e t u r n new D o g ( ) ;
} else {
r e t u r n new C a t ( ) ;
}
}
}

The MainDriver class demonstrates the use of our factory. It creates an AnimalFactory
factory. The factory creates an Animal object and then another Animal object. The first
object is a Cat and the second object is a Dog. The output of each object’s makeSound()
method is displayed.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class MainDriver {

public s t a t i c void main ( S t r i n g [ ] args ) {


A n i m a l F a c t o r y a n i m a l F a c t o r y = new A n i m a l F a c t o r y ( ) ;

Animal a1 = a n i m a l F a c t o r y . g e t A n i m a l ( ” f e l i n e ” ) ;
S y s t e m . o u t . p r i n t l n ( ” a1 sound : ” + a 1 . m a k e S o u n d ( ) ) ;

Animal a2 = a n i m a l F a c t o r y . g e t A n i m a l ( ” canine ” ) ;
S y s t e m . o u t . p r i n t l n ( ” a2 sound : ” + a 2 . m a k e S o u n d ( ) ) ;
Design Patterns and Software Refactoring 75

}
}

Record your output in your log book.

Notice that the factory has encapsulated our Animal object creation code, thus resulting
in clean code in Demo, the class that creates the factory. Additionally, notice the use of
polymorphism. We obtain different Animal objects (Cat and Dog) based on data passed
to the factory.

Note that it is common to pass data that determines the type of object to be created
to the factory when the factory is created (via the factory constructor). However, if
multiple objects are being created by the factory, it may make sense to pass this data to
the factory’s creational method rather than to the constructor, since it might not make
sense to create a new factory object each time we wanted to have the factory instantiate
a new object.

A factory may also be used in conjunction with the singleton pattern. It is common to
have a singleton return a factory instance. To do this, we could replace:

AnimalFactory a n i m a l F a c t o r y = new A n i m a l F a c t o r y ( ) ;

with

AnimalFactory animalFactory = AnimalFactory . getAnimalFactoryInstance () ;

In this example, [Link]() would be implemented to


return a static AnimalFactory object. This results in a single factory being instantiated
and used rather than requiring a new factory to be instantiated each time the factory
needs to be used.

Redo the AnimalFactory to make it a singleton, run the code and include
you new modified code in your submission.

[Link] Abstract Factory Pattern


Design Patterns and Software Refactoring 76

The abstract factory pattern is a creational design pattern. An abstract factory is a


factory that returns factories. Why is this layer of abstraction useful? A normal factory
can be used to create sets of related objects. An abstract factory returns factories. Thus,
an abstract factory is used to return factories that can be used to create sets of related
objects.

As an example, you could have a BMW factory that returns car part objects (seats, air
filters, etc) associated with a BMW. You could also have a Toyota factory that returns car
part objects associated with a Toyota. We could create an abstract factory that returns
these different types of car factories depending on the car that we were interested in.
We could then obtain car part objects from the car factory. Via polymorphism, we can
use a common interface to get the different factories, and we could could then use a
common interface to get the different car parts.

Now, we’ll look at the code for a simple example of the Abstract Factory Design Pattern.

Our AbstractFactory will return either a MammalFactory or a ReptileFactory via the


SpeciesFactory return type. MammalFactory and ReptileFactory are subclasses of Species-
Factory.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . a b s t r a c t f a c t o r y ;
/� �

� @author b o n i f a c e
�/
public class AbstractFactory {

public SpeciesFactory getSpeciesFactory ( String type ) {


if ( ”mammal” . e q u a l s ( t y p e ) ) {
r e t u r n new M a m m a l F a c t o r y ( ) ;
} else {
r e t u r n new R e p t i l e F a c t o r y ( ) ;
}
}
}

SpeciesFactory is an abstract class with the getAnimal() abstract method. This method
returns an Animal object. The polymorphism of AbstractFactory is achieved because its
getSpeciesFactory() method returns a SpeciesFactory, regardless of the actual underlying
class. This polymorphism could also be achieved via an interface rather than an abstract
class.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . a b s t r a c t f a c t o r y ;
/� �

� @author b o n i f a c e
�/
public abstract class SpeciesFactory {
public abstract Animal getAnimal ( String type ) ;
}

MammalFactory implements getAnimal(). It returns an Animal, which is either a Dog


or a Cat.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . a b s t r a c t f a c t o r y ;

/� �

� @author b o n i f a c e
�/
public class MammalFactory extends SpeciesFactory {

@Override
public Animal getAnimal ( String type ) {
i f ( ” dog ” . e q u a l s ( t y p e ) ) {
r e t u r n new D o g ( ) ;
Design Patterns and Software Refactoring 77

} else {
r e t u r n new C a t ( ) ;
}
}
}

ReptileFactory implements getAnimal(). It returns an Animal, which is either a Snake


or a Tyrannosaurus.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . a b s t r a c t f a c t o r y ;

/� �

� @author b o n i f a c e
�/
public class ReptileFactory extends SpeciesFactory {

@Override
public Animal getAnimal ( String type ) {
i f ( ” snake ” . e q u a l s ( t y p e ) ) {
r e t u r n new S n a k e ( ) ;
} else {
r e t u r n new T y r a n n o s a u r u s ( ) ;
}
}
}

Animal is an abstract class with the makeSound() abstract method. Subclasses of Ani-
mal implement the makeSound() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;

/� �

� @author b o n i f a c e
�/
public abstract class Animal {
public abstract String makeSound () ;
}

Cat Class

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class Cat extends Animal {

@Override
public String makeSound () {
r e t u r n ”Meow” ;
}
}

The Dog class

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class Dog extends Animal {

@Override
public String makeSound () {
r e t u r n ”Woof” ;
}
}

The Snake Class


Design Patterns and Software Refactoring 78

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class Cat extends Animal {

@Override
public String makeSound () {
return ” Hiss ” ;
}
}

The Tyrannosaurus class is shown here.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . f a c t o r y m e t h o d ;
/� �

� @author b o n i f a c e
�/
public class Tyrannosaurus extends Animal {

@Override
public String makeSound () {
r e t u r n ” Roar ” ;
}
}

The DriverMain class contains our main() method. It creates an AbstractFactory object.
From the AbstractFactory, we obtain a SpeciesFactory (a ReptileFactory) and get two
Animal objects (Tyrannosaurus and Snake) from the SpeciesFactory. After this, we
obtain another SpeciesFactory (a MammalFactory) and then obtain two more Animal
objects (Dog and Cat).

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . a b s t r a c t f a c t o r y ;

/� �

� @author b o n i f a c e
�/
public abstract class MainDriver {

public s t a t i c void main ( S t r i n g [ ] args ) {


A b s t r a c t F a c t o r y a b s t r a c t F a c t o r y = new A b s t r a c t F a c t o r y ( ) ;

SpeciesFactory speciesFactory1 = abstractFactory . getSpeciesFactory (” reptile ”) ;


Animal a1 = s p e c i e s F a c t o r y 1 . g e t A n i m a l ( ” tyrannosaurus ” ) ;
S y s t e m . o u t . p r i n t l n ( ” a1 sound : ” + a 1 . m a k e S o u n d ( ) ) ;
A n i m a l a2 = s p e c i e s F a c t o r y 1 . g e t A n i m a l ( ” snake ” ) ;
S y s t e m . o u t . p r i n t l n ( ” a2 sound : ” + a 2 . m a k e S o u n d ( ) ) ;

S p e c i e s F a c t o r y s p e c i e s F a c t o r y 2 = a b s t r a c t F a c t o r y . g e t S p e c i e s F a c t o r y ( ”mammal” ) ;
A n i m a l a 3 = s p e c i e s F a c t o r y 2 . g e t A n i m a l ( ” dog ” ) ;
S y s t e m . o u t . p r i n t l n ( ” a3 sound : ” + a 3 . m a k e S o u n d ( ) ) ;
Animal a4 = s p e c i e s F a c t o r y 2 . g e t A n i m a l ( ” cat ” ) ;
S y s t e m . o u t . p r i n t l n ( ” a4 sound : ” + a 4 . m a k e S o u n d ( ) ) ;

}
}

Execute the code and record output in your log book.

Notice the use of polymorphism. We obtain different factories via the common Species-
Factory superclass. We also obtain different animals via the common Animal superclass.
Design Patterns and Software Refactoring 79

[Link] Builder Pattern

The builder pattern is a creational design pattern used to assemble complex objects.
With the builder pattern, the same object construction process can be used to create
different objects. The builder has 4 main parts: a Builder, Concrete Builders, a Director,
and a Product.

A Builder is an interface (or abstract class) that is implemented (or extended) by Con-
crete Builders. The Builder interface sets forth the actions (methods) involved in as-
sembling a Product object. It also has a method for retrieving the Product object (ie,
getProduct()). The Product object is the object that gets assembled in the builder
pattern.

Concrete Builders implement the Builder interface (or extend the Builder abstract class).
A Concrete Builder is responsible for creating and assembling a Product object. Different
Concrete Builders create and assemble Product objects differently.

A Director object is responsible for constructing a Product. It does this via the Builder
interface to a Concrete Builder. It constructs a Product via the various Builder methods.

There are various uses of the builder pattern. For one, if we’d like the construction
process to remain the same but we’d like to create a different type of Product, we can
create a new Concrete Builder and pass this to the same Director. If we’d like to alter
the construction process, we can modify the Director to use a different construction
process.

Now, let’s look at an example of the builder pattern. Our example will build different
kinds of restaurant meals.

First off, our Product will be a Meal class, which represents food items in a meal. It
represents a drink, main course, and side item.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . b u i l d e r ;

/� �

� @author b o n i f a c e
�/
public class Meal {
Design Patterns and Software Refactoring 80

private String drink ;


private String mainCourse ;
private String side ;

public String getDrink () {


return drink ;
}

public void s e t D r i n k ( S t r i n g drink ) {


this . drink = drink ;
}

public String getMainCourse () {


return mainCourse ;
}

public void s e t M a i n C o u r s e ( S t r i n g m a i n C o u r s e ) {
this . mainCourse = mainCourse ;
}

public String getSide () {


return side ;
}

public void s e t S i d e ( S t r i n g side ) {


this . side = side ;
}

public String toString () {


r e t u r n ” d r i n k : ” + d r i n k + ” , main c o u r s e : ” + m a i n C o u r s e + ” , side : ” + side ;
}
}

Our Builder interface is MealBuilder. It features methods used to build a meal and a
method to retrieve the meal.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . b u i l d e r ;

/� �

� @author b o n i f a c e
�/
public interface MealBuilder {
public void b u i l d D r i n k () ;

public void buildMainCourse () ;

public void buildSide () ;

public Meal getMeal () ;


}

Our first Concrete Builder is ItalianMealBuilder. Its constructor creates a meal. Its
methods are implemented to build the various parts of the meal. It returns the meal via
getMeal().

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . b u i l d e r ;

/� �

� @author b o n i f a c e
�/
public class ItalianMealBuilder implements MealBuilder {

private Meal meal ;

public ItalianMealBuilder () {
m e a l = new M e a l ( ) ;
}

@Override
public void b u i l d D r i n k () {
m e a l . s e t D r i n k ( ” r e d wine ” ) ;
}

@Override
public void b u i l d M a i n C o u r s e () {
meal . setMainCourse (” pizza ”) ;
}

@Override
public void b u i l d S i d e () {
m e a l . s e t S i d e ( ” bread ” ) ;
}
Design Patterns and Software Refactoring 81

@Override
public Meal getMeal () {
return meal ;
}
}

Our second Concrete Builder is JapaneseMealBuilder. Its constructor creates a meal.


Its methods are implemented to build the various parts of a Japanese meal. It returns
the meal via getMeal().

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . b u i l d e r ;

/� �

� @author b o n i f a c e
�/
public class JapaneseMealBuilder implements MealBuilder {

private Meal meal ;

public JapaneseMealBuilder () {
m e a l = new M e a l ( ) ;
}

@Override
public void b u i l d D r i n k () {
meal . s e t D r i n k ( ” sake ” ) ;
}

@Override
public void b u i l d M a i n C o u r s e () {
meal . s e t M a i n C o u r s e ( ” chicken t e r i y a k i ” ) ;
}

@Override
public void b u i l d S i d e () {
m e a l . s e t S i d e ( ” miso soup ” ) ;
}

@Override
public Meal getMeal () {
return meal ;
}
}

Our Director class is MealDirector. It takes a MealBuilder as a parameter in its construc-


tor. Thus, a different type of meal will be assembled by the MealDirector depending on
the Concrete Builder passed in to the constructor. The assembly of the meal (Product)
takes place in the constructMeal() method of the Director. This method spells out the
parts of the meal that will be assembled.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . b u i l d e r ;

/� �

� @author b o n i f a c e
�/
public class MealDirector {

private MealBuilder mealBuilder = null ;

public MealDirector ( MealBuilder mealBuilder ) {


this . mealBuilder = mealBuilder ;
}
public void c o n s t r u c t M e a l () {
mealBuilder . buildDrink () ;
mealBuilder . buildMainCourse () ;
mealBuilder . buildSide () ;
}
public Meal getMeal () {
return mealBuilder . getMeal () ;
}
}

The MainDriver class lets us demonstrate our builder pattern. First, our director builds
an Italian meal. An ItalianMealBuilder is passed to the MealDirector’s constructor.
The meal is constructed via [Link](). The meal is obtained from
Design Patterns and Software Refactoring 82

mealDirector via [Link](). The Italian meal is displayed. After this, we


perform the same process to build and display a Japanese meal.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . b u i l d e r ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

M e a l B u i l d e r m e a l B u i l d e r = new I t a l i a n M e a l B u i l d e r ( ) ;
M e a l D i r e c t o r m e a l D i r e c t o r = new M e a l D i r e c t o r ( m e a l B u i l d e r ) ;
mealDirector . constructMeal () ;
Meal meal = mealDirector . getMeal () ;
S y s t e m . o u t . p r i n t l n ( ” meal i s : ” + m e a l ) ;

m e a l B u i l d e r = new J a p a n e s e M e a l B u i l d e r ( ) ;
m e a l D i r e c t o r = new M e a l D i r e c t o r ( m e a l B u i l d e r ) ;
mealDirector . constructMeal () ;
meal = mealDirector . getMeal () ;
S y s t e m . o u t . p r i n t l n ( ” meal i s : ” + m e a l ) ;
}
}

Record Output in your log book

Notice that if we’d like to create a new type of meal, we can do so by implementing
a new Concrete Builder (ie, SwedishMealBuilder, FrenchMealBuilder, etc), which we’d
pass to the MealDirector. If we’d like the meal to be constructed of different parts (ie,
no drink), we can alter the construction process in MealDirector. Thus, construction
process has been separated to the Director, and the data representation is controlled by
the Concrete Builders that implement the Builder interface.

Create a two extra meals for your Example and include the code in your
submission

[Link] Prototype Pattern

The prototype pattern is a creational design pattern. In the prototype pattern, a new
object is created by cloning an existing object. In Java, the clone() method is an
implementation of this design pattern. The prototype pattern can be a useful way of
creating copies of objects.

One example of how this can be useful is if an original object is created with a resource
such as a data stream that may not be available at the time that a clone of the object
is needed.

Another example is if the original object creation involves a significant time commitment,
such as reading data from a database or over a network. An added benefit of the
Design Patterns and Software Refactoring 83

prototype pattern is that it can reduce class proliferation in a project by avoiding factory
proliferation.

Normally in Java, if you’d like to use cloning (ie, the prototype pattern), you can utilize
the clone() method and the Cloneable interface. By default, clone() performs a shallow
copy

However, we can implement our own prototype pattern. To do so, we’ll create a Proto-
type interface that features a doClone() method.

public interface Prototype {

public Prototype doClone () ;

The Person class implements the doClone() method. This method creates a new Person
object and clones the name field. It returns the newly cloned Person object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . p r o t o t y p e ;
/� �

� @author b o n i f a c e
�/
public class Person implements Prototype {

String name ;

public Person ( String name ) {


this . name = name ;
}

@Override
public Prototype doClone () {
r e t u r n new P e r s o n ( n a m e ) ;
}

public String toString () {


r e t u r n ” T h i s p e r s o n i s named ” + n a m e ;
}
}

The Dog class also implements the doClone() method. This method creates a new Dog
object and clones the sound field. The cloned Dog object is returned.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . p r o t o t y p e ;
/� �

� @author b o n i f a c e
�/
public class D o g implements Prototype {

String sound ;

public Dog ( String sound ) {


this . sound = sound ;
}

@Override
public Prototype doClone () {
r e t u r n new D o g ( s o u n d ) ;
}

public String toString () {


r e t u r n ” T h i s dog s a y s ” + s o u n d ;
}
}

The MainDriver creates a Person object and then clones it to a second Person object.
It then creates a Dog object and clones it to a second Dog object.
Design Patterns and Software Refactoring 84

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . c r e a t i o n a l . p r o t o t y p e ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

P e r s o n p e r s o n 1 = new P e r s o n ( ” Fred ” ) ;
S y s t e m . out . p r i n t l n ( ” person 1: ” + p e r s o n 1 ) ;
Person person2 = ( Person ) person1 . doClone () ;
S y s t e m . out . p r i n t l n ( ” person 2: ” + p e r s o n 2 ) ;

D o g d o g 1 = new D o g ( ”Wooof ! ” ) ;
S y s t e m . o u t . p r i n t l n ( ” dog 1 : ” + d o g 1 ) ;
Dog dog2 = ( Dog ) dog1 . doClone () ;
S y s t e m . o u t . p r i n t l n ( ” dog 2 : ” + d o g 2 ) ;

}
}

Record output in your log book


Design Patterns and Software Refactoring 85

7.7.2 Structural Design Patterns

In software engineering, structural design patterns are design patterns that ease the
design by identifying a simple way to realize relationships between entities.

A structural design pattern serves as a blueprint for how different classes and objects
are combined to form larger structures. Unlike creational patterns, which are mostly
different ways to fulfill the same fundamental purpose, each structural pattern has a
different purpose.

Structural Patterns describe how objects and classes can be combined to form structures.
We distinguish between object patterns and class patterns.

The difference is that class patterns describe relationships and structures with the help
of inheritance. Object patterns, on other hand, describe how objects can be associated
and aggregated to form larger, more complex structures.

In some sense, structural patterns are similar to the simpler concept of data structures.

However, structural design patterns also specify the methods that connect objects, not
merely the references between them. Furthermore, data structures are fairly static
entities. They only describe how data is arranged in the structure.

A structural design pattern also describes how data moves through the pattern. Struc-
tural class patterns use inheritance to combine the interfaces or implementations of
multiple classes.

Structural object patterns use object composition to combine the implementations of


multiple objects. They can combine the interfaces of all the composed objects into one
unified interface or they can provide a completely new interface.

1. Adapter pattern

2. Composite pattern

3. Proxy pattern

4. Flyweight Pattern

5. Facade Pattern

6. Bridge Pattern

7. Decorator Pattern
Design Patterns and Software Refactoring 86

[Link] Adapter Pattern

The adapter pattern is a structural design pattern. In the Adapter pattern, a wrapper
class (ie, the adapter) is used to translate requests from it to another class (ie, the
adaptee). In effect, an adapter provides particular interactions with an adaptee that are
not offered directly by the adaptee.

The adapter pattern takes two forms. In the first form, a ”class adapter” utilizes inher-
itance. The class adapter extends the adaptee class and adds the desired methods to
the adapter. These methods can be declared in an interface (ie, the ”target” interface).

In the second form, an ”object adapter” utilizes composition. The object adapter con-
tains an adaptee and implements the target interface to interact with the adaptee.

Now let’s look at simple examples of a class adapter and an object adapter. First, we
have an adaptee class named CelciusReporter. It stores a temperature value in Celcius.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . a d a p t e r ;

/� �

� @author b o n i f a c e
�/
public class CelciusReporter {

double temperatureInC ;

public CelciusReporter () {
}

p u b l i c double g e t T e m p e r a t u r e ( ) {
return temperatureInC ;
}

p u b l i c void s e t T e m p e r a t u r e ( double t e m p e r a t u r e I n C ) {
this . temperatureInC = temperatureInC ;
}
}

Here is our target interface that will be implemented by our adapter. It defines actions
that our adapter will perform.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . a d a p t e r ;

/� �

� @author b o n i f a c e
�/
public interface TemperatureInfo {
Design Patterns and Software Refactoring 87

public double getTemperatureInF () ;

public void s e t T e m p e r a t u r e I n F ( double temperatureInF ) ;

public double getTemperatureInC () ;

public void s e t T e m p e r a t u r e I n C ( double temperatureInC ) ;


}

TemperatureClassReporter is a class adapter. It extends CelciusReporter (the adaptee)


and implements TemperatureInfo (the target interface). If a temperature is in Celcius,
TemperatureClassReporter utilizes the temperatureInC value from CelciusReporter. Fahren-
heit requests are internally handled in Celcius.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . a d a p t e r ;

/� �

� @author b o n i f a c e
�/
// example o f a c l a s s a d a p t e r
public class TemperatureClassReporter extends CelciusReporter implements TemperatureInfo {

@Override
p u b l i c double g e t T e m p e r a t u r e I n C ( ) {
return temperatureInC ;
}

@Override
p u b l i c double g e t T e m p e r a t u r e I n F ( ) {
return cToF ( temperatureInC ) ;
}

@Override
p u b l i c void s e t T e m p e r a t u r e I n C ( double t e m p e r a t u r e I n C ) {
this . temperatureInC = temperatureInC ;
}

@Override
p u b l i c void s e t T e m p e r a t u r e I n F ( double t e m p e r a t u r e I n F ) {
this . temperatureInC = fToC ( temperatureInF ) ;
}

p r i v a t e double f T o C ( double f ) {
return ( ( f − 32) � 5 / 9) ;
}

p r i v a t e double c T o F ( double c ) {
return ( ( c � 9 / 5) + 32) ;
}

TemperatureObjectReporter is an object adapter. It is similar in functionality to Tem-


peratureClassReporter, except that it utilizes composition for the CelciusReporter rather
than inheritance.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . a d a p t e r ;

/� �

� @author b o n i f a c e
�/
// example o f an o b j e c t a d a p t e r
public class TemperatureObjectReporter implements TemperatureInfo {

CelciusReporter celciusReporter ;

public TemperatureObjectReporter () {
c e l c i u s R e p o r t e r = new C e l c i u s R e p o r t e r ( ) ;
}

@Override
p u b l i c double g e t T e m p e r a t u r e I n C ( ) {
return celciusReporter . getTemperature () ;
}

@Override
p u b l i c double g e t T e m p e r a t u r e I n F ( ) {
return cToF ( celciusReporter . getTemperature () ) ;
}
Design Patterns and Software Refactoring 88

@Override
p u b l i c void s e t T e m p e r a t u r e I n C ( double t e m p e r a t u r e I n C ) {
celciusReporter . setTemperature ( temperatureInC ) ;
}

@Override
p u b l i c void s e t T e m p e r a t u r e I n F ( double t e m p e r a t u r e I n F ) {
celciusReporter . setTemperature ( fToC ( temperatureInF ) ) ;
}

p r i v a t e double f T o C ( double f ) {
return ( ( f − 32) � 5 / 9) ;
}

p r i v a t e double c T o F ( double c ) {
return ( ( c � 9 / 5) + 32) ;
}

The MainDriver class is a client class that demonstrates the adapter pattern. First,
it creates a TemperatureClassReporter object and references it via a TemperatureInfo
reference. It demonstrates calls to the class adapter via the TemperatureInfo interface.
After this, it creates a TemperatureObjectReporter object and references it via the same
TemperatureInfo reference. It then demonstrates calls to the object adapter.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . a d a p t e r ;

/� �

� @author b o n i f a c e
�/
public class DriverMain {

public static void main ( String [ ] args ) {

// c l a s s a d a p t e r
S y s t e m . out . p r i n t l n ( ” c l a s s adapter t e s t ” ) ;
T e m p e r a t u r e I n f o t e m p I n f o = new T e m p e r a t u r e C l a s s R e p o r t e r ( ) ;
testTempInfo ( tempInfo ) ;

// o b j e c t a d a p t e r
S y s t e m . o u t . p r i n t l n ( ”\ n o b j e c t adapter t e s t ” ) ;
t e m p I n f o = new T e m p e r a t u r e O b j e c t R e p o r t e r ( ) ;
testTempInfo ( tempInfo ) ;

public s t a t i c void t e s t T e m p I n f o ( T e m p e r a t u r e I n f o t e m p I n f o ) {
tempInfo . setTemperatureInC (0) ;
S y s t e m . o u t . p r i n t l n ( ” temp i n C : ” + t e m p I n f o . g e t T e m p e r a t u r e I n C ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ” temp i n F : ” + t e m p I n f o . g e t T e m p e r a t u r e I n F ( ) ) ;

tempInfo . setTemperatureInF (85) ;


S y s t e m . o u t . p r i n t l n ( ” temp i n C : ” + t e m p I n f o . g e t T e m p e r a t u r e I n C ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ” temp i n F : ” + t e m p I n f o . g e t T e m p e r a t u r e I n F ( ) ) ;
}
}

Write output in your log book


Design Patterns and Software Refactoring 89

[Link] Composite Pattern

The composite pattern is a structural design pattern. In the composite pattern, a tree
structure exists where identical operations can be performed on leaves and nodes. A
node in a tree is a class that can have children. A node class is a ’composite’ class. A leaf
in a tree is a ’primitive’ class that does not have children. The children of a composite
can be leaves or other composites.

The leaf class and the composite class share a common ’component’ interface that defines
the common operations that can be performed on leaves and composites. When an
operation on a composite is performed, this operation is performed on all children of the
composite, whether they are leaves or composites. Thus, the composite pattern can be
used to perform common operations on the objects that compose a tree.

The Gang of Four description of the composite pattern defines a client’s interaction with
the tree struture via a Component interface, where this interface includes the common
operations on the composite and leaf classes, and the add/remove/get operations on the
composites of the tree. This seems slightly awkward since a leaf does not implement the
add/remove/get operations. In Java it makes more sense to define the common leaf/com-
posite operations on a Component interface, but to put the add/remove/get composite
operations in a separate interface or to simply implement them in the composite class.

Now we’ll look at an example of the composite pattern. First, we’ll declare a Component
interface that declares the operations that are common for the composite class and the
leaf class. This allows us to perform operations on composites and leaves using one
standard interface.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . c o m p o s i t e ;

/� �

� @author b o n i f a c e
Design Patterns and Software Refactoring 90

�/
public interface Component {

public void sayHello () ;

public void sayGoodbye () ;


}

The Leaf class has a name field and implements the sayHello() and sayGoodbye() meth-
ods of the Component interface by outputting messages to standard output.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . c o m p o s i t e ;

/� �

� @author b o n i f a c e
�/
public class Leaf implements Component {

String name ;

public Leaf ( String name ) {


this . name = name ;
}

@Override
public void s a y H e l l o () {
System . out . println ( name + ” leaf says hello ”) ;
}

@Override
public void s a y G o o d b y e () {
System . out . println ( name + ” leaf s a y s goodbye ” ) ;
}
}

The Composite class implements the Component interface. It implements the sayHello()
and sayGoodbye() methods by calling these same methods on all of its children, which
are Components (since they can be both Leaf objects and Composite objects, which
both implement the Component interface).

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . c o m p o s i t e ;

import java . util . ArrayList ;


import java . util . List ;

/� �

� @author b o n i f a c e
�/
public class Composite implements Component {

L i s t <C o m p o n e n t > c o m p o n e n t s = new A r r a y L i s t <C o m p o n e n t >() ;

@Override
public void s a y H e l l o () {
for ( Component component : components ) {
component . sayHello () ;
}
}

@Override
public void s a y G o o d b y e () {
for ( Component component : components ) {
component . sayGoodbye () ;
}
}

public void add ( C o m p o n e n t c o m p o n e n t ) {


components . add ( component ) ;
}

public void r e m o v e ( C o m p o n e n t c o m p o n e n t ) {
components . remove ( component ) ;
}

p u b l i c L i s t <C o m p o n e n t > g e t C o m p o n e n t s ( ) {
return components ;
}

public Component getComponent ( int index ) {


return components . get ( index ) ;
Design Patterns and Software Refactoring 91

}
}

The MainDriver class demonstrates the composite pattern. It creates 5 Leaf objects. It
adds two of these two a Composite object and two of these to another Composite object.
It adds these two Composite objects and the last Leaf object to another Composite
object. It calls sayHello() on leaf1, then sayHello() on composite1, then sayHello() on
composite2, and then sayGoodbye() on composite3.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . c o m p o s i t e ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

Leaf leaf1 = new L e a f ( ”Bob” ) ;


Leaf leaf2 = new L e a f ( ” Fred ” ) ;
Leaf leaf3 = new L e a f ( ” Sue ” ) ;
Leaf leaf4 = new Leaf (” Ellen ”) ;
Leaf leaf5 = new L e a f ( ” Joe ” ) ;

C o m p o s i t e c o m p o s i t e 1 = new C o m p o s i t e ( ) ;
composite1 . add ( leaf1 ) ;
composite1 . add ( leaf2 ) ;

C o m p o s i t e c o m p o s i t e 2 = new C o m p o s i t e ( ) ;
composite2 . add ( leaf3 ) ;
composite2 . add ( leaf4 ) ;

Composite c o m p o s i t e 3 = new C o m p o s i t e ( ) ;
composite3 . add ( composite1 ) ;
composite3 . add ( composite2 ) ;
composite3 . add ( leaf5 ) ;

System . out . println (” Calling � s a y H e l l o � on l e a f 1 ” ) ;


leaf1 . sayHello () ;

S y s t e m . o u t . p r i n t l n ( ”\ n C a l l i n g � s a y H e l l o � on c o m p o s i t e 1 ” ) ;
composite1 . sayHello () ;

S y s t e m . o u t . p r i n t l n ( ”\ n C a l l i n g � s a y H e l l o � on c o m p o s i t e 2 ” ) ;
composite2 . sayHello () ;

S y s t e m . o u t . p r i n t l n ( ”\ n C a l l i n g � sayGoodbye � on c o m p o s i t e 3 ” ) ;
composite3 . sayGoodbye () ;

}
}

Write your output in the log book


Design Patterns and Software Refactoring 92

[Link] Proxy Pattern

The proxy pattern is a structural design pattern. In the proxy pattern, a proxy class is
used to control access to another class. The reasons for this control can vary. As one
example, a proxy may avoid instantiation of an object until the object is needed. This
can be useful if the object requires a lot of time or resources to create. Another reason
to use a proxy is to control access rights to an object. A client request may require
certain credentials in order to access the object.

Now, we’ll look at an example of the proxy pattern. First, we’ll create an abstract
class called Thing with a basic sayHello() message that includes the date/time that the
message is displayed.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . p r o x y ;

import java . util . Date ;

/� �

� @author b o n i f a c e
�/
public abstract class Thing {

public void s a y H e l l o () {
S y s t e m . o u t . p r i n t l n ( t h i s . g e t C l a s s ( ) . g e t S i m p l e N a m e ( ) + ” s a y s howdy a t ” + new D a t e ( ) ) ←�
;
}
}

FastThing subclasses Thing.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . p r o x y ;

/� �

� @author b o n i f a c e
�/
public c l a s s F a s t T h i n g extends Thing {
public FastThing () {
}
}

SlowThing also subclasses Thing. However, its constructor takes 5 seconds to execute.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . p r o x y ;
Design Patterns and Software Refactoring 93

/� �

� @author b o n i f a c e
�/
public class SlowThing extends Thing {

public SlowThing () {
try {
Thread . sleep (5000) ;
} catch ( I n t e r r u p t e d E x c e p t i o n e) {
e . printStackTrace () ;
}
}
}

The Proxy class is a proxy to a SlowThing object. Since a SlowThing object takes 5
seconds to create, we’ll use a proxy to a SlowThing so that a SlowThing object is only
created on demand. This occurs when the proxy’s sayHello() method is executed. It
instantiates a SlowThing object if it doesn’t already exist and then calls sayHello() on
the SlowThing object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . p r o x y ;

import java . util . Date ;

/� �

� @author b o n i f a c e
�/
public class Proxy {

SlowThing slowThing ;

public Proxy () {
S y s t e m . o u t . p r i n t l n ( ” C r e a t i n g p r o x y a t ” + new D a t e ( ) ) ;
}

public void s a y H e l l o () {
if ( s l o w T h i n g == n u l l ) {
s l o w T h i n g = new S l o w T h i n g ( ) ;
}
slowThing . sayHello () ;
}
}

The MainDriver class demonstrates the use of our proxy. It creates a Proxy object and
then creates a FastThing object and calls sayHello() on the FastThing object. Next, it
calls sayHello() on the Proxy object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . p r o x y ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public s t a t i c void main ( S t r i n g [ ] args ) {


P r o x y p r o x y = new P r o x y ( ) ;
F a s t T h i n g f a s t T h i n g = new F a s t T h i n g ( ) ;
fastThing . sayHello () ;
proxy . sayHello () ;

}
}

Record your output in the log book.

From the output, notice that creating the Proxy object and calling sayHello() on the
FastThing object occurred at a specific time , and calling sayHello() on the Proxy object
did not call sayHello() on the SlowThing object until another time. We can see that the
SlowThing creation was a time-consuming process. However, this did not slow down the
execution of our application until the SlowThing object was actually required. We can
Design Patterns and Software Refactoring 94

see here that the proxy pattern avoids the creation of time-consuming objects until they
are actually needed.

[Link] Flyweight Pattern

The flyweight pattern is a structural design pattern. In the flyweight pattern, instead of
creating large numbers of similar objects, objects are reused. This can be used to reduce
memory requirements and instantiation time and related costs. Similarities between
objects are stored inside of the objects, and differences are moved outside of the objects
and placed in client code. These differences are passed in to the objects when needed via
method calls on the objects. A Flyweight interface declares these methods. A Concrete
Flyweight class implements the Flyweight interface which is used to perform operations
based on external state and it also stores common state. A Flyweight Factory is used
create and return Flyweight objects.

Now, let’s look at an example of the flyweight design pattern. We’ll create a Flyweight
interface with a doMath() method that will be used to perform a mathematical operation
on two integers passed in as parameters.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f l y w e i g h t ;
/� �

� @author b o n i f a c e
�/
public interface Flyweight {

public void doMath ( int a , int b) ;


}

The FlyweightAdder class is a concrete flyweight class. It contains an ”operation” field


that is used to store the name of an operation that is common to adder flyweights.
Notice the call to [Link](3000). This simulates a construction process that is
expensive in terms of time. Each FlyweightAdder object that is created takes 3 seconds
to create, so we definitely want to minimize the number of flyweight objects that are
created. The doMath() method is implemented. It displays the common ”operation”
Design Patterns and Software Refactoring 95

field and displays the addition of a and b, which are external state values that are passed
in and used by the FlyweightAdder when doMath() is executed.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f l y w e i g h t ;

/� �

� @author b o n i f a c e
�/
public class FlyweightAdder implements Flyweight {

String operation ;

public FlyweightAdder () {
o p e r a t i o n = ” adding ” ;
try {
Thread . sleep (3000) ;
} catch ( I n t e r r u p t e d E x c e p t i o n e) {
e . printStackTrace () ;
}
}

@Override
public void d o M a t h ( i n t a , i n t b ) {
S y s t e m . o u t . p r i n t l n ( o p e r a t i o n + ” ” + a + ” and ” + b + ” : ” + ( a + b ) ) ;
}
}

The FlyweightMultiplier class is similar to the FlyweightAdder class, except that it


performs multiplication rather than addition.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f l y w e i g h t ;

/� �

� @author b o n i f a c e
�/
public class FlyweightMultiplier implements Flyweight {

String operation ;

public FlyweightMultiplier () {
operation = ” multiplying ” ;
try {
Thread . sleep (3000) ;
} catch ( I n t e r r u p t e d E x c e p t i o n e) {
e . printStackTrace () ;
}
}

@Override
public void d o M a t h ( i n t a , i n t b ) {
S y s t e m . o u t . p r i n t l n ( o p e r a t i o n + ” ” + a + ” and ” + b + ” : ” + ( a � b)) ;
}

The FlyweightFactory class is our flyweight factory. It utilizes the singleton pattern so
that we only have once instance of the factory, which we obtain via its static getInstance()
method. The FlyweightFactory creates a hashmap pool of flyweights. If a request is
made for a flyweight object and that object doesn’t exist, it is created and placed in the
flyweight pool. The flyweight pool of the FlyweightFactory stores all the instances of
the different types of flyweights (ie, FlyweightAdder object, FlyweightMultiplier object,
etc). Thus, only one instance of each type is created, and this occurs on-demand.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f l y w e i g h t ;

import java . util . HashMap ;


import java . util . Map ;

/� �

� @author b o n i f a c e
�/
public class FlyweightFactory {
Design Patterns and Software Refactoring 96

private static FlyweightFactory flyweightFactory ;


private M a p <S t r i n g , F l y w e i g h t > f l y w e i g h t P o o l ;

private FlyweightFactory () {
f l y w e i g h t P o o l = new H a s h M a p <S t r i n g , F l y w e i g h t >() ;
}
public static FlyweightFactory getInstance () {
i f ( f l y w e i g h t F a c t o r y == n u l l ) {
f l y w e i g h t F a c t o r y = new F l y w e i g h t F a c t o r y ( ) ;
}
return flyweightFactory ;
}

public Flyweight getFlyweight ( String key ) {


if ( flyweightPool . containsKey ( key ) ) {
return flyweightPool . get ( key ) ;
} else {
Flyweight flyweight ;
i f ( ” add ” . e q u a l s ( k e y ) ) {
f l y w e i g h t = new F l y w e i g h t A d d e r ( ) ;
} else {
f l y w e i g h t = new F l y w e i g h t M u l t i p l i e r ( ) ;
}
f l y w e i g h t P o o l . put ( key , f l y w e i g h t ) ;
return flyweight ;
}
}
}

The MainDriver class demonstrates our flyweight pattern. It obtains a FlyweightFactory


object via [Link](). After this, in a loop, it obtains a Flyweigh-
tAdder from the FlyweightFactory and calls its doMath() operation with the current
loop index as the two parameter values. Next, it does the same thing with a Flyweight-
Multiplier.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f l y w e i g h t ;

/� �

� @author b o n i f a c e
�/

public class MainDriver {

public static void main ( String [ ] args ) {

FlyweightFactory flyweightFactory = FlyweightFactory . getInstance () ;

for ( i n t i = 0 ; i < 5 ; i++) {


F l y w e i g h t f l y w e i g h t A d d e r = f l y w e i g h t F a c t o r y . g e t F l y w e i g h t ( ” add ” ) ;
flyweightAdder . doMath (i , i ) ;

Flyweight flyweightMultiplier = flyweightFactory . getFlyweight (” multiply ”) ;


flyweightMultiplier . doMath (i , i ) ;
}
}
}

Write output in your log book

When executing MainDriver, we see that it takes some seconds to create the Flyweigh-
tAdder object and the same thing happens for the FlyweightMultiplier object. After
this, no more delays occur since we keep reusing the flyweight objects rather than instan-
tiating new objects. This highlights how the flyweight pattern can be used to minimize
resource requirements by avoiding unnecessary object instantiations for similar objects.
Design Patterns and Software Refactoring 97

[Link] Facade Pattern

The facade pattern is a structural design pattern. In the facade pattern, a facade classes
is used to provide a single interface to set of classes. The Facade simplifies a clients
interaction with a complex system by localizing the interactions into a single interface.
As a result, the client can interact with a single object rather than being required to
interact directly in complicated ways with the objects that make up the subsystem.

As an example, supposed we have three horribly written classes. For based on the class
and method names (and the lack of documentation), it would be very difficult for a
client to interact with these classes.

Class1’s doSomethingComplicated() method takes an integer and returns its cube.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f a c a d e ;

/� �

� @author b o n i f a c e
�/
public class Class1 {

public int doSomethingComplicated ( int x) {


return x � x � x ;
}
}

Class2’s doAnotherThing() method doubles the cube of an integer and returns it.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f a c a d e ;

/� �

� @author b o n i f a c e
�/
public class Class2 {

public int doAnotherThing ( Class1 class1 , int x ) {


return 2 � class1 . doSomethingComplicated ( x ) ;
}
}

Class3’s doMoreStuff() takes a Class1 object, a Class2 object, and an integer and returns
twice the sixth power of the integer.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f a c a d e ;

/� �

� @author b o n i f a c e
�/
public class Class3 {

public int doMoreStuff ( Class1 class1 , Class2 class2 , int x ) {


return class1 . doSomethingComplicated ( x ) � class2 . doAnotherThing ( class1 , x) ;
}
}
Design Patterns and Software Refactoring 98

For a client unfamiliar with Class1, Class2, and Class3, it would be very difficult to
figure out how to interact with these classes. The classes interact and perform tasks in
unclear ways. As a result, we need to be able to simplify interaction with this system of
classes so that clients can interact with these classes in a simple, standardized manner.

We do this with the Facade class. The Facade class has three methods: cubeX(), cubeX-
Times2(), and xToSixthPowerTimes2(). The names of these methods clearly indicate
what they do, and these methods hide the interactions of Class1, Class2, and Class3
from client code.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f a c a d e ;

/� �

� @author b o n i f a c e
�/
public class Facade {

public int cubeX ( int x ) {


Class1 c l a s s 1 = new C l a s s 1 ( ) ;
return class1 . doSomethingComplicated ( x ) ;
}

public int cubeXTimes2 ( int x ) {


Class1 c l a s s 1 = new C l a s s 1 ( ) ;
Class2 c l a s s 2 = new C l a s s 2 ( ) ;
return class2 . doAnotherThing ( class1 , x) ;
}

public int xToSixthPowerTimes2 ( int x ) {


Class1 c l a s s 1 = new C l a s s 1 ( ) ;
Class2 c l a s s 2 = new C l a s s 2 ( ) ;
Class3 c l a s s 3 = new C l a s s 3 ( ) ;
return class3 . doMoreStuff ( class1 , class2 , x) ;
}
}

The MainDriver class contains our client code. It creates a Facade object and then calls
its three methods with a parameter value of 3. It displays the returned results.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . f a c a d e ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

F a c a d e f a c a d e = new F a c a d e ( ) ;
int x = 3;
S y s t e m . o u t . p r i n t l n ( ”Cube o f ” + x + ” : ” + f a c a d e . c u b e X ( 3 ) ) ;
S y s t e m . o u t . p r i n t l n ( ”Cube o f ” + x + ” t i m e s 2 : ” + f a c a d e . c u b e X T i m e s 2 ( 3 ) ) ;
S y s t e m . o u t . p r i n t l n ( x + ” t o s i x t h power t i m e s 2 : ” + f a c a d e . x T o S i x t h P o w e r T i m e s 2 ( 3 ) ) ;

}
}

Record your output in your log book

This example demonstrates how the facade pattern can be used to simplify interactions
with a system of classes by providing a single point of interaction with the subsystem
and hiding the complex details of subsystem interactions from client code. This is
accomplished with a Facade class.
Design Patterns and Software Refactoring 99

[Link] Bridge Pattern

The bridge pattern is a structural design pattern. In the bridge pattern, we separate an
abstraction and its implementation and develop separate inheritance structures for both
the abstraction and the implementor. The abstraction is an interface or abstract class,
and the implementor is likewise an interface or abstract class. The abstraction contains
a reference to the implementor. Children of the abstraction are referred to as refined
abstractions, and children of the implementor are concrete implementors. Since we can
change the reference to the implementor in the abstraction, we are able to change the
abstraction’s implementor at run-time. Changes to the implementor do not affect client
code.

The bridge pattern can be demonstrated with an example. Suppose we have a Vehicle
class. We can extract out the implementation of the engine into an Engine class. We
can reference this Engine implementor in our Vehicle via an Engine field. We’ll declare
Vehicle to be an abstract class. Subclasses of Vehicle need to implement the drive()
method. Notice that the Engine reference can be changed via the setEngine() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public abstract class Vehicle {

Engine engine ;
int weightInKilos ;

public abstract void drive () ;

public void s e t E n g i n e ( E n g i n e engine ) {


this . engine = engine ;
}

public void r e p o r t O n S p e e d ( i n t h o r s e p o w e r ) {
int ratio = weightInKilos / horsepower ;
i f ( r a t i o < 3) {
S y s t e m . o u t . p r i n t l n ( ”The v e h i c l e i s g o i n g a t a f a s t s p e e d . ” ) ;
} e l s e i f ( ( r a t i o >= 3 ) && ( r a t i o < 8 ) ) {
S y s t e m . o u t . p r i n t l n ( ”The v e h i c l e i s g o i n g an a v e r a g e s p e e d . ” ) ;
} else {
S y s t e m . o u t . p r i n t l n ( ”The v e h i c l e i s g o i n g a t a s l o w s p e e d . ” ) ;
}
}

BigBus is a subclass of Vehicle. It has a weight of 3000 kg. Its drive() method displays
a message, calls the engine’s go() method, and then calls reportOnSpeed() with the
horsepower of the engine to report on how fast the vehicle is moving.
Design Patterns and Software Refactoring 100

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public class BigBus extends Vehicle {

public BigBus ( Engine engine ) {


thi s . weigh tIn Kil os = 3000;
this . engine = engine ;
}

@Override
public void dr ive () {
S y s t e m . o u t . p r i n t l n ( ” \nThe b i g bus is driving ”) ;
int h o r s e p o w e r = engine . go () ;
reportOnSpeed ( horsepower ) ;
}

SmallCar is similar to BigBus but is much lighter.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public class SmallCar extends Vehicle {

public SmallCar ( Engine engine ) {


this . weightInKilos = 600;
this . engine = engine ;
}

@Override
public void dr ive () {
S y s t e m . o u t . p r i n t l n ( ” \nThe s m a l l car is driving ”) ;
int h o r s e p o w e r = engine . go () ;
reportOnSpeed ( horsepower ) ;
}

Our implementor interface is the Engine interface, which declares the go() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public interface Engine {
public int go () ;
}

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public class BigEngine implements Engine {

int horsepower ;

public BigEngine () {
horsepower = 350;
}

@Override
public int go () {
S y s t e m . o u t . p r i n t l n ( ”The b i g engine is running ” ) ;
return horsepower ;
}
}
Design Patterns and Software Refactoring 101

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public class SmallEngine implements Engine {

int horsepower ;

public SmallEngine () {
horsepower = 100;
}

@Override
public int go () {
S y s t e m . o u t . p r i n t l n ( ”The s m a l l engine is running ” ) ;
return horsepower ;
}
}

The MainDriver class demonstrates our bridge pattern. We create a BigBus vehicle with
a SmallEngine implementor. We call the vehicle’s drive() method. Next, we change the
implementor to a BigEngine and once again call drive(). After this, we create a SmallCar
vehicle with a SmallEngine implementor. We call drive(). Next, we change the engine
to a BigEngine and once again call drive().

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . b r i d g e ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

V e h i c l e v e h i c l e = new B i g B u s ( new S m a l l E n g i n e ( ) ) ;
vehicle . drive () ;
v e h i c l e . s e t E n g i n e ( new B i g E n g i n e ( ) ) ;
vehicle . drive () ;

vehicle = new S m a l l C a r ( new S m a l l E n g i n e ( ) ) ;


vehicle . drive () ;
vehicle . s e t E n g i n e ( new B i g E n g i n e ( ) ) ;
vehicle . drive () ;
}
}

Record your output in the lab book

Notice that we were able to change the implementor (engine) dynamically for each
vehicle. These changes did not affect the client code in MainDriver. In addition, since
BigBus and SmallCar were both subclasses of the Vehicle abstraction, we were even able
to point the vehicle reference to a BigBus object and a SmallCar object and call the
same drive() method for both types of vehicles.
Design Patterns and Software Refactoring 102

[Link] Decorator Pattern

The decorator pattern is a structural design pattern. Whereas inheritance adds func-
tionality to classes, the decorator pattern adds functionality to objects by wrapping
objects in other objects. Each time additional functionality is required, the object is
wrapped in another object. Java I/O streams are a well-known example of the decorator
pattern.

For the decorator pattern, we require a class that serves as the base object that we
add functionality to. This is a Concrete Component, and it implements a Component
interface. The Component interface declares the common operations that are to be
performed by the concrete component and all the decorators that wrap the concrete
component object. A Decorator is an abstract class that implements the Component
interface and contains a reference to a Component. Concrete Decorators are classes that
extend Decorator.

We can illustrate the decorator pattern with an example. We’ll start by creating an
Animal interface. The Animal interface is our component interface.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;

/� �

� @author b o n i f a c e
�/
public interface Animal {

public void describe () ;

LivingAnimal implements Animal and is our concrete component. Its describe() method
displays a message indicating that it is an animal.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;
Design Patterns and Software Refactoring 103

/� �

� @author b o n i f a c e
�/
public class LivingAnimal implements Animal {

@Override
public void d e s c r i b e () {
S y s t e m . o u t . p r i n t l n ( ” \ n I am an a n i m a l . ” ) ;
}
}

AnimalDecorator is our decorator abstract class. It implements Animal but since it is an


abstract class, it does not have to implement describe(). Its constructor sets its Animal
reference field.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;

/� �

� @author b o n i f a c e
�/
public abstract class AnimalDecorator implements Animal {

Animal animal ;

public AnimalDecorator ( Animal animal ) {


this . animal = animal ;
}
}

LegDecorator is a concrete decorator. Its constructor passes an Animal reference to


AnimalDecorator’s constructor. Its describe() method call’s the Animal reference’s
describe() method and then outputs an additional message. It then calls its dance()
method, showing that additional functionality can be added by the concrete decorator.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;

/� �

� @author b o n i f a c e
�/
public class LegDecorator extends AnimalDecorator {

public LegDecorator ( Animal animal ) {


super ( animal ) ;
}

@Override
public void d e s c r i b e () {
animal . describe () ;
S y s t e m . o u t . p r i n t l n ( ” I have legs . ”) ;
dance () ;
}

public void da nce () {


S y s t e m . o u t . p r i n t l n ( ” I can d a n c e . ” ) ;
}
}

WingDecorator is a concrete decorator very similar to LegDecorator.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;

/� �

� @author b o n i f a c e
�/
public class WingDecorator extends AnimalDecorator {

public WingDecorator ( Animal animal ) {


super ( animal ) ;
}

@Override
public void d e s c r i b e () {
animal . describe () ;
Design Patterns and Software Refactoring 104

S y s t e m . o u t . p r i n t l n ( ” I have w i n g s . ” ) ;
fly () ;
}

public void fly () {


S y s t e m . o u t . p r i n t l n ( ” I can fly . ”) ;
}
}

GrowlDecorator is another concrete decorator.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;

/� �

� @author b o n i f a c e
�/
public class GrowlDecorator extends AnimalDecorator {

public GrowlDecorator ( Animal animal ) {


super ( animal ) ;
}

@Override
public void d e s c r i b e () {
animal . describe () ;
growl () ;
}

public void gr owl () {


System . out . println (” Grrrrr . ”) ;
}
}

The MainDriver class demonstrates the decorator design pattern. First, a LivingAnimal
object is created and is referenced via the Animal reference. The describe() method
is called. After this, we wrap the LivingAnimal in a LegDecorator object and once
again call describe. We can see that legs have been added. After that, we wrap the
LegDecorator in a WingDecorator, which adds wings to our animal. Later, we wrap the
animal in two GrowlDecorators. From the describe() output, we can see that two growl
messages are displayed since we wrapped the animal twice.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . s t r u c t u r a l . d e c o r a t o r ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

A n i m a l a n i m a l = new L i v i n g A n i m a l ( ) ;
animal . describe () ;

a n i m a l = new L e g D e c o r a t o r ( a n i m a l ) ;
animal . describe () ;

a n i m a l = new W i n g D e c o r a t o r ( a n i m a l ) ;
animal . describe () ;

a n i m a l = new G r o w l D e c o r a t o r ( a n i m a l ) ;
a n i m a l = new G r o w l D e c o r a t o r ( a n i m a l ) ;
animal . describe () ;
}
}

Record your output in Lab Book

In this example, we just used the Animal reference to refer to the objects. Using this
approach, we could only access the shared operations of the Animal interface (ie, the
describe() method). Instead of referencing this interface, we could have referenced the
concrete decorator class. This would have exposed the unique functionality of the con-
crete decorator.
Design Patterns and Software Refactoring 105

7.7.3 Behavioral Design Patterns

7.7.4 Behavioral patterns

In software engineering, behavioral design patterns are design patterns that identify
common communication patterns between objects and realize these patterns. By doing
so, these patterns increase flexibility in carrying out this communication.

A behavioral pattern explains how objects interact. It describes how different objects
and classes send messages to each other to make things happen and how the steps of a
task are divided among different objects. It describes how different objects work together
to accomplish a task

Where creational patterns mostly describe a moment of time (the instant of creation),
and structural patterns describe a more or less static structure, behavioral patterns
describe a process or a flow.

The interactions between cooperating objects should be such that they are communi-
cating while maintaining as loose coupling as possible. 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.

Behavioral class patterns use inheritance, subclassing, and polymorphism to adjust the
steps taken during a process. Behavioral class patterns focus on changing the exact
algorithm used or task performed depending on circumstances.

1. Template Method Pattern

2. Mediator Pattern

3. Chain of Responsibility Pattern

4. Observer Pattern

5. Strategy Pattern

6. Command Pattern

7. State Pattern

8. Visitor Pattern

9. Iterator Pattern

10. Memento Pattern

11. Interpreter Pattern


Design Patterns and Software Refactoring 106

[Link] Template Method Pattern

The template method pattern is a behavioral class pattern. A behavioral class pat-
tern uses inheritance for distribution of behavior. In the template method pattern, a
method (the ’template method’) defines the steps of an algorithm. The implementation
of these steps (ie, methods) can be deferred to subclasses. Thus, a particular algorithm
is defined in the template method, but the exact steps of this algorithm can be defined
in subclasses. The template method is implemented in an abstract class. The steps
(methods) of the algorithm are declared in the abstract class, and the methods whose
implementations are to be delegated to subclasses are declared abstract.

Here is an example of the template method pattern. Meal is an abstract class with
a template method called doMeal() that defines the steps involved in a meal. We de-
clare the method as final so that it can’t be overridden. The algorithm defined by
doMeal() consists of four steps: prepareIngredients(), cook(), eat(), and cleanUp(). The
eat() method is implemented although subclasses can override the implementation. The
prepareIngredients(), cook(), and cleanUp() methods are are declared abstract so that
subclasses need to implement them.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . t e m p l a t e m e t h o d ;

/� �

� @author b o n i f a c e
�/
public abstract class Meal {
// t e m p l a t e method

public f i n a l void d o M e a l () {
prepareIngredients () ;
cook () ;
eat () ;
cleanUp () ;
}

public abstract void prepareIngredients () ;

public abstract void cook () ;

public void eat () {


S y s t e m . o u t . p r i n t l n ( ”Mmm, t h a t � s good ” ) ;
}

public abstract void cleanUp () ;


}

The HamburgerMeal class extends Meal and implements Meal’s three abstract methods.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . t e m p l a t e m e t h o d ;

/� �

� @author b o n i f a c e
�/
public class HamburgerMeal extends Meal {
Design Patterns and Software Refactoring 107

@Override
public void p r e p a r e I n g r e d i e n t s () {
S y s t e m . o u t . p r i n t l n ( ” G e t t i n g b u r g e r s , buns , and f r e n c h fries ”) ;
}

@Override
public void cook () {
S y s t e m . o u t . p r i n t l n ( ” Cooking b u r g e r s on grill and fries i n oven ” ) ;
}

@Override
public void c l e a n U p () {
S y s t e m . o u t . p r i n t l n ( ” Throwing away p a p e r plates ”) ;
}
}

The CHeeseBurgerMeal class implements Meal’s three abstract methods and also over-
rides the eat() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . t e m p l a t e m e t h o d ;

/� �

� @author b o n i f a c e
�/
public c l a s s C h e e s e B u r g e r M e a l extends Meal {
@Override
public void p r e p a r e I n g r e d i e n t s () {
S y s t e m . o u t . p r i n t l n ( ” G e t t i n g ground b e e f and C h e e s e ” ) ;
}

@Override
public void cook () {
S y s t e m . o u t . p r i n t l n ( ” Cooking ground b e e f i n pan ” ) ;
}

@Override
public void eat () {
S y s t e m . o u t . p r i n t l n ( ”The C h e e s e B u r g e r s are tasty ”) ;
}

@Override
public void c l e a n U p () {
S y s t e m . o u t . p r i n t l n ( ” Doing t h e dishes ”) ;
}

The MainDriver creates a HamburgerMeal object and calls its doMeal() method. It
creates a TacoMeal object and calls doMeal() on the TacoMeal object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . t e m p l a t e m e t h o d ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public s t a t i c void main ( S t r i n g [ ] args ) {


M e a l m e a l 1 = new H a m b u r g e r M e a l ( ) ;
meal1 . doMeal () ;

System . out . println () ;

M e a l m e a l 2 = new C h e e s e B u r g e r M e a l ( ) ;
meal2 . doMeal () ;

}
}

Record your output in your log Book

As you can see, the template method design pattern allows us to define the steps in an
algorithm and pass the implementation of these steps to subclasses.
Design Patterns and Software Refactoring 108

[Link] Mediator Pattern

The mediator pattern is a behavioral object design pattern. The mediator pattern
centralizes communication between objects into a mediator object. This centralization is
useful since it localizes in one place the interactions between objects, which can increase
code maintainability, especially as the number of classes in an application increases.
Since communication occurs with the mediator rather than directly with other objects,
the mediator pattern results in a loose coupling of objects.

The classes that communicate with the mediator are known as Colleagues. The mediator
implementation is known as the Concrete Mediator. The mediator can have an interface
that spells out the communication with Colleages. Colleagues know their mediator, and
the mediator knows its colleagues.

Now, let’s look at an example of this pattern. We’ll create a Mediator class (without
implementing a mediator interface in this example). This mediator will mediate the
communication between two buyers (a Swedish buyer and a French buyer), an American
seller, and a currency converter.

The Mediator has references to the two buyers, the seller, and the converter. It has
methods so that objects of these types can be registered. It also has a placeBid()
method. This method takes a bid amount and a unit of currency as parameters. It
converts this amount to a dollar amount via communication with the dollarConverter.
It then asks the seller if the bid has been accepted, and it returns the answer.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
public class Mediator {

Buyer swedishBuyer ;
Buyer frenchBuyer ;
AmericanSeller americanSeller ;
DollarConverter dollarConverter ;

public Mediator () {
}

public void r e g i s t e r S w e d i s h B u y e r ( S w e d i s h B u y e r swedishBuyer ) {


this . swedishBuyer = swedishBuyer ;
}

public void r e g i s t e r F r e n c h B u y e r ( F r e n c h B u y e r frenchBuyer ) {


this . frenchBuyer = frenchBuyer ;
}

public void r e g i s t e r A m e r i c a n S e l l e r ( A m e r i c a n S e l l e r americanSeller ) {


this . americanSeller = americanSeller ;
}

public void r e g i s t e r D o l l a r C o n v e r t e r ( D o l l a r C o n v e r t e r dollarConverter ) {


this . dollarConverter = dollarConverter ;
}

public boolean placeBid ( float bid , String unitOfCurrency ) {


Design Patterns and Software Refactoring 109

f l o a t d o l l a r A m o u n t = d o l l a r C o n v e r t e r . c o n v e r t C u r r e n c y T o D o l l a r s ( bid , unitOfCurrency ) ;
return americanSeller . isBidAccepted ( dollarAmount ) ;
}
}

Here is the Buyer class. The SwedishBuyer and FrenchBuyer classes are subclasses of
Buyer. The buyer has a unit of currency as a field, and it also has a reference to the
mediator. The Buyer class has a attemptToPurchase() method. This method submits
a bid to the mediator’s placeBid() method. It returns the mediator’s response.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
class Buyer {

Mediator mediator ;
String unitOfCurrency ;

public Buyer ( Mediator mediator , String unitOfCurrency ) {


this . mediator = mediator ;
this . unitOfCurrency = unitOfCurrency ;
}

public boolean a t t e m p t T o P u r c h a s e ( f l o a t bid ) {


S y s t e m . o u t . p r i n t l n ( ” Buyer a t t e m p t i n g a b i d o f ” + b i d + ” ” + u n i t O f C u r r e n c y ) ;
return m e d i a t o r . p l a c e B i d ( bid , u n i t O f C u r r e n c y ) ;
}
}

The SwedishBuyer class is a subclass of Buyer. In the constructor, we set the unitOfCur-
rency to be ”krona”. We also register the SwedishBuyer with the mediator so that the
mediator knows about the SwedishBuyer object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
class SwedishBuyer extends Buyer {

public SwedishBuyer ( Mediator mediator ) {


super ( m e d i a t o r , ” krona ” ) ;
this . mediator . registerSwedishBuyer ( this ) ;
}
}

The FrenchBuyer class is similar to the SwedishBuyer class, except the unitOfCurrency
is ”euro”, and it registers with the mediator as the FrenchBuye

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
class FrenchBuyer extends Buyer {

public FrenchBuyer ( Mediator mediator ) {


super ( m ed ia t or , ” euro ” ) ;
this . mediator . registerFrenchBuyer ( this ) ;
}
}

In the constructor of the AmericanSeller class, the class gets a reference to the mediator
and the priceInDollars gets set. This is the price of some good being sold. The seller
registers with the mediator as the AmericanSeller. The seller’s isBidAccepted() method
Design Patterns and Software Refactoring 110

takes a bid (in dollars). If the bid is over the price (in dollars), the bid is accepted and
true is returned. Otherwise, false is returned.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
class AmericanSeller {

Mediator mediator ;
float priceInDollars ;

public AmericanSeller ( Mediator mediator , float priceInDollars ) {


this . mediator = mediator ;
this . priceInDollars = priceInDollars ;
this . mediator . registerAmericanSeller ( this ) ;
}

public boolean i s B i d A c c e p t e d ( f l o a t b i d I n D o l l a r s ) {
if ( b i d I n D o l l a r s >= p r i c e I n D o l l a r s ) {
S y s t e m . o u t . p r i n t l n ( ” S e l l e r a c c e p t s t h e b i d o f ” + b i d I n D o l l a r s + ” d o l l a r s \n” ) ;
return true ;
} else {
S y s t e m . o u t . p r i n t l n ( ” S e l l e r r e j e c t s t h e b i d o f ” + b i d I n D o l l a r s + ” d o l l a r s \n” ) ;
return f a l s e ;
}
}
}

The DollarConverter class is another colleague class. When created, it gets a reference
to the mediator and registers itself with the mediator as the DollarConverter. This class
has methods to convert amounts in euros and kronor to dollars.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
class DollarConverter {

Mediator mediator ;
public static f i n a l float DOLLAR_UNIT = 1.0 f ;
public static f i n a l float EURO_UNIT = 0.7 f ;
public static f i n a l float KRONA_UNIT = 8.0 f ;

public DollarConverter ( Mediator mediator ) {


this . mediator = mediator ;
mediator . registerDollarConverter ( this ) ;
}

private float convertEurosToDollars ( float euros ) {


float dollars = euros � ( DOLLAR_UNIT / EURO_UNIT ) ;
S y s t e m . out . p r i n t l n ( ” Converting ” + e u r o s + ” euros to ” + d o l l a r s + ” d o l l a r s ” ) ;
return dollars ;
}

private float convertKronorToDollars ( float kronor ) {


float dollars = kronor � ( DOLLAR_UNIT / KRONA_UNIT ) ;
S y s t e m . out . p r i n t l n ( ” Converting ” + k r o n o r + ” kronor to ” + d o l l a r s + ” d o l l a r s ” ) ;
return dollars ;
}

public f l o a t convertCurrencyToDollars ( f l o a t amount , String unitOfCurrency ) {


if ( ” krona ” . e q u a l s I g n o r e C a s e ( u n i t O f C u r r e n c y ) ) {
return convertKronorToDollars ( amount ) ;
} else {
return convertEurosToDollars ( amount ) ;
}
}
}

The MainDriver demonstrates our mediator pattern. It creates a SwedishBuyer object


and a FrenchBuyer object. It creates an AmericanSeller object with a selling price set
to 10 dollars. It then creates a DollarConverter. All of these objects register themselves
with the mediator in their constructors. The Swedish buyer starts with a bid of 55
kronor and keeps bidding up in increments of 15 kronor until the bid is accepted. The
Design Patterns and Software Refactoring 111

French buyer starts bidding at 3 euros and keeps bidding in increments of 1.50 euros
until the bid is accepted.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e d i a t o r ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {
public s t a t i c void main ( S t r i n g [ ] args ) {
M e d i a t o r m e d i a t o r = new M e d i a t o r ( ) ;

B u y e r s w e d i s h B u y e r = new S w e d i s h B u y e r ( m e d i a t o r ) ;
B u y e r f r e n c h B u y e r = new F r e n c h B u y e r ( m e d i a t o r ) ;
f l o a t se lli ngP ric eIn Dollar s = 10.0 f ;
A m e r i c a n S e l l e r a m e r i c a n S e l l e r = new A m e r i c a n S e l l e r ( m e d i a t o r , s e l l i n g P r i c e I n D o l l a r s ) ;
D o l l a r C o n v e r t e r d o l l a r C o n v e r t e r = new D o l l a r C o n v e r t e r ( m e d i a t o r ) ;

f l o a t swedishBidInKronor = 55.0 f ;
while ( ! swedishBuyer . a t t e m p t T o P u r c h a s e ( s w e d i s h B i d I n K r o n o r ) ) {
s w e d i s h B i d I n K r o n o r += 1 5 . 0 f ;
}

f l o a t frenchBidInEuros = 3.0 f ;
while ( ! frenchBuyer . a t t e m p t T o P u r c h a s e ( f r e n c h B i d I n E u r o s ) ) {
f r e n c h B i d I n E u r o s += 1 . 5 f ;
}
}
}

Record your output in the log Book

In this example of the mediator pattern, notice that all communication between our ob-
jects (buyers, seller, and converter) occurs via the mediator. The mediator pattern helps
reduce the number of object references needed (via composition) as classes proliferate
in a project as a project grows.

[Link] Chain of Responsibility Pattern

The chain of responsibility pattern is a behavioral object design pattern. In the chain
of responsibility pattern, a series of handler objects are chained together to handle
a request made by a client object. If the first handler can’t handle the request, the
request is forwarded to the next handler, and it is passed down the chain until the
request reaches a handler that can handle the request or the chain ends. In this pattern,
the client is decoupled from the actual handling of the request, since it does not know
what class will actually handle the request.

In this pattern, a Handler is an interface for handling a request and accessing a handler’s
successor. A Handler is implemented by a Concrete Handler. The Concrete Handler
will handle the request or pass it on to the next Concrete Handler. A Client makes the
request to the start of the handler chain.
Design Patterns and Software Refactoring 112

Now, let’s look at an example of the chain of responsibility pattern. Rather than an
interface, We’ll use an abstract base class as the handler so that subclasses can utilize
the implemented setSuccessor() method. This abstract class is called PlanetHandler.
Concrete handlers that subclass PlanetHandler need to implement the handleRequest()
method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c h a i n o f r e s p o n s i b i l i t y ;

/� �

� @author b o n i f a c e
�/
public abstract class PlanetHandler {

PlanetHandler successor ;

public void s e t S u c c e s s o r ( P l a n e t H a n d l e r successor ) {


this . successor = successor ;
}

public abstract void handleRequest ( PlanetEnum request ) ;


}

This example will utilize an enum of the planets called PlanetEnum.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c h a i n o f r e s p o n s i b i l i t y ;

/� �

� @author b o n i f a c e
�/
public enum PlanetEnum {

MERCURY , VENUS , EARTH , MARS , JUPITER , SATURN , URANUS , NEPTUNE ;


}

MercuryHandler subclasses PlanetHandler and implements the handleRequest() method.


If the request is a [Link], it will handle the request. Otherwise, the
request is passed on to this handler’s successor if the successor exists.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c h a i n o f r e s p o n s i b i l i t y ;

/� �

� @author b o n i f a c e
�/
public class MercuryHandler extends PlanetHandler {

public void h a n d l e R e q u e s t ( P l a n e t E n u m r e q u e s t ) {
if ( r e q u e s t == P l a n e t E n u m . M E R C U R Y ) {
S y s t e m . o u t . p r i n t l n ( ” MercuryHandler h a n d l e s ” + r e q u e s t ) ;
S y s t e m . o u t . p r i n t l n ( ” Mercury i s h o t . \ n” ) ;
} else {
S y s t e m . o u t . p r i n t l n ( ” MercuryHandler doesn � t handle ” + r e q u e s t ) ;
i f ( s u c c e s s o r != n u l l ) {
successor . handleRequest ( request ) ;
}
}
}
}

VenusHandler is similar to MercuryHandler, except it handles [Link] re-


quests.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c h a i n o f r e s p o n s i b i l i t y ;

/� �

� @author b o n i f a c e
�/
public class VenusHandler extends PlanetHandler {

public void h a n d l e R e q u e s t ( P l a n e t E n u m r e q u e s t ) {
if ( r e q u e s t == P l a n e t E n u m . V E N U S ) {
Design Patterns and Software Refactoring 113

S y s t e m . o u t . p r i n t l n ( ” VenusHandler h a n d l e s ” + r e q u e s t ) ;
S y s t e m . o u t . p r i n t l n ( ” Venus i s p o i s o n o u s . \ n” ) ;
} else {
S y s t e m . o u t . p r i n t l n ( ” VenusHandler d o e s n � t h a n d l e ” + r e q u e s t ) ;
i f ( s u c c e s s o r != n u l l ) {
successor . handleRequest ( request ) ;
}
}
}
}

EarthHandler similarly handles [Link] requests.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c h a i n o f r e s p o n s i b i l i t y ;

/� �

� @author b o n i f a c e
�/
public class EarthHandler extends PlanetHandler {

public void h a n d l e R e q u e s t ( P l a n e t E n u m r e q u e s t ) {
if ( r e q u e s t == P l a n e t E n u m . E A R T H ) {
S y s t e m . o u t . p r i n t l n ( ” EarthHandler handles ” + r e q u e s t ) ;
S y s t e m . o u t . p r i n t l n ( ” E art h i s c o m f o r t a b l e . \ n” ) ;
} else {
S y s t e m . o u t . p r i n t l n ( ” EarthHandler doesn � t handle ” + r e q u e s t ) ;
i f ( s u c c e s s o r != n u l l ) {
successor . handleRequest ( request ) ;
}
}
}
}

The MainDriver is the client class. It creates the chain of handlers, starting with Mer-
curyHandler, then VenusHandler, and then EarthHandler. The setUpChain() method
returns the chain to main() via a PlanetHandler reference. Four requests are made of
the chain, where the requests are VENUS, MERCURY, EARTH, and JUPITER.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c h a i n o f r e s p o n s i b i l i t y ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public s t a t i c void main ( S t r i n g [ ] args ) {


PlanetHandler chain = setUpChain () ;
// Submit R e q u e s t s
chain . handleRequest ( PlanetEnum . VENUS ) ;
chain . handleRequest ( PlanetEnum . MERCURY ) ;
chain . handleRequest ( PlanetEnum . EARTH ) ;
chain . handleRequest ( PlanetEnum . JUPITER ) ;
}

public static PlanetHandler setUpChain () {


P l a n e t H a n d l e r m e r c u r y H a n d l e r = new M e r c u r y H a n d l e r ( ) ;
P l a n e t H a n d l e r v e n u s H a n d l e r = new V e n u s H a n d l e r ( ) ;
P l a n e t H a n d l e r e a r t h H a n d l e r = new E a r t h H a n d l e r ( ) ;

mercuryHandler . setSuccessor ( venusHandler ) ;


venusHandler . setSuccessor ( earthHandler ) ;

return mercuryHandler ;
}
}

Record the output in your lab book

Notice that if a handler can’t handle the request, it passes the request on to the next
handler.

Notice that the last request made of the chain is JUPITER. This request is not handled
by any handlers, demonstrating that a request does not have to be handled by any
Design Patterns and Software Refactoring 114

handlers. If we had wanted to, we could have also written an OtherPlanets handler
and placed it at the end of the chain to handle planet requests not handled by other
previous handlers. This would demonstrate that we can make our handlers specific at
the beginning of the chain and more general at the end of the chain, thus handling
broader categories of requests as we approach the end of the chain.

[Link] Observer Pattern

The observer pattern is a behavioral object design pattern. In the observer pattern, an
object called the subject maintains a collection of objects called observers. When the
subject changes, it notifies the observers. Observers can be added or removed from the
collection of observers in the subject. The changes in state of the subject can be passed
to the observers so that the observers can change their own state to reflect this change.

The subject has an interface that defines methods for attaching and detaching observers
from the subject’s collection of observers. This interface also features a notification
method. This method should be called when the state of the subject changes. This
notifies the observers that the subject’s state has changed. The observers have an
interface with a method to update the observer. This update method is called for each
observer in the subject’s notification method. Since this communication occurs via an
interface, any concrete observer implementing the observer interface can be updated by
the subject. This results in loose coupling between the subject and the observer classes.

Now we’ll look at an example of the observer pattern. We’ll start by creating an interface
for the subject called WeatherSubject. This will declare three methods: addObserver(),
removeObserver(), and doNotify().

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . o b s e r v e r ;

/� �

� @author b o n i f a c e
�/
public interface WeatherSubject {

public void addObserver ( WeatherObserver weatherObserver ) ;

public void removeObserver ( WeatherObserver weatherObserver ) ;

public void doNotify () ;


}

We’ll also create an interface for the observers called WeatherObserver. It features one
method, a doUpdate() method.
Design Patterns and Software Refactoring 115

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . o b s e r v e r ;

/� �

� @author b o n i f a c e
�/
public interface WeatherObserver {

public void doUpdate ( int temperature ) ;


}

The WeatherStation class implements WeatherSubject. It is our subject class. It main-


tains a set of WeatherObservers which are added via addObserver() and removed via
removeObserver(). When WeatherSubject’s state changes via setTemperature(), the
doNotify() method is called, which contacts all the WeatherObservers with the temper-
ature via their doUpdate() methods.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . o b s e r v e r ;

import java . util . HashSet ;


import java . util . Iterator ;
import java . util . Set ;

/� �

� @author b o n i f a c e
�/
public class WeatherStation implements WeatherSubject {

S e t <W e a t h e r O b s e r v e r > w e a t h e r O b s e r v e r s ;
int temperature ;

public WeatherStation ( int temperature ) {


w e a t h e r O b s e r v e r s = new H a s h S e t <W e a t h e r O b s e r v e r >() ;
this . temperature = temperature ;
}

@Override
public void a d d O b s e r v e r ( W e a t h e r O b s e r v e r w e a t h e r O b s e r v e r ) {
weatherObservers . add ( weatherObserver ) ;
}

@Override
public void r e m o v e O b s e r v e r ( W e a t h e r O b s e r v e r w e a t h e r O b s e r v e r ) {
weatherObservers . remove ( weatherObserver ) ;
}

@Override
public void d o N o t i f y () {
I t e r a t o r <W e a t h e r O b s e r v e r > i t = w e a t h e r O b s e r v e r s . i t e r a t o r ( ) ;
while ( it . h a s N e x t () ) {
W e a t h e r O b s e r v e r w e a t h e r O b s e r v e r = it . next () ;
weatherObserver . doUpdate ( temperature ) ;
}
}

public void s e t T e m p e r a t u r e ( i n t n e w T e m p e r a t u r e ) {
S y s t e m . o u t . p r i n t l n ( ” \ nWeather s t a t i o n s e t t i n g temperature to ” + n e w T e m p e r a t u r e ) ;
temperature = newTemperature ;
doNotify () ;
}
}

WeatherCustomer1 is an observer that implements WeatherObserver. Its doUpdate()


method gets the current temperature from the WeatherStation and displays it.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . o b s e r v e r ;

/� �

� @author b o n i f a c e
�/
public class WeatherCustomer1 implements WeatherObserver {

@Override
public void d o U p d a t e ( i n t t e m p e r a t u r e ) {
S y s t e m . o u t . p r i n t l n ( ” Weather c u s t o m e r 1 j u s t found out the temperature i s : ” + ←�
temperature ) ;
}
}
Design Patterns and Software Refactoring 116

WeatherCustomer2 performs similar functionality as WeatherCustomer1.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . o b s e r v e r ;

/� �

� @author b o n i f a c e
�/
public class WeatherCustomer2 implements WeatherObserver {

@Override
public void d o U p d a t e ( i n t t e m p e r a t u r e ) {
S y s t e m . o u t . p r i n t l n ( ” Weather c u s t o m e r 2 j u s t found out the temperature i s : ” + ←�
temperature ) ;
}
}

The MainDriver class demonstrates the observer pattern. It creates a WeatherStation


and then a WeatherCustomer1 and a WeatherCustomer2. The two customers are added
as observers to the weather station. Then the setTemperature() method of the weather
station is called. This changes the state of the weather station and the customers are
notified of this temperature update. Next, the WeatherCustomer1 object is removed
from the station’s collection of observers. Then, the setTemperature() method is called
again. This results in the notification of the WeatherCustomer2 object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . o b s e r v e r ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public s t a t i c void main ( String [ ] args ) {


WeatherStation w e a t h e r S t a t i o n = new W e a t h e r S t a t i o n ( 3 3 ) ;

W e a t h e r C u s t o m e r 1 w c 1 = new W e a t h e r C u s t o m e r 1 ( ) ;
W e a t h e r C u s t o m e r 2 w c 2 = new W e a t h e r C u s t o m e r 2 ( ) ;
weatherStation . addObserver ( wc1 ) ;
weatherStation . addObserver ( wc2 ) ;

weatherStation . setTemperature (34) ;

weatherStation . removeObserver ( wc1 ) ;

weatherStation . setTemperature (35) ;


}
}

Record output in your log book

In a more advanced case, we might have given each observer a reference to the weather
station object. This could allow the observer the ability to compare the state of the
subject in detail with its own state and make any necessary updates to its own state.

[Link] Strategy Pattern


Design Patterns and Software Refactoring 117

The strategy pattern is a behavioral object design pattern. In the strategy pattern, dif-
ferent algorithms are represented as Concrete Strategy classes, and they share a common
Strategy interface. A Context object contains a reference to a Strategy. By changing
the Context’s Strategy, different behaviors can be obtained. Although these behaviors
are different, the different strategies all operate on data from the Context.

The strategy pattern is one way that composition can be used as an alternative to sub-
classing. Rather than providing different behaviors via subclasses overriding methods
in superclasses, the strategy pattern allows different behaviors to be placed in Con-
crete Strategy classes which share the common Strategy interface. A Context class is
composed of a reference to a Strategy.

Here is an example of the strategy pattern. First, we’ll define a Strategy interface. It
declares a checkTemperature() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t r a t e g y ;

/� �

� @author b o n i f a c e
�/
public interface Strategy {
boolean c h e c k T e m p e r a t u r e ( i n t temperatureInF ) ;

The HikeStrategy class is a concrete strategy class that implements the Strategy in-
terface. The checkTemperature method is implemented so that if the temperature is
between 50 and 90, it returns true. Otherwise it returns false.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t r a t e g y ;

/� �

� @author b o n i f a c e
�/
public class HikeStrategy implements Strategy {

@Override
public boolean c h e c k T e m p e r a t u r e ( i n t t e m p e r a t u r e I n F ) {
i f ( ( t e m p e r a t u r e I n F >= 5 0 ) && ( t e m p e r a t u r e I n F <= 9 0 ) ) {
return true ;
} else {
return f a l s e ;
}
}
}

The SkiStrategy implements the Strategy interface. If the temperature is 32 or less, the
checkTemperature method returns true. Otherwise it returns false.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t r a t e g y ;

/� �

� @author b o n i f a c e
�/
public class SkiStrategy implements Strategy {

@Override
public boolean c h e c k T e m p e r a t u r e ( i n t temperatureInF ) {
i f ( t e m p e r a t u r e I n F <= 3 2 ) {
return true ;
} else {
return f a l s e ;
}
}
}
Design Patterns and Software Refactoring 118

The Context class contains a temperature and a reference to a Strategy. The Strategy
can be changed, resulting in different behavior that operates on the same data in the
Context. The result of this can be obtained from the Context via the getResult() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t r a t e g y ;

/� �

� @author b o n i f a c e
�/
public class Context {

int temperatureInF ;
Strategy strategy ;

public Context ( int temperatureInF , Strategy strategy ) {


this . temperatureInF = temperatureInF ;
this . strategy = strategy ;
}

public void s e t S t r a t e g y ( S t r a t e g y strategy ) {


this . strategy = strategy ;
}

public int getTemperatureInF () {


return temperatureInF ;
}

public boolean g e t R e s u l t () {
return strategy . checkTemperature ( temperatureInF ) ;
}
}

The MainDriver class creates a Context object with a temperature of 60 and with a
SkiStrategy. It displays the temperature from the context and whether that temperature
is OK for skiing. After that, it sets the Strategy in the Context to HikeStrategy. It then
displays the temperature from the context and whether that temperature is OK for
hiking.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t r a t e g y ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

int temperatureInF = 60;

S t r a t e g y s k i S t r a t e g y = new S k i S t r a t e g y ( ) ;
C o n t e x t c o n t e x t = new C o n t e x t ( t e m p e r a t u r e I n F , skiStrategy ) ;

System . out . println (” Is t h e t e m p e r a t u r e ( ” + c o n t e x t . g e t T e m p e r a t u r e I n F ( ) + ”F) good ←�


for skiing ? ” +
context . getResult () ) ;

S t r a t e g y h i k e S t r a t e g y = new H i k e S t r a t e g y ( ) ;
context . setStrategy ( hikeStrategy ) ;

System . out . println (” Is t h e t e m p e r a t u r e ( ” + c o n t e x t . g e t T e m p e r a t u r e I n F ( ) + ”F) good ←�


for hiking ? ” +
context . getResult () ) ;

}
}

Record output in your log book


Design Patterns and Software Refactoring 119

[Link] Command Pattern

The command pattern is a behavioral object design pattern. In the command pattern,
a Command interface declares a method for executing a particular action. Concrete
Command classes implement the execute() method of the Command interface, and this
execute() method invokes the appropriate action method of a Receiver class that the
Concrete Command class contains. The Receiver class performs a particular action. A
Client class is responsible for creating a Concrete Command and setting the Receiver of
the Concrete Command. An Invoker class contains a reference to a Command and has
a method to execute the Command.

In the command pattern, the invoker is decoupled from the action performed by the
receiver. The invoker has no knowledge of the receiver. The invoker invokes a command,
and the command executes the appropriate action of the receiver. Thus, the invoker
can invoke commands without knowing the details of the action to be performed. In
addition, this decoupling means that changes to the receiver’s action don’t directly affect
the invocation of the action.

The command pattern can be used to perform ’undo’ functionality. In this case, the
Command interface should include an unexecute() method.

Here is an example of the command pattern. We have a Command interface with an


execute() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
�/
public interface Command {

public void execute () ;


}

LunchCommand implements Command. It contains a reference to Lunch, a receiver.


Its execute() method invokes the appropriate action on the receiver.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
�/
Design Patterns and Software Refactoring 120

public class LunchCommand implements Command {

Lunch lunch ;

public LunchCommand ( Lunch lunch ) {


this . lunch = lunch ;
}

@Override
public void e x e c u t e () {
lunch . makeLunch () ;
}

The DinnerCommand is similar to LunchCommand. It contains a reference to Dinner,


a receiver. Its execute() method invokes the makeDinner() action of the Dinner object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
�/
public class DinnerCommand implements Command {

Dinner dinner ;

public DinnerCommand ( Dinner dinner ) {


this . dinner = dinner ;
}

@Override
public void e x e c u t e () {
dinner . makeDinner () ;
}
}

Lunch is a receiver.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
�/
public class Lunch {

public void m a k e L u n c h () {
S y s t e m . o u t . p r i n t l n ( ” Lunch i s b e i n g made” ) ;
}
}

Dinner is also a receiver.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
�/
public class Dinner {

public void m a k e D i n n e r () {
S y s t e m . o u t . p r i n t l n ( ” Dinner is b e i n g made” ) ;
}
}

MealInvoker is the invoker class. It contains a reference to the Command to invoke. Its
invoke() method calls the execute() method of the Command.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
Design Patterns and Software Refactoring 121

�/
public class MealInvoker {

Command command ;

public MealInvoker ( Command command ) {


this . command = command ;
}

public void s e t C o m m a n d ( C o m m a n d command ) {


this . command = command ;
}

public void i n v o k e () {
command . execute () ;
}
}

The MainDriver class demonstrates the command pattern. It instantiates a Lunch (re-
ceiver) object and creates a LunchCommand (concrete command) with the Lunch. The
LunchCommand is referenced by a Command interface reference. Next, we perform the
same procedure on the Dinner and DinnerCommand objects. After this, we create a
MealInvoker object with lunchCommand, and we call the invoke() method of mealIn-
voker. After this, we set mealInvoker’s command to dinnerCommand, and once again
call invoke() on mealInvoker.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . c o m m a n d ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {
public s t a t i c void main ( S t r i n g [ ] args ) {

L u n c h l u n c h = new L u n c h ( ) ; // r e c e i v e r
C o m m a n d l u n c h C o m m a n d = new L u n c h C o m m a n d ( l u n c h ) ; // c o n c r e t e command

D i n n e r d i n n e r = new D i n n e r ( ) ; // r e c e i v e r
C o m m a n d d i n n e r C o m m a n d = new D i n n e r C o m m a n d ( d i n n e r ) ; // c o n c r e t e command

M e a l I n v o k e r m e a l I n v o k e r = new M e a l I n v o k e r ( l u n c h C o m m a n d ) ; // i n v o k e r
mealInvoker . invoke () ;

mealInvoker . setCommand ( dinnerCommand ) ;


mealInvoker . invoke () ;

Record output in your log book

As you can see, the invoker invokes a command, but has no direct knowledge of the
action being performed by the receiver.

[Link] State Pattern


Design Patterns and Software Refactoring 122

The state pattern is a behavioral object design pattern. The idea behind the state
pattern is for an object to change its behavior depending on its state. In the state
pattern, we have a Context class, and this class has a State reference to a Concrete State
instance. The State interface declares particular methods that represent the behaviors of
a particular state. Concrete States implement these behaviors. By changing a Context’s
Concrete State, we change its behavior. In essence, in the state pattern, a class (the
Context) is supposed to behave like different classes depending on its state. The state
pattern avoids the use of switch and if statements to change behavior.

Let’s look at an example of the state pattern. First off, we’ll define the EmotionalState
interface. It declares two methods, sayHello() and sayGoodbye().

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t a t e ;

/� �

� @author b o n i f a c e
�/
public interface EmotionalState {

public String sayHello () ;

public String sayGoodbye () ;


}

The HappyState class is a Concrete State that implements sayHello() and sayGoodbye()
of EmotionalState. These messages are cheerful (representing a happy state).

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t a t e ;

/� �

� @author b o n i f a c e
�/
// C o n c r e t e S t a t e
public class HappyState implements EmotionalState {

@Override
public String sayGoodbye () {
r e t u r n ”Bye , f r i e n d ! ” ;
}

@Override
public String sayHello () {
return ” Hello , f r i e n d ! ” ;
}

The SadState class also implements the EmotionalState interface. The messages are sad
(representing a sad state).

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t a t e ;

/� �

� @author b o n i f a c e
�/
// C o n c r e t e S t a t e
public class SadState implements EmotionalState {

@Override
public String sayGoodbye () {
r e t u r n ” Bye . S n i f f , s n i f f . ” ;
}

@Override
public String sayHello () {
return ” Hello . Sniff , s n i f f . ” ;
}
}
Design Patterns and Software Refactoring 123

The Person class is the Context class. It contains an EmotionalState reference to a con-
crete state. In this example, we have Person implement the EmotionalState reference,
and we pass the calls to Person’s sayHello() and sayGoodbye() methods on to the corre-
sponding methods on the emotionalState reference. As a result of this, a Person object
behaves differently depending on the state of Person (ie, the current EmotionalState
reference).

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t a t e ;

/� �

� @author b o n i f a c e
�/
// C o n t e x t
public class Person implements EmotionalState {

EmotionalState emotionalState ;

public Person ( EmotionalState emotionalState ) {


this . emotionalState = emotionalState ;
}

public void s e t E m o t i o n a l S t a t e ( E m o t i o n a l S t a t e emotionalState ) {


this . emotionalState = emotionalState ;
}

@Override
public String sayGoodbye () {
return emotionalState . sayGoodbye () ;
}

@Override
public String sayHello () {
return emotionalState . sayHello () ;
}
}

The MainDriver class demonstrates the state pattern. First, it creates a Person object
with a HappyState object. We display the results of sayHello() and sayGoodbyte() when
the person object is in the happy state. Next, we change the person object’s state with
a SadState object. We display the results of sayHello() and sayGoodbyte(), and we see
that in the sad state, the person object’s behavior is different.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . s t a t e ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {
public s t a t i c void main ( S t r i n g [ ] args ) {

P e r s o n p e r s o n = new P e r s o n ( new H a p p y S t a t e ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ” H e l l o i n happy s t a t e : ” + p e r s o n . s a y H e l l o ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ” Goodbye i n happy s t a t e : ” + p e r s o n . s a y G o o d b y e ( ) ) ;

p e r s o n . s e t E m o t i o n a l S t a t e ( new S a d S t a t e ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ” H e l l o i n sad s t a t e : ” + p e r s o n . s a y H e l l o ( ) ) ;
S y s t e m . o u t . p r i n t l n ( ” Goodbye i n s a d s t a t e : ” + p e r s o n . s a y G o o d b y e ( ) ) ;

Record output in your log book

Note that we don’t necessarily need to have the Context (ie, Person) implement the
EmotionalState interface. The behavioral changes could have been internal to the Con-
text rather than exposing EmotionalState’s methods to the outside. However, having
the Context class implement the State interface allows us to directly access the different
behaviors that result from the different states of the Context.
Design Patterns and Software Refactoring 124

[Link] Visitor Pattern

The visitor pattern is a behavioral object design pattern. The visitor pattern is used
to simplify operations on groupings of related objects. These operations are performed
by the visitor rather than by placing this code in the classes being visited. Since the
operations are performed by the visitor rather than by the classes being visited, the
operation code gets centralized in the visitor rather than being spread out across the
grouping of objects, thus leading to code maintainability. The visitor pattern also avoids
the use of the instanceof operator in order to perform calculations on similar classes.

In the visitor pattern, we have a Visitor interface that declares visit() methods for
the various types of elements that can be visited. Concrete Visitors implement the
Visitor interface’s visit() methods. The visit() methods are the operations that should
be performed by the visitor on an element being visited.

The related classes that will be visited implement an Element interface that declares
an accept() method that takes a visitor as an argument. Concrete Elements implement
the Element interface and implement the accept() method. In the accept() method, the
visitor’s visit() method is called with ’this’, the current object of the Concrete Element
type.

The elements to visit all implement the accept() method that takes a visitor as an
argument. In this method, they call the visitor’s visit() method with ’this’. As a result
of this, an element takes a visitor and then the visitor performs its operation on the
element.

Let’s illustrate the visitor pattern with an example. First, we’ll define a NumberVisitor
interface. This interface declares three visit methods which take different types as ar-
guments. Note that if we only wrote one visit method, we’d have to use the instanceof
operator or a similar technique to handle the different element types. However, since
Design Patterns and Software Refactoring 125

we have separate visit methods, we don’t need the instanceof operator, since each visit
method handles a different type.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

import java . util . List ;

/� �

� @author b o n i f a c e
�/
public interface NumberVisitor {

public void visit ( TwoElement twoElement ) ;

public void visit ( ThreeElement threeElement ) ;

public void v i s i t ( L i s t <N u m b e r E l e m e n t > e l e m e n t L i s t ) ;


}

All of the elements classes to be visited will implement the NumberElement interface.
This interface has a single method that takes a NumberVisitor as an argument

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

/� �

� @author b o n i f a c e
�/
public interface NumberElement {

public void accept ( NumberVisitor visitor ) ;


}

Let’s create a TwoElement class that implements NumberElement. It has two int fields.
Its accept() method calls the visitor’s visit() method with ’this’. The operator to be
performed on TwoElement is performed by the visitor.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

/� �

� @author b o n i f a c e
�/
public class TwoElement implements NumberElement{

int a;
int b;

public TwoElement ( int a , int b) {


this . a = a ;
this . b = b ;
}

@Override
public void a c c e p t ( N u m b e r V i s i t o r visitor ) {
visitor . visit ( this ) ;
}
}

The ThreeElement class is similar to TwoElement, except that it has three int fields.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

/� �

� @author b o n i f a c e
�/
public class ThreeElement implements NumberElement {

int a;
int b;
int c;

public ThreeElement ( int a , int b , int c) {


this . a = a ;
this . b = b ;
Design Patterns and Software Refactoring 126

this . c = c ;
}

@Override
public void a c c e p t ( N u m b e r V i s i t o r visitor ) {
visitor . visit ( this ) ;
}
}

Now, let’s create a visitor called SumVisitor that implements the NumberVisitor inter-
face. For TwoElement and ThreeElement objects, this visitor will sum up the int fields.
For a List of NumElements (ie, TwoElement and ThreeElement objects), this visitor
will iterate over the elements and call their accept() methods. As a result of this, the
visitor will perform visit operations on all the TwoElement and ThreeElement objects
that make up the list, since the call to accept() in turn calls the visitor’s visit methods
for the TwoElement and ThreeElement objects.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

import java . util . List ;

/� �

� @author b o n i f a c e
�/
public class SumVisitor implements NumberVisitor {

@Override
public void vi sit ( T w o E l e m e n t t w o E l e m e n t ) {
int sum = twoElement . a + twoElement . b ;
S y s t e m . o u t . p r i n t l n ( t w o E l e m e n t . a + ”+” + t w o E l e m e n t . b + ”=” + s u m ) ;
}

@Override
public void vi sit ( T h r e e E l e m e n t t h r e e E l e m e n t ) {
int sum = threeElement . a + threeElement . b + threeElement . c ;
S y s t e m . o u t . p r i n t l n ( t h r e e E l e m e n t . a + ”+” + t h r e e E l e m e n t . b + ”+” + t h r e e E l e m e n t . c + ”=←�
” + sum ) ;
}

@Override
p u b l i c v o i d v i s i t ( L i s t <N u m b e r E l e m e n t > e l e m e n t L i s t ) {
f o r ( N u m b e r E l e m e n t ne : e l e m e n t L i s t ) {
ne . accept ( t h i s ) ;
}
}
}

Here is another visitor, TotalSumVisitor. In addition to summing up the int fields and
displaying the sum, this visitor will keep track of the total sums of all the elements that
are visited.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

import java . util . List ;

/� �

� @author b o n i f a c e
�/
public class TotalSumVisitor implements NumberVisitor {

int totalSum = 0;

@Override
public void vi sit ( T w o E l e m e n t t w o E l e m e n t ) {
int sum = twoElement . a + twoElement . b ;
S y s t e m . o u t . p r i n t l n ( ” Adding ” + t w o E l e m e n t . a + ”+” + t w o E l e m e n t . b + ”=” + s u m + ” t o ←�
total ”) ;
t o t a l S u m += s u m ;
}

@Override
public void vi sit ( T h r e e E l e m e n t t h r e e E l e m e n t ) {
int sum = threeElement . a + threeElement . b + threeElement . c ;
S y s t e m . o u t . p r i n t l n ( ” Adding ” + t h r e e E l e m e n t . a + ”+” + t h r e e E l e m e n t . b + ”+” + ←�
t h r e e E l e m e n t . c + ”=” + s u m
+ ” to t o t a l ” ) ;
Design Patterns and Software Refactoring 127

t o t a l S u m += s u m ;
}

@Override
p u b l i c v o i d v i s i t ( L i s t <N u m b e r E l e m e n t > e l e m e n t L i s t ) {
f o r ( N u m b e r E l e m e n t ne : e l e m e n t L i s t ) {
ne . accept ( t h i s ) ;
}
}

public int getTotalSum () {


return totalSum ;
}

Let’s see the visitor pattern in action. The MainDriver class creates two TwoElement
objects and one ThreeElement object. It creates a list of NumberElements and adds the
TwoElement object and the ThreeElement object to the list. Next, we create a SumVis-
itor and we visit the list with the SumVisitor. After this, we create a TotalSumVisitor
and visit the list with the TotalSumVisitor. We display the total sum via the call to
TotalSumVisitor’s getTotalSum() method.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . v i s i t o r ;

import java . util . ArrayList ;


import java . util . List ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {
public s t a t i c void main ( S t r i n g [ ] args ) {

T w o E l e m e n t t w o 1 = new T w o E l e m e n t ( 3 , 3 ) ;
T w o E l e m e n t t w o 2 = new T w o E l e m e n t ( 2 , 7 ) ;
T h r e e E l e m e n t t h r e e 1 = new T h r e e E l e m e n t ( 3 , 4 , 5) ;

L i s t <N u m b e r E l e m e n t > n u m b e r E l e m e n t s = new A r r a y L i s t <N u m b e r E l e m e n t >() ;


numberElements . add ( two1 ) ;
numberElements . add ( two2 ) ;
numberElements . add ( three1 ) ;

S y s t e m . o u t . p r i n t l n ( ” V i s i t i n g element l i s t with SumVisitor ” ) ;


N u m b e r V i s i t o r s u m V i s i t o r = new S u m V i s i t o r ( ) ;
sumVisitor . visit ( numberElements ) ;

S y s t e m . o u t . p r i n t l n ( ”\ n V i s i t i n g element l i s t with TotalSumVisitor ” ) ;


T o t a l S u m V i s i t o r t o t a l S u m V i s i t o r = new T o t a l S u m V i s i t o r ( ) ;
totalSumVisitor . visit ( numberElements ) ;
S y s t e m . o u t . p r i n t l n ( ” T o t a l sum : ” + t o t a l S u m V i s i t o r . g e t T o t a l S u m ( ) ) ;
}
}

Record output in your log book

Notice that if we’d like to perform new operations on the grouping of elements, all we
would need to do is write a new visitor class. We would not have to make any additions
to the existing element classes, since they provide the data but none of the code for the
operations.
Design Patterns and Software Refactoring 128

[Link] Iterator Pattern

The iterator pattern is a behavioral object design pattern. The iterator pattern allows for
the traversal through the elements in a grouping of objects via a standardized interface.
An Iterator interface defines the actions that can be performed. These actions include
being able to traverse the objects and also obtain the objects.

Java features the widely used [Link] interface which is used to iterate through
things such as Java collections. We can write our own iterator by implementing [Link].
This interface features the hasNext(), next(), and remove() methods. When writing an
iterator for a class, it is very common for the iterator class to be an inner class of the
class that we’d like to iterate through.

Let’s look at an example of this. We have an Item class, which represents an item on a
menu. An item has a name and a price.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . i t e r a t o r ;

/� �

� @author b o n i f a c e
�/
public class Item {

String name ;
float price ;

public Item ( String name , float price ) {


this . name = name ;
this . price = price ;
}

public String toString () {


r e t u r n n a m e + ” : \�” + p r i c e ;
}
}

Here is the Menu class. It has a list of menu items of type Item. Items can be added via
the addItem() method. The iterator() method returns an iterator of menu items. The
MenuIterator class is an inner class of Menu that implements the Iterator interface for
Item objects. It contains basic implementations of the hasNext(), next(), and remove()
methods.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . i t e r a t o r ;
Design Patterns and Software Refactoring 129

import java . util . ArrayList ;


import java . util . Iterator ;
import java . util . List ;

/� �

� @author b o n i f a c e
�/
public class Menu {

L i s t <I t e m > m e n u I t e m s ;

public Menu () {
m e n u I t e m s = new A r r a y L i s t <I t e m >() ;
}

public void a d d I t e m ( Item item ) {


menuItems . add ( item ) ;
}

p u b l i c I t e r a t o r <I t e m > i t e r a t o r ( ) {
r e t u r n new M e n u I t e r a t o r ( ) ;
}

c l a s s M e n u I t e r a t o r implements I t e r a t o r <I t e m > {


int currentIndex = 0;

@Override
public boolean h a s N e x t () {
i f ( c u r r e n t I n d e x >= m e n u I t e m s . s i z e ( ) ) {
return f a l s e ;
} else {
return true ;
}
}

@Override
public Item next () {
r e t u r n m e n u I t e m s . g e t ( c u r r e n t I n d e x ++) ;
}

@Override
public void r e m o v e () {
m e n u I t e m s . r e m o v e (−− c u r r e n t I n d e x ) ;
}

The MainDriver class demonstrates the iterator pattern. It creates three items and
adds them to the menu object. Next, it gets an Item iterator from the menu object and
iterates over the items in the menu. After this, it calls remove() to remove the last item
obtained by the iterator. Following this, it gets a new iterator object from the menu
and once again iterates over the menu items.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . i t e r a t o r ;

import java . util . Iterator ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

Item i 1 = new I t e m ( ” s p a g h e t t i ” , 7 . 5 0 f ) ;
Item i 2 = new I t e m ( ” hamburger ” , 6 . 0 0 f ) ;
Item i 3 = new I t e m ( ” c h i c k e n s a n d w i c h ” , 6 . 5 0 f ) ;

M e n u m e n u = new M e n u ( ) ;
menu . a d d I t e m ( i1 ) ;
menu . a d d I t e m ( i2 ) ;
menu . a d d I t e m ( i3 ) ;

S y s t e m . o u t . p r i n t l n ( ” D i s p l a y i n g Menu : ” ) ;
I t e r a t o r <I t e m > i t e r a t o r = m e n u . i t e r a t o r ( ) ;
while ( iterator . hasNext () ) {
Item item = iterator . next () ;
System . out . println ( item ) ;
}

S y s t e m . o u t . p r i n t l n ( ” \ nRemoving l a s t item r e t u r n e d ” ) ;
iterator . remove () ;

S y s t e m . o u t . p r i n t l n ( ” \ n D i s p l a y i n g Menu : ” ) ;
Design Patterns and Software Refactoring 130

iterator = menu . iterator () ;


while ( iterator . hasNext () ) {
Item item = iterator . next () ;
System . out . println ( item ) ;
}

}
}

Record output in your log book

Note that since the menu utilizes a Java collection, we could have used an iterator
obtained for the menu list rather than write our own iterator as an inner class.

[Link] Memento Pattern

The memento pattern is a behavioral design pattern. The memento pattern is used to
store an object’s state so that this state can be restored at a later point. The saved
state data in the memento object is not accessible outside of the object to be saved and
restored. This protects the integrity of the saved state data.

In this pattern, an Originator class represents the object whose state we would like
to save. A Memento class represents an object to store the state of the Originator.
The Memento class is typically a private inner class of the Originator. As a result,
the Originator has access to the fields of the memento, but outside classes do not have
access to these fields. This means that state information can be transferred between
the Memento and the Originator within the Originator class, but outside classes do not
have access to the state data stored in the Memento.

The memento pattern also utilizes a Caretaker class. This is the object that is responsible
for storing and restoring the Originator’s state via a Memento object. Since the Memento
is a private inner class, the Memento class type is not visible to the Caretaker. As a
result, the Memento object needs to be stored as an Object within the Caretaker.

Now, let’s look at an example. The DietInfo class is our Originator class. We’d like to
be able to save and restore its state. It contains 3 fields: a dieter name field, the day
number of the diet, and the weight of the dieter on the specified day of the diet.

This class contains a private inner class called Memento. This is our Memento class that
is used to save the state of DietInfo. Memento has 3 fields representing the dieter name,
the day number, and the weight of the dieter.
Design Patterns and Software Refactoring 131

Notice the save() method of DietInfo. This creates and returns a Memento object. This
returned Memento object gets stored by the caretaker. Note that [Link] is
not visible, so the caretaker can’t reference [Link]. Instead, it stores the
reference as an Object.

The restore() method of DietInfo is used to restore the state of the DietInfo. The
caretaker passes in the Memento (as an Object). The memento is cast to a Memento
object and then the DietInfo object’s state is restored by copying over the values from
the memento.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e m e n t o ;

/� �

� @author b o n i f a c e
�/
// o r i g i n a t o r − o b j e c t whose s t a t e we want t o s a v e
public class DietInfo {

String personName ;
int dayNumber ;
int weight ;

public DietInfo ( String personName , int dayNumber , int weight ) {


this . personName = personName ;
this . dayNumber = dayNumber ;
this . weight = weight ;
}

public String toString () {


r e t u r n ”Name : ” + p e r s o n N a m e + ” , day number : ” + d a y N u m b e r + ” , w e i g h t : ” + w e i g h t ;
}

public void s e t D a y N u m b e r A n d W e i g h t ( i n t dayNumber , int weight ) {


this . dayNumber = dayNumber ;
this . weight = weight ;
}

public Memento save () {


r e t u r n new M e m e n t o ( p e r s o n N a m e , dayNumber , weight ) ;
}

public void r e s t o r e ( O b j e c t o b j M e m e n t o ) {
Memento memento = ( Memento ) objMemento ;
personName = memento . mementoPersonName ;
dayNumber = memento . mementoDayNumber ;
weight = memento . mementoWeight ;
}

// memento − o b j e c t t h a t s t o r e s the saved state of the originator


private class Memento {
String mementoPersonName ;
int mementoDayNumber ;
int mementoWeight ;

public Memento ( String personName , int dayNumber , int weight ) {


mementoPersonName = personName ;
mementoDayNumber = dayNumber ;
mementoWeight = weight ;
}
}
}

DietInfoCaretaker is the caretaker class that is used to store the state (ie, the memento)
of a DietInfo object (ie, the originator). The memento is stored as an object since
[Link] is not visible to the caretaker. This protects the integrity of the data
stored in the Memento object. The caretaker’s saveState() method saves the state of the
DietInfo object. The caretaker’s restoreState() method restores the state of the DietInfo
object.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e m e n t o ;

/� �

� @author b o n i f a c e
�/
// c a r e t a k e r − s a v e s and r e s t o r e s a D i e t I n f o object � s s t a t e v i a a memento
Design Patterns and Software Refactoring 132

// n o t e t h a t D i e t I n f o . Memento i s n � t v i s i b l e t o t h e c a r e t a k e r s o we need t o c a s t t h e memento ←�


to Object
public class DietInfoCaretaker {

Object objMemento ;

public void s a v e S t a t e ( D i e t I n f o d i e t I n f o ) {
objMemento = dietInfo . save () ;
}

public void r e s t o r e S t a t e ( D i e t I n f o dietInfo ) {


dietInfo . restore ( objMemento ) ;
}
}

The MainDriver class demonstrates the memento pattern. It creates a caretaker and then
a DietInfo object. The DietInfo object’s state is changed and displayed. At one point,
the caretaker saves the state of the DietInfo object. After this, the DietInfo object’s
state is further changed and displayed. After this, the caretaker restores the state of the
DietInfo object. We verify this restoration by displaying the DietInfo object’s state.

package za . ac . c p u t . k a b a s o b . d e s i g n p a t t e r n s . b e h a v i o r a l . m e m e n t o ;

/� �

� @author b o n i f a c e
�/
public class MainDriver {

public static void main ( String [ ] args ) {

// c a r e t a k e r
DietInfoCaretaker d i e t I n f o C a r e t a k e r = new D i e t I n f o C a r e t a k e r ( ) ;

// o r i g i n a t o r
D i e t I n f o d i e t I n f o = new D i e t I n f o ( ” Fred ” , 1 , 1 0 0 ) ;
System . out . println ( dietInfo ) ;

dietInfo . setDayNumberAndWeight (2 , 99) ;


System . out . println ( dietInfo ) ;

S y s t e m . out . p r i n t l n ( ” Saving s t a t e . ” ) ;
dietInfoCaretaker . saveState ( dietInfo ) ;

dietInfo . setDayNumberAndWeight (3 , 98) ;


System . out . println ( dietInfo ) ;

dietInfo . setDayNumberAndWeight (4 , 97) ;


System . out . println ( dietInfo ) ;

S y s t e m . out . p r i n t l n ( ” Restoring saved s t a t e . ” ) ;


dietInfoCaretaker . restoreState ( dietInfo ) ;
System . out . println ( dietInfo ) ;

}
}

Record output in your log book

Notice how the state changes, and how we are able to save and restore the state of the
originator via the caretaker’s reference to the memento.

[Link] Interpreter Pattern

This one has been left for you to do as an exercise.


Design Patterns and Software Refactoring 133

7.8 Chapter Exercises

This exercise has two parts.

Part 1

The First part requires you to read and master 6 design patterns, two from each category.
Write a small write up on the practical usage of the patterns you have chosen. Your
solution should follow the pattern below.

1. Pattern Name and Classification

� Creational
� Structural
� Behavioural

2. Intent Also Known As Motivation and Applicability

3. Structure and Participants

4. Collaborations

5. Consequences

6. Implementation

7. Sample Code

8. Known Uses

9. Related Patterns

Part 2

Re-Write the Design Patterns in Section, but use JUnit Tests in place of the Driver class
used in the examples. Also write code to demostrate the usage of the Interpreter Design
Pattern.

You might also like