3. Introduction Summary References
INTRODUCTION
When faced with a new problem, where do you look for
inspiration?
Most people look to solutions of previous problems that
have similar characteristics.
This insight is what is behind design patterns; collections
of proven ways to structure the relationships between
objects in the pursuit of a given objective.
4. Introduction Summary References
INSPIRATION
Design patterns speed the process of finding a solution, by
eliminating the need to reinvent well-known and proven
solutions.
Just as important, design patterns provide a vocabulary
with which to discuss the space of possible design choices.
This vocabulary is termed a pattern language.
5. Introduction Summary References
TYPES OF DESIGN PATTERNS
Creational: Patterns provide instantiation mechanisms,
making it easier to create objects in a way that suits the
situation.
Structural: Patterns generally deal with relationships
between entities, making it easier for these entities to work
together.
Behavioral: Patterns are used in communications
between entities and make it easier and more flexible for
these entities to communicate.
6. Introduction Summary References
BENEFITS OF USING DESIGN PATTERNS
Analogy from civil engineering.
Question: What will a civil engineer do when confronted
with a problem to cross a river?
Answer: Build a tunnel or a bridge.
Question: How about preventing rain from entering a
window?
Answer: Build a canopy.
They give the developer a selection of tried and tested
solutions to work with.
They are language neutral and so can be applied to any
language that supports object-orientation.
They aid communication by the very fact that they are well
documented and can be researched if that is not the case.
They have a proven track record as they are already widely
used and thus reduce the technical risk to the project.
They are highly flexible and can be used in practically any
7. Introduction Summary References
RELATIONSHIP TO DEPENDENCY AND VISIBILITY
Many patterns are involved with the concepts of
dependency we introduced in the previous chapter.
Determining where strong dependencies are necessary,
and how to weaken dependencies whenever possible.
8. Introduction Summary References
A SIMPLE EXAMPLE, THE ADAPTER
An adaptor is used to connect a client (an object that
needs a service) with a server (an object that provides the
service).
The client requires a certain interface, and while the server
provides the necessary functionality, it does not support
the interface.
The adapter changes the interface, without actually doing
the work.
9. Introduction Summary References
AN EXAMPLE ADAPTER
EXAMPLE
class MyCollection implements Collection {
public boolean isEmpty ( )
{ return data . count ( ) == 0; }
public int size ( )
{ return data . count ( ) ; }
public void addElement ( Object newElement )
{ data . add ( newElement ) ; }
public boolean containsElement ( Object t e s t )
{ return data . f i n d ( t e s t ) != n u l l ; }
public Object findElement ( Object t e s t )
{ return data . f i n d ( t e s t ) ; }
private DataBox data = new DataBox ( ) ;
}
Example
DataBox is some collection that does not support the
Collection interface.
Adapters are often needed to connect software from
10. Introduction Summary References
DESCRIBING PATTERNS
Patterns themselves have developed their own vocabulary for
description:
NAME: Contributes to the pattern vocabulary.
SYNOPSIS: Short description of the problem the pattern will
solve.
FORCES: Requirements, considerations, or necessary
conditions
SOLUTION: The essense of the solution
COUNTERFORCES: Reasons for not using the pattern.
RELATED PATTERNS: Possible alternatives in the design.
11. Introduction Summary References
EXAMPLE PATTERNS
We will briefly examine a number of common patterns:
Iterator.
Software Factory.
Strategy.
Singleton.
Composite.
Decorator.
Double-Dispatch.
Flyweight.
Proxy.
Facade.
Observer.
12. Introduction Summary References
ITERATOR
Problem: How do you provide a client access to elements
in a collection, without exposing the structure of the
collection.
Solution: Allow clients to manipulate an object that can
return the current value and move to the next element in
the collection.
Example, Enumerators in Java.
EXAMPLE
interface Enumerator {
public boolean hasMoreElements ( ) ;
public Object nextElement ( ) ;
}
Enumeator e = . . . ;
while ( e . hasMoreElements ) {
Object val = e . nextElement ( ) ;
. . .
}
13. Introduction Summary References
SOFTWARE FACTORY
INTRODUCTION
Problem: How do you simplify the manipulation of many
different implementations of the same interface (i.e.,
iterators).
Solution: Hide creation within a method, have the method
declare a return type that is more general than its actual
return type.
EXAMPLE
class SortedList {
. . .
Enumerator elements ( ) { return new SortedListEnumerator ( ) ; }
. . .
private class SortedListEnumerator implements Enumerator {
. . .
}
}
14. Introduction Summary References
SOFTWARE FACTORY
The method is the “factory” in the name. Users don’t need
to know the exact type the factory returns, only the
declared type.
The factory could even return different types, depending
upon circumstances.
17. Introduction Summary References
SOFTWARE FACTORY
STEP 2: CREATE CONCRETE CLASSES IMPLEMENTING THE SAME INTERFACE.
RECTANGLE
public class Rectangle implements Shape {
@Override
public void draw ( ) {
System . out . p r i n t l n ( " Inside Rectangle : : draw ( ) method . " ) ;
}
}
SQUARE
public class Square implements Shape {
@Override
public void draw ( ) {
System . out . p r i n t l n ( " Inside Square : : draw ( ) method . " ) ;
}
}
18. Introduction Summary References
SOFTWARE FACTORY
CIRCLE
public class Circle implements Shape {
@Override
public void draw ( ) {
System . out . p r i n t l n ( " Inside Circle : : draw ( ) method . " ) ;
}
}
19. Introduction Summary References
SOFTWARE FACTORY
STEP 3: CREATE A FACTORY TO GENERATE OBJECT OF CONCRETE CLASS BASED ON GIVEN
INFORMATION.
SHAPEFACTORY
public class ShapeFactory {
/ / use getShape method to get object of type shape
public Shape getShape ( String shapeType ) {
i f ( shapeType == null ) {
return null ;
}
i f ( shapeType . equalsIgnoreCase ( "CIRCLE" ) ) {
return new Circle ( ) ;
} else i f ( shapeType . equalsIgnoreCase ( "RECTANGLE" ) ) {
return new Rectangle ( ) ;
} else i f ( shapeType . equalsIgnoreCase ( "SQUARE" ) ) {
return new Square ( ) ;
}
return null ;
}
}
20. Introduction Summary References
SOFTWARE FACTORY
STEP 4: USE THE FACTORY TO GET OBJECT OF CONCRETE CLASS BY PASSING AN
INFORMATION SUCH AS TYPE.
FACTORY PATTERN DEMO
public class FactoryPatternDemo {
public static void main ( String [ ] args ) {
ShapeFactory shapeFactory = new ShapeFactory ( ) ;
/ / get an object of Circle and c a l l i t s draw method .
Shape shape1 = shapeFactory . getShape ( "CIRCLE" ) ;
/ / c a l l draw method of Circle
shape1 . draw ( ) ;
/ / get an object of Rectangle and c a l l i t s draw method .
Shape shape2 = shapeFactory . getShape ( "RECTANGLE" ) ;
/ / c a l l draw method of Rectangle
shape2 . draw ( ) ;
/ / get an object of Square and c a l l i t s draw method .
Shape shape3 = shapeFactory . getShape ( "SQUARE" ) ;
/ / c a l l draw method of c i r c l e
shape3 . draw ( ) ;
}
}
22. Introduction Summary References
STRATEGY
Problem: Allow the client the choice of many alternatives,
but each is complex, and you don’t want to include code for
all.
Solution: Make many implementations of the same
interface, and allow the client to select one and give it back
to you.
Example: The layout managers in the AWT.
Several different layout managers are implemented, and
the designer selects and creates one.
Gives the designer flexibility, keeps the code size down.
25. Introduction Summary References
STRATEGY
STEP 2: CREATE CONCRETE CLASSES IMPLEMENTING THE SAME INTERFACE.
OPERATION ADD
public class OperationAdd implements Strategy {
@Override
public int doOperation ( int num1, int num2) {
return num1 + num2;
}
}
OPERATION SUBTRACT
public class OperationSubstract implements Strategy {
@Override
public int doOperation ( int num1, int num2) {
return num1 − num2;
}
}
27. Introduction Summary References
STRATEGY
STEP 3: CREATE CONTEXT CLASS.
CONTEXT
public class Context {
private Strategy strategy ;
public Context ( Strategy strategy ) {
this . strategy = strategy ;
}
public int executeStrategy ( int num1, int num2 ) {
return strategy . doOperation (num1, num2 ) ;
}
}
28. Introduction Summary References
STRATEGY
STEP 4: USE THE CONTEXT TO SEE CHANGE IN BEHAVIOUR WHEN IT CHANGES ITS
STRATEGY.
STRATEGY PATTERN DEMO
public class StrategyPatternDemo {
public static void main ( String [ ] args ) {
Context context = new Context (new OperationAdd ( ) ) ;
System . out . p r i n t l n ( " 10 + 5 = " + context . executeStrategy (10 , 5 ) ) ;
context = new Context (new OperationSubstract ( ) ) ;
System . out . p r i n t l n ( " 10 − 5 = " + context . executeStrategy (10 , 5 ) ) ;
context = new Context (new OperationMultiply ( ) ) ;
System . out . p r i n t l n ( " 10 ∗ 5 = " + context . executeStrategy (10 , 5 ) ) ;
}
}
30. Introduction Summary References
SINGLETON
Problem: You want to ensure that there is never more than
one instace of a given class.
Solution: Make the constructor private, have a method that
returns just one instance, which is held inside the class
itself.
EXAMPLE
class SingletonClass {
public :
static SingletonClass ∗ oneAndOnly ( ) { return theOne ; }
private :
static SingletonClass ∗ theOne ;
SingletonClass ( ) { . . . }
} ;
/ / s t a t i c i n i t i a l i z a t i o n
SingletonClass ∗ SingletonClass : : theOne = new SingletonClass ( ) ;
31. Introduction Summary References
COMPOSITE
Problem: How do you facilitate creation of complex
systems from simple parts?
Solution: Provide a few simple components, and a system
to compose components (simple or otherwise) into new
components.
Regular expressions are an example, are type systems, or
the nesting of panels within panels in the Java AWT API.
33. Introduction Summary References
COMPOSITE
STEP 1: CREATE EMPLOYEE CLASS HAVING LIST OF EMPLOYEE OBJECTS.
EMPLOYEE
import java . u t i l . ArrayList ;
import java . u t i l . L i s t ;
public class Employee {
private String name;
private String dept ;
private int salary ;
private List <Employee> subordinates ;
/ / constructor
public Employee ( String name, String dept , int sal ) {
this .name = name;
this . dept = dept ;
this . salary = sal ;
subordinates = new ArrayList <Employee > ( ) ;
}
public void add ( Employee e ) {
subordinates . add ( e ) ;
}
public void remove ( Employee e ) {
subordinates . remove ( e ) ;
}
public List <Employee> getSubordinates ( ) {
34. Introduction Summary References
COMPOSITE
STEP 2: USE THE EMPLOYEE CLASS TO CREATE AND PRINT EMPLOYEE HIERARCHY.
COMPOSITE PATTERN DEMO
public class CompositePatternDemo {
public static void main ( String [ ] args ) {
Employee CEO = new Employee ( " John " , "CEO" , 30000);
Employee headSales = new Employee ( " Robert " , "Head Sales " , 20000);
Employee headMarketing = new Employee ( " Michel " , "Head Marketing " , 20000);
Employee clerk1 = new Employee ( " Laura " , " Marketing " , 10000);
Employee clerk2 = new Employee ( "Bob" , " Marketing " , 10000);
Employee salesExecutive1 = new Employee ( " Richard " , " Sales " , 10000);
Employee salesExecutive2 = new Employee ( "Rob" , " Sales " , 10000);
CEO. add ( headSales ) ;
CEO. add ( headMarketing ) ;
headSales . add ( salesExecutive1 ) ;
headSales . add ( salesExecutive2 ) ;
headMarketing . add ( clerk1 ) ;
headMarketing . add ( clerk2 ) ;
/ / p r i n t a l l employees of the organization
System . out . p r i n t l n (CEO) ;
35. Introduction Summary References
DECORATOR I
Filter, wrapper.
Problem: Allow functionally to be layered around an
abstraction, but still dynamically changeable.
Solution: Combine inheritance and composition.
By making an object that both subclasses from another
class and holds an instance of the class, can add new
behaviour while referring all other behaviour to the original
class.
Example Input Streams in the Java I/O System.
36. Introduction Summary References
DECORATOR II
EXAMPLE
/ / a buffered input stream is−an input stream
class BufferedInputStream extends InputStream {
public BufferedInputStream ( InputStream s ) { data = s ; }
. . .
/ / and a buffered input stream has−an input stream
private InputStream data ;
}
An instance of BufferedInputStream can wrap around any other
type of InputStream, and simply adds a little bit new
functionality.
37. Introduction Summary References
DOUBLE DISPATCH (MULTIPLE POLYMORPHISM) I
Problem: You have variation in two or more polymorphic
variables.
Solution: Make each a receiver in turn, each message ties
down one source of variation.
Example, suppose we have a hierarchy of Shapes
(Triangle, Square) and Device (Printer, Terminal).
Two variables, one a Shape and one a Device.
First, pass a message to the device, passing the shape as
argument:
38. Introduction Summary References
DOUBLE DISPATCH (MULTIPLE POLYMORPHISM) II
EXAMPLE
Shape aShape = . . . ;
Device aDevice = . . . ;
aDevice . display ( aShape ) ;
function P r i n t e r . display ( Shape aShape )
begin
aShape . displayOnPrinter ( s e l f ) ;
end ;
function Terminal . display ( Shape aShape )
begin
aShape . displayOnTerminal ( s e l f ) ;
end ;
One message fixes the device, but how to fix the shape?
Each subclass of Shape must implement methods for each
output device:
39. Introduction Summary References
DOUBLE DISPATCH (MULTIPLE POLYMORPHISM) III
EXAMPLE
class Triangle : public Shape {
public :
Triangle ( Point , Point , Point ) ;
/ / . . .
v i r t u a l void displayOnPrinter ( P r i n t e r ) ;
v i r t u a l void displayOnTerminal ( Terminal ) ;
/ / . . .
private :
Point p1 , p2 , p3 ;
} ;
void Triangle . displayOnPrinter ( P r i n t e r p ) {
/ / p r i n t e r−s p e c i f i c code to
/ / display t r i a n g l e
/ / . . .
}
void Triangle . displayOnTerminal ( Terminal t ) {
/ / terminal−s p e c i f i c code to
/ / display t r i a n g l e
/ / . . .
}
40. Introduction Summary References
PROXY
Problem: How to hide unimportant communication details,
such as a network, from the client.
Solution: A proxy uses the interface that the client expects,
but passes messages over the network to the server, gets
back the response, and passes it to the client.
The client is therefore hidden from the network details.
FIGURE: Proxy
Similar in some ways to adaptor, but here the intermediary and
the server can have the same interface.
43. Introduction Summary References
PROXY
STEP 2: CREATE CONCRETE CLASSES IMPLEMENTING THE SAME INTERFACE.
REAL IMAGE
public class RealImage implements Image {
private String fileName ;
public RealImage ( String fileName ) {
this . fileName = fileName ;
loadFromDisk ( fileName ) ;
}
@Override
public void display ( ) {
System . out . p r i n t l n ( " Displaying " + fileName ) ;
}
private void loadFromDisk ( String fileName ) {
System . out . p r i n t l n ( " Loading " + fileName ) ;
}
}
44. Introduction Summary References
PROXY
PROXY IMAGE
public class ProxyImage implements Image {
private RealImage realImage ;
private String fileName ;
public ProxyImage ( String fileName ) {
this . fileName = fileName ;
}
@Override
public void display ( ) {
i f ( realImage == null ) {
realImage = new RealImage ( fileName ) ;
}
realImage . display ( ) ;
}
}
45. Introduction Summary References
PROXY
STEP 3: USE THE PROXYIMAGE TO GET OBJECT OF REALIMAGE CLASS WHEN REQUIRED.
PROXY PATTERN DEMO
public class ProxyPatternDemo {
public static void main ( String [ ] args ) {
Image image = new ProxyImage ( " test_10mb . jpg " ) ;
/ / image w i l l be loaded from disk
image . display ( ) ;
System . out . p r i n t l n ( " " ) ;
/ / image w i l l not be loaded from disk
image . display ( ) ;
}
}
47. Introduction Summary References
FACADE
Problem: Actual work is performed by two or more objects,
but you want to hide this level of complexity from the client.
Solution: Create a facade object that receives the
messages, but passes commands on to the workers for
completion.
FIGURE: Facade
Also similar to adapter and proxy.
50. Introduction Summary References
FACADE
STEP 2: CREATE CONCRETE CLASSES IMPLEMENTING THE SAME INTERFACE.
RECTANGLE
public class Rectangle implements Shape {
@Override
public void draw ( ) {
System . out . p r i n t l n ( " Inside Rectangle : : draw ( ) method . " ) ;
}
}
SQUARE
public class Square implements Shape {
@Override
public void draw ( ) {
System . out . p r i n t l n ( " Inside Square : : draw ( ) method . " ) ;
}
}
52. Introduction Summary References
FACADE
STEP 3: CREATE A FACADE CLASS.
SHAPE MAKER
public class ShapeMaker {
private Shape c i r c l e ;
private Shape rectangle ;
private Shape square ;
public ShapeMaker ( ) {
c i r c l e = new Circle ( ) ;
rectangle = new Rectangle ( ) ;
square = new Square ( ) ;
}
public void drawCircle ( ) {
c i r c l e . draw ( ) ;
}
public void drawRectangle ( ) {
rectangle . draw ( ) ;
}
public void drawSquare ( ) {
square . draw ( ) ;
}
}
53. Introduction Summary References
FACADE
STEP 4: USE THE FACADE TO DRAW VARIOUS TYPES OF SHAPES.
FACADE PATTERN DEMO
public class FacadePatternDemo {
public static void main ( String [ ] args ) {
ShapeMaker shapeMaker = new ShapeMaker ( ) ;
shapeMaker . drawCircle ( ) ;
shapeMaker . drawRectangle ( ) ;
shapeMaker . drawSquare ( ) ;
}
}
55. Introduction Summary References
OBSERVER
Problem: How do you dynamically (at run time) add and
remove connections between objects.
Solution: An Observer Manager implements the following
protocol:
“I Want to Observe X” – the OM will keep track of who is
watching who.
“Tell Everybody who is Observing Met that I have
Changed” – the OM can then tell everybody that an object
has changed.
In this way neither the observer nor the observed object
need know the existance of the other.
56. Introduction Summary References
PATTERNS AND FRAMEWORKS
Both are ways of describing and documenting solutions to
common problems.
Frameworks are more “shrinkwrapped”, ready for
immediate use.
Patterns are more abstract – many patterns are involved in
the solution of one problem.
57. Introduction Summary References
SUMMARY
In this chapter we have examined a variety of topics
related to dependency.
How classes and objects can depend upon each other.
How methods within a class can depend upon each other.
How to control visibility, as a means of controlling
dependency.
How strong dependency can be weakened by using
alternative designs.
58. Introduction Summary References
REFERENCES
Images and content for developing these slides have been
taken from the follwoing book with the permission of the
author.
An Introduction to Object Oriented Programming, Timothy
A. Budd.
Some examples and text has been used from Tutsplus.
Some examples have been taken from Tutorialspoint.
Code Project.
This presentation is developed with Beamer:
Darmstadt, crane.