Title: Design Patterns
1Design Patterns
2Introduction to Patterns
- The recurring aspects of designs are called
design patterns. - A pattern is the outline of a reusable solution
to a general problem encountered in a particular
context - Many of them have been systematically documented
for all software developers to use - A good pattern should
- Be as general as possible
- Contain a solution that has been proven to
effectively solve the problem in the indicated
context. - Studying patterns is an effective way to learn
from the experience of others
3Pattern description
- Context
- The general situation in which the pattern
applies - Problem
- A short sentence or two raising the main
difficulty. - Forces
- The issues or concerns to consider when solving
the problem - Solution
- The recommended way to solve the problem in the
given context. - to balance the forces
- Antipatterns (Optional)
- Solutions that are inferior or do not work in
this context. - Related patterns (Optional)
- Patterns that are similar to this pattern.
- References
- Who developed or inspired the pattern.
4Design Patterns
- Good designers know not to solve every problem
from first principles. They reuse solutions. - Practitioners do not do a good job of recording
experience in software design for others to use.
5Design Patterns (Contd)
- A Design Pattern systematically names, explains,
and evaluates an important and recurring design. - We describe a set of well-engineered design
patterns that practitioners can apply when
crafting their applications.
6Becoming a Master Designer
- First, One Must Learn the Rules
- Algorithms
- Data Structures
- Languages
- Later, One Must Learn the Principles
- Structured Programming
- Modular Programming
- OO Programming
7Becoming a Master Designer (Contd)
- Finally, One Must Study the Designs of Other
Masters - Design patterns must be understood, memorized,
and applied. - There are thousands of existing design patterns.
8Introduction
- Creational patterns (constructing objects)
- Structural patterns (controlling heap layout)
- Behavioral patterns (affecting object semantics)
9What is a pattern?
- a known solution to a known problem
- a standard solution to a common programming
problem - a technique for making code more flexible by
making it meet certain criteria - a design or implementation structure that
achieves a particular purpose - a high-level programming idiom
- shorthand for describing certain aspects of
program organization - connections among program components
- the shape of a heap snapshot or object model
10Encapsulation (data hiding)
- Problem Exposed fields can be directly
manipulated - Violations of the representation invariant
- Dependences prevent changing the implementation
- Solution Hide some components
- Permit only stylized access to the object
- Disadvantages
- Interface may not (efficiently) provide all
desired operations - Indirection may reduce performance
11Subclassing (inheritance)
- Problem Repetition in implementations
- Similar abstractions have similar members
(fields, methods) - Solution Inherit default members from a
superclass - Select an implementation via run-time dispatching
- Disadvantages
- Code for a class is spread out, potentially
- reducing understandability
- Run-time dispatching introduces overhead
12Iteration
- Problem To access all members of a collection,
must perform a specialized traversal for each
data structure - Introduces undesirable dependences
- Does not generalize to other collections
- Solution
- The implementation performs traversals, does
bookkeeping - Results are communicated to clients via a
standard interface - Disadvantages
- Iteration order is fixed by the implementation
and not under - the control of the client
13Exceptions
- Problem
- Errors in one part of the code should be handled
elsewhere. - Code should not be cluttered with error-handling
code. - Return values should not be preempted by error
codes. - Solution Language structures for throwing and
catching exceptions - Disadvantages
- Code may still be cluttered.
- It may be hard to know where an exception will be
handled. - Use of exceptions for normal control flow may be
confusing and inefficient.
14When (not) to use design patterns
- Rule 1 delay
- Design patterns can increase or decrease
understandability - Add indirection, increase code size
- Improve modularity, separate concerns, ease
description - If your design or implementation has a problem,
consider design patterns that address that
problem - Canonical reference the "Gang of Four" book
- Design Patterns Elements of Reusable
Object-Oriented Software, by Erich Gamma, Richard
Helm, Ralph Johnson, and John Vlissides,
Addison-Wesley, 1995. - Another good reference for Java
- Effective Java Programming Language Guide, by
Joshua Bloch, Addison-Wesley, 2001.
15Creational
- Factories
- Factory method
- Factory object
- Prototype
- Sharing
- Singleton
- Interning
- Flyweight
16Factories
- Problem client desires control over object
creation - Factory method put code in methods in client
- Factory object put code in a separate object
- Prototype put code in clone methods
17Example
- class Race
- Race createRace()
- Frame frame1 new Frame()
- Wheel front1 new Wheel()
- Wheel rear1 new Wheel()
- Bicycle bike1 new Bicycle(frame1, front1,
rear1) - Frame frame2 new Frame()
- Wheel frontWheel2 new Wheel()
- Wheel rearWheel2 new Wheel()
- Bicycle bike2 new Bicycle(frame2, front2,
rear2) - ...
-
-
18TourDeFrance
- class TourDeFrance extends Race
- Race createRace()
- Frame frame1 new RacingFrame()
- Wheel front1 new Wheel700c()
- Wheel rear1 new Wheel700c()
- Bicycle bike1 new Bicycle(frame1, front1,
rear1) - Frame frame2 new RacingFrame()
- Wheel frontWheel2 new Wheel700c()
- Wheel rearWheel2 new Wheel700c()
- Bicycle bike2 new Bicycle(frame2, front2,
rear2) - ...
-
-
19Cyclocross
- class Cyclocross extends Race
- Race createRace()
- Frame frame1 new MountainFrame()
- Wheel front1 new Wheel26in()
- Wheel rear1 new Wheel26in()
- Bicycle bike1 new Bicycle(frame1, front1,
rear1) - Frame frame2 new MountainFrame()
- Wheel frontWheel2 new Wheel26in()
- Wheel rearWheel2 new Wheel26in()
- Bicycle bike2 new Bicycle(frame2, front2,
rear2) - ...
-
-
20With a Factory
- class Race
- Frame createFrame() return new Frame()
- Wheel createWheel() return new Wheel()
- Bicycle createBicycle(Frame frame, Wheel front,
Wheel rear) - return new Bicycle(frame, front, rear)
- // Return a complete bicycle without needing any
arguments - Bicycle completeBicycle()
- Frame frame createFrame()
- Wheel frontWheel createWheel()
- Wheel rearWheel createWheel()
- return createBicycle(frame, frontWheel,
rearWheel) -
- Race createRace()
- Bicycle bike1 completeBicycle()
- Bicycle bike2 completeBicycle()
- ...
-
21part 2
- class TourDeFrance extends Race
- Frame createFrame() return new RacingFrame()
- Wheel createWheel() return new Wheel700c()
- Bicycle createBicycle(Frame frame, Wheel front,
Wheel rear) - return new RacingBicycle(frame, front, rear)
-
-
- class Cyclocross extends Race
- Frame createFrame() return new MountainFrame()
- Wheel createWheel() return new Wheel26inch()
- Bicycle createBicycle(Frame frame, Wheel front,
Wheel rear) - return new MountainBicycle(frame, front, rear)
-
-
22Different classes
- class BicycleFactory
- Frame createFrame() return new Frame()
- Wheel createWheel() return new Wheel()
- Bicycle createBicycle(Frame frame, Wheel front,
Wheel rear) - return new Bicycle(frame, front, rear)
-
- // return a complete bicycle without needing any
arguments - Bicycle completeBicycle()
- Frame frame createFrame()
- Wheel frontWheel createWheel()
- Wheel rearWheel createWheel()
- return createBicycle(frame, frontWheel,
rearWheel) -
-
23Or like this
- class RacingBicycleFactory
- Frame createFrame() return new RacingFrame()
- Wheel createWheel() return new Wheel700c()
- Bicycle createBicycle(Frame frame, Wheel front,
Wheel rear) - return new RacingBicycle(frame, front, rear)
-
-
- class MountainBicycleFactory
- Frame createFrame() return new MountainFrame()
- Wheel createWheel() return new Wheel26inch()
- Bicycle createBicycle(Frame frame, Wheel front,
Wheel rear) - return new MountainBicycle(frame, front, rear)
-
-
24Using the factory
- class Race
- BicycleFactory bfactory
- // constructor
- Race() bfactory new BicycleFactory()
- Race createRace()
- Bicycle bike1 bfactory.completeBicycle()
- Bicycle bike2 bfactory.completeBicycle()...
- class TourDeFrance extends Race
- // constructor
- TourDeFrance() bfactory new
RacingBicycleFactory() -
- class Cyclocross extends Race
- // constructor
- Cyclocross() bfactory new MountainBicycleFacto
ry()
25The Abstract Factory Pattern (Intent)
- Provides an interface for creating families of
related or dependent objects without specifying
their concrete classes.
26The Abstract Factory Pattern (Behavior)
- Sometimes we have systems that support different
representations depending on external factors. - There is an Abstract Factory that provides an
interface for the client. In this way the client
can obtain a specific object through this
abstract interface.
27Example of the Abstract Factory Pattern
WidgetFactory
Client
CreateScrollBar() Create Window()
Window
MotifWidgetFactory
PMWidgetFactory
PMWindow
MotifWindow
CreateScrollBar() Create Window()
CreateScrollBar() Create Window()
ScrollBar
PMScrollBar
MotifScrollBar
28Structure of the Abstract Factory Pattern
AbstractFactory
Client
CreateProductA() CreateProductB()
AbstractProductA
ConcreteFactory1
ConcreteFactory2
ProductA1
ProductA2
CreateProductA() CreateProductB()
CreateProductA() CreateProductB()
AbstractProductB
ProductB1
ProductB2
29Participants of the Abstract Factory Pattern
- Abstract Factory
- Declares an interface for operations that create
abstract product objects. - Concrete Factory
- Implements the operations to create concrete
product objects.
30Participants of the Abstract Factory Pattern
(Contd)
- Abstract Product
- Declares an interface for a type of product
object. - Concrete Product
- Defines a product object to be declared by the
corresponding concrete factory. (Implements the
Abstract Product interface). - Client
- Uses only interfaces declared by Abstract Factory
and Abstract Product classes.
31Abstract Factory Example
public abstract class AbstractFactory public
static final String MOTIF_WIDGET_NAME
"Motif" public static final String
WINDOWS_WIDGET_NAME "Windows" public static
AbstractFactory getFactory(String name) if
(name.equals(MOTIF_WIDGET_NAME)) return
new MotifFactory( ) else if
(name.equals(WINDOWS_WIDGET_NAME)) return
new WindowsFactory( ) return null public
abstract AbstractWindow getWindow()
32Abstract Factory Example (Contd)
// Code for class MotifFactory package
example public class MotifFactory extends
AbstractFactory public MotifFactory()
public AbstractWindow getWindow()
return new MotifWindow()
33Abstract Factory Example (Contd)
// Code for class WindowsFactory public class
WindowsFactory extends AbstractFactory
public WindowsFactory() public
AbstractWindow getWindow() return new
WindowsWindow()
34Abstract Factory Example (Contd)
// Code for class AbstractWindow public
abstract class AbstractWindow public
abstract void show()
35Abstract Factory Example (Contd)
//Code for class MotifWindow public class
MotifWindow extends AbstractWindow public
MotifWindow() public void show()
JFrame frame new JFrame() try
UIManager.setLookAndFeel("
com.sun.java.swing.plaf.motif.MotifLookAndFeel")
catch (Exception e)
e.printStackTrace()
//updating the components tree after changing the
LAF SwingUtilities.updateComponentTreeUI(f
rame) frame.setSize(300, 300)
frame.setVisible(true)
36Abstract Factory Example (Contd)
// Code for class WindowsWindow public class
WindowsWindow extends AbstractWindow public
WindowsWindow() public void show()
JFrame frame new JFrame() try
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFee
l") catch (Exception e)
e.printStackTrace() //updating
the components tree after changing the LAF
SwingUtilities.updateComponentTreeUI(frame)
frame.setSize(300, 300)
frame.setVisible(true)
37Abstract Factory Example (Contd)
// Code for class Client public class Client
public Client(String factoryName)
AbstractFactory factory
AbstractFactory.getFactory(factoryName)
AbstractWindow window factory.getWindow()
window.show() public static void
main(String args) //args0
contains the name of the family of widgets
//to be used by the Client class (Motif or
Windows) new Client(args0)
38Prototype
- Every object is itself a factory
- Each class contains a clone method that creates a
copy ofthe receiver object - class Bicyle
- Object clone() ...
-
- Why is Object the return type of clone?
39Using prototype
- class Race
- Bicycle bproto
- // constructor
- Race(Bicycle bproto) this.bproto bproto
- Race createRace()
- Bicycle bike1 (Bicycle) bproto.clone()
- Bicycle bike2 (Bicycle) bproto.clone()
- ...
-
-
40Sharing
- Singleton only one object exists at runtime
- Interning only one object with a particular
(abstract) value exists at runtime - Flyweight separate intrinsic and extrinsic
state, represent them separately, and intern the
intrinsic state
41Singleton
- Only one object of the given type exists
- class Bank
- private static bank theBank
- // constructor
- private Bank() ...
- // factory method
- public static getBank()
- if (theBank null)
- theBank new Bank()
-
- return theBank
- ...
42Interning
- Reuse existing objects instead of creating new
ones - Permitted only for immutable objects
43Interning 2
- Maintain a collection of all objects
- If an object already appears, return that instead
- HashMap segnames new HashMap()
- String canonicalName(String n)
- if (segnames.containsKey(n))
- return segnames.get(n)
- else
- segnames.put(n, n)
- return n
-
-
44Interning 3
- Two approaches
- create the object, but perhaps discard it and
return another - check against the arguments before creating the
new object
45Flyweight
- Separate the intrinsic (same across all objects)
and extrinsic (different for different objects)
state - Intern the intrinsic state
- Good when most of the object is immutable
46More on flyweight
- Flyweight is manageable only if there are very
few mutable - (extrinsic) fields.
- Flyweight complicates the code.
- Use flyweight only when profiling has determined
that - space is a serious problem.
47Structural
- Wrappers
- Adapters
- Decorators
- Proxies
48Wrappers
- The wrapper translates between incompatible
interfaces - Wrappers are a thin layer over an encapsulated
class - modify the interface
- extend behavior
- restrict access
- The encapsulated class does most of the work
49Wrappers 2
50Adapter
- Change an interface without changing
functionality - rename a method
- convert units
- implement a method in terms of another
- Example angles passed in radians vs. degrees
51Adapter 2
52The Adapter Pattern
- Intent Convert the interface of a class into
another interface clients expect. Adapter lets
classes work together that couldnt otherwise
because of incompatible interfaces. - Motivation When we want to reuse classes in an
application that expects classes with a different
interface, we do not want (and often cannot) to
change the reusable classes to suit our
application.
53Example of the Adapter Pattern
Shape
TextView
Editor
BoundingBox() CreateManipulator()
GetExtent()
text
return text -gt GetExtent()
return new Text Manipulator
54Structure of the Adapter Pattern Using Multiple
Inheritance
Adaptee
Client
Target
SpecificRequest()
Request()
(implementation)
55Structure of the Adapter Pattern Using Object
Composition
Target
Adaptee
Client
Request()
SpecificRequest()
adaptee
Adapter
Request()
56Participants of the Adapter Pattern
- Target Defines the application-specific
interface that clients use. - Client Collaborates with objects conforming to
the target interface. - Adaptee Defines an existing interface that needs
adapting. - Adapter Adapts the interface of the adaptee to
the target interface.
57Decorator
- Add functionality without changing the interface
- Add to existing methods to do something
additional (while still preserving the previous
specification) - Not all subclassing is decoration
58Proxy
- Same interface and functionality as the wrapped
class - Control access to other objects
- communication manage network details when using
a remote object - locking serialize access by multiple clients
- security permit access only if proper
credentials - creation object might not yet exist (creation is
expensive) - hide latency when creating object
- avoid work if object is never used
59Subclassing vs. delegation
- Subclassing
- automatically gives access to all methods of
superclass - built into the language (syntax, efficiency)
- Delegation
- permits cleaner removal of methods (compile-time
checking) - wrappers can be added and removed dynamically
- objects of arbitrary concrete classes can be
wrapped - multiple wrappers can be composed
- Some wrappers have qualities of more than one of
adapter, decorator, and proxy
60Composite
- Composite permits a client to manipulate either
an atomic unit or a collection of units in the
same way - Good for dealing with part-whole relationships
61Interpreter and procedural patterns
- Interpreter collects code for similar objects,
spreads apart code for similar operations - Makes it easy to add objects, hard to add
operations - Procedural collects code for similar operations,
spreads apart code for similar objects - Makes it easy to add operations, hard to add
objects - The visitor pattern is a variety of the
procedural pattern
62Intrepreter and procedural
- Both interpreter and procedural have classes for
objects - The code for operations is similar
- The question is where to place that code
- Selecting between interpreter and procedural
- Are the algorithms central, or are the objects?
- (Is the system operation-centric or
object-centric?) - What aspects of the system are most likely to
change?
63With intrepreter
- Add a method to each class for each supported
operation - class Expression ...
- Type typecheck()
- String prettyPrint()
-
- class EqualOp extends Expression ...
- Type typecheck() ...
- String prettyPrint() ...
-
- class CondExpr extends Expression ...
- Type typecheck() ...
- String prettyPrint() ...
-
64With procedural
- Create a class per operation, with a method per
operand type - class Typecheck
- // typecheck "a?bc"
- Type tcCondExpr(CondExpr e)
- Type condType tcExpression(e.condition) //
type of "a" - Type thenType tcExpression(e.thenExpr) // type
of "b" - Type elseType tcExpression(e.elseExpr) // type
of "c" - if ((condType BoolType) (thenType
elseType)) - return thenType
- else
- return ErrorType
-
- // typecheck "ab"
- Type tcEqualOp(EqualOp e) ...
-
65Typecheck
- class Typecheck
- ...
- Type tcExpression(Expression e)
- if (e instanceof PlusOp)
- return tcPlusOp((PlusOp)e)
- else if (e instanceof VarRef)
- return tcVarRef((VarRef)e)
- else if (e instanceof EqualOp)
- return tcEqualOp((EqualOp)e)
- else if (e instanceof CondExpr)
- return tcCondExpr((CondExpr)e)
- else ... ...
66Visitor
- Visitor encodes a traversal of a hierarchical
data structure - Nodes (objects in the hierarchy) accept visitors
- Visitors visit nodes (objects)
67Visitor 2
- class Node
- void accept(Visitor v)
- for each child of this node
- child.accept(v)
-
- v.visit(this)
- class Visitor
- void visit(Node n)
- perform work on n
- n.accept(v) performs a depthfirst traversal of
the structure rooted at n, performing v's
operation on each element of the structure
68Implementing visitor
- You must add definitions of visit and accept (see
textbook) - Visit might count nodes, perform typechecking,
etc. - It is easy to add operations (visitors), hard to
add nodes (modify each existing visitor) - Visitors are similar to iterators each element
of the data structure is presented in turn to the
visit method - Visitors have knowledge of the structure, not
just the sequence
69Abstraction-Occurrence
- Context
- Often in a domain model you find a set of related
objects (occurrences). - The members of such a set share common
information - but also differ from each other in important
ways. - Problem
- What is the best way to represent such sets of
occurrences in a class diagram? - Forces
- You want to represent the members of each set of
occurrences without duplicating the common
information
70 Abstraction-Occurrence
Occurrence
Abstraction
TVSeries
Episode
seriesName
number
producer
title
storySynopsis
Title
LibraryItem
name
barCodeNumber
author
isbn
publicationDate
libOfCongress
71 Abstraction-Occurrence
72 Abstraction-Occurrence
ScheduledTrain
SpecificTrain
number
date
ScheduledLeg
SpecificLeg
actualDepTime
scheduledDepTime
actualArrTime
scheduledArrTime
origin
destination
Station
73General Hierarchy
- Context
- Objects in a hierarchy can have one or more
objects above them (superiors), - and one or more objects below them
(subordinates). - Some objects cannot have any subordinates
- Problem
- How do you represent a hierarchy of objects, in
which some objects cannot have subordinates? - Forces
- You want a flexible way of representing the
hierarchy - that prevents certain objects from having
subordinates - All the objects have many common properties and
operations
74 General Hierarchy
Node
subordinate
0..1
SuperiorNode
NonSuperiorNode
contains
supervises
Employee
FileSystemItem
0..1
0..1
Manager
Technician
Secretary
Directory
File
75 General Hierarchy
76Player-Role
- Context
- A role is a particular set of properties
associated with an object in a particular
context. - An object may play different roles in different
contexts. - Problem
- How do you best model players and roles so that a
player can change roles or possess multiple roles?
77Player-Role
- Forces
- It is desirable to improve encapsulation by
capturing the information associated with each
separate role in a class. - You want to avoid multiple inheritance.
- You cannot allow an instance to change class
- Solution
Player
AbstractRole
Role1
Role2
78Player-Role
79Player-Role
80Player-Role
- Antipatterns
- Merge all the properties and behaviours into a
single Player class and not have Role classes
at all. - Create roles as subclasses of the Player class.
81Singleton Pattern
- Context
- It is very common to find classes for which only
one instance should exist (singleton) - Problem
- How do you ensure that it is never possible to
create more than one instance of a singleton
class? - Forces
- The use of a public constructor cannot guarantee
that no more than one instance will be created. - The singleton instance must also be accessible to
all classes that require it
82Singleton
Singleton
theInstance
getInstance
Company
if (theCompanynull)
theCompany
theCompany new Company()
Company private
return theCompany
getInstance
83Observer Pattern
- Context
- When an association is created between two
classes, the code for the classes becomes
inseparable. - If you want to reuse one class, then you also
have to reuse the other. - Problem
- How do you reduce the interconnection between
classes, especially between classes that belong
to different modules or subsystems? - Forces
- You want to maximize the flexibility of the
system to the greatest extent possible
84Observer
85Observer
- Antipatterns
- Connect an observer directly to an observable so
that they both have references to each other. - Make the observers subclasses of the observable.
86The Observer Pattern (Intent)
- Define a one-to-many dependency between objects
so that when one object changes state, all its
dependents are notified and updated
automatically.
87The Observer Pattern (Motivation)
- A common side-effect of partitioning a system
into a collection of cooperating classes is the
need to maintain consistency between related
objects. - You dont want to achieve consistency by making
the classes tightly coupled, because that reduces
their reusability.
88Example of the Observer Pattern
a b c
a 50 b 30 c 20
change notification
requests, modifications
89Structure of the Observer Pattern
observers
Subject
Observer
Attach(Observer) Detach(Observer)Notify()
Update()
for all o in observers o -gt Update()
ConcreteObserver
observerState subject-gtGetState()
Update()
subject
ConcreteSubject
observerState
GetState() SetState()
return subjectState
subjectState
90Structure of the Observer Pattern
- The key objects in this pattern are subject and
observer. - A subject may have any number of dependent
observers. - All observers are notified whenever the subject
undergoes a change in state.
91Participants of the Observer Pattern
- Subject
- Knows its numerous observers.
- Provides an interface for attaching and detaching
observer objects. - Sends a notification to its observers when its
state changes. - Observer
- Defines an updating interface for concrete
observers.
92Participants of the Observer Pattern (Contd)
- Concrete Subject
- Stores state of interest to concrete observers.
- Concrete Observer
- Maintains a reference to a concrete subject
object. - Stores state that should stay consistent with the
subject's. - Implements the updating interface.
93Delegation Pattern
- Context
- You are designing a method in a class
- You realize that another class has a method which
provides the required service - Inheritance is not appropriate
- E.g. because the isa rule does not apply
- Problem
- How can you most effectively make use of a method
that already exists in the other class? - Forces
- You want to minimize development cost by reusing
methods
94Delegation
delegatingMethod()
Delegate
Delegator
delegate.method()
delegatingMethod
method
push()
LinkedList
Stack
list.addFirst()
addFirst
push
addLast
pop
addAfter
isEmpty
removeFirst
removeLast
delete
isEmpty
95Delegation
Example
96Delegation
- Antipatterns
- Overuse generalization and inherit the method
that is to be reused - Instead of creating a single method in the
Delegator that does nothing other than call a
method in the Delegate - consider having many different methods in the
Delegator call the delegates method - Access non-neighboring classes
return specificFlight.regularFlight.flightNumber()
return getRegularFlight().flightNumber()
97Adapter Pattern
- Context
- You are building an inheritance hierarchy and
want to incorporate it into an existing class. - The reused class is also often already part of
its own inheritance hierarchy. - Problem
- How to obtain the power of polymorphism when
reusing a class whose methods - have the same function
- but not the same signature
- as the other methods in the hierarchy?
- Forces
- You do not have access to multiple inheritance or
you do not want to use it.
98Adapter
99Adapter
100Façade Pattern
- Context
- Often, an application contains several complex
packages. - A programmer working with such packages has to
manipulate many different classes - Problem
- How do you simplify the view that programmers
have of a complex package? - Forces
- It is hard for a programmer to understand and use
an entire subsystem - If several different application classes call
methods of the complex package, then any
modifications made to the package will
necessitate a complete review of all these
classes.
101Façade
102The Facade Pattern (Intent)
- Provide a unified interface to a set of
interfaces in a subsystem. Facade defines a
higher-level interface that makes the subsystem
easier to use.
103The Facade Pattern (Motivation)
- Structuring a system into subsystems helps reduce
complexity. - A common design goal is to minimize the
communication and dependencies between
subsystems. - Use a facade object to provide a single,
simplified interface to the more general
facilities of a subsystem.
104Example of the Facade Pattern
Compiler
Compile()
Scanner
Token
Parser
CodeGenerator
ProgNodeBuilder
RISCCG
ProgNode
StackMachineCG
Statement Node
Expression Node
Variable Node
Compiler Subsystem Classes
105Structure of the Facade Pattern
Client Classes
Facade
Subsystem Classes
106Participants of the Facade Pattern
- Facade
- Knows which subsystem classes are responsible for
a request. - Delegates client requests to appropriate
subsystem objects. - Subsystem Classes
- Implement subsystem functionality.
- Handle work assigned by the facade object.
- Have no knowledge of the facade that is, they
keep no references to it.
107Immutable Pattern
- Context
- An immutable object is an object that has a state
that never changes after creation - Problem
- How do you create a class whose instances are
immutable? - Forces
- There must be no loopholes that would allow
illegal modification of an immutable object - Solution
- Ensure that the constructor of the immutable
class is the only place where the values of
instance variables are set or modified. - Instance methods which access properties must not
have side effects. - If a method that would otherwise modify an
instance variable is required, then it has to
return a new instance of the class.
108Read-only Interface Pattern
- Context
- You sometimes want certain privileged classes to
be able to modify attributes of objects that are
otherwise immutable - Problem
- How do you create a situation where some classes
see a class as read-only whereas others are able
to make modifications? - Forces
- Restricting access by using the public, protected
and private keywords is not adequately selective.
- Making access public makes it public for both
reading and writing
109Read-only Interface
interface
UnprivilegedClass
ReadOnlyInterface
getAttribute
Mutable
Mutator
attribute private
getAttribute
setAttribute
110Read-only Interface
111Read-only Interface
- Antipatterns
- Make the read-only class a subclass of the
Mutable class - Override all methods that modify properties
- such that they throw an exception
112Proxy Pattern
- Context
- Often, it is time-consuming and complicated to
create instances of a class (heavyweight
classes). - There is a time delay and a complex mechanism
involved in creating the object in memory - Problem
- How to reduce the need to create instances of a
heavyweight class? - Forces
- We want all the objects in a domain model to be
available for programs to use when they execute a
systems various responsibilities. - It is also important for many objects to persist
from run to run of the same program
113Proxy
interface
ClassIF
HeavyWeight
Proxy
Client
114Proxy
115The Iterator Pattern (Intent)
- Provide a way to access the elements of an
aggregate object sequentially without exposing
its underlying representation. - Move the responsibility for access and traversal
from the aggregate object to the iterator object.
116The Iterator Pattern (Motivation)
- One might want to traverse an aggregate object in
different ways. - One might want to have more than one traversal
pending on the same aggregate object. - Not all types of traversals can be anticipated a
priori. - One should not bloat the interface of the
aggregate object with all these traversals.
117Example of the Iterator Pattern
list
List
Count() Append(Element)
Remove(Element)
118Structure of the Iterator Pattern
Aggregate
Iterator
CreateIterator()
First() Next() IsDone() CurrentItem()
ConcreteAggregate
ConcreteIterator
CreateIterator()
return new ConcreteIterator(this)
119Participants of the Iterator Pattern
- Iterator Defines an interface for accessing and
traversing elements. - Concrete Iterator Implements an iterator
interface and keeps track of the current position
in the traversal of the aggregate. - Aggregate Defines an interface for creating an
iterator object. - Concrete Aggregate Implements the iterator
creation interface to return an instance of the
proper concrete iterator.
120The Composite Pattern (Intent)
- Compose objects into tree structures to represent
part-whole hierarchies. - Composite lets clients treat individual objects
and compositions of objects uniformly.
121The Composite Pattern (Motivation)
- If the composite pattern is not used, client code
must treat primitive and container classes
differently, making the application more complex
than is necessary.
122Example of the Composite Pattern
Graphic
Draw() Add(Graphic)Remove(Graphic) GetChild(int)
graphics
Line
Text
Rect.
Picture
Draw()
Draw()
Draw()
Draw() Add(Graphic) Remove(Graphic) GetChild(int)
forall g in graphics g.Draw()
123Structure of the Composite Pattern
Client
Component
Operation() Add(Component) Remove(Component)GetCh
ild(int)
children
Leaf
Composite
forall g in children g.Operation()
Operation()
Operation() Add(Component) Remove(Component)GetCh
ild(int)
124Participants of Composite Pattern
- Component
- Declares the interface for objects in the
composition. - Implements default behavior for the interface
common to all classes. - Declares an interface for accessing and managing
its child components. - Defines an interface for accessing a components
parent in the recursive structure (optional).
125Participants of Composite Pattern (Contd)
- Leaf
- Represents leaf objects in the composition. A
leaf has no children. - Defines behavior for primitive objects in the
composition. - Composite
- Defines behavior for components having children.
- Stores child components.
- Implements child-related operations in the
component interface.
126Participants of Composite Pattern (Contd)
- Client
- Manipulates objects in the composition through
the component interface.
127The Template Pattern (Intent)
- Define the skeleton of an algorithm in an
operation, deferring some steps to subclasses. - The Template Method lets subclasses redefine
certain steps of an algorithm without changing
the algorithms structure.
128The Template Pattern (Motivation)
- By defining some of the steps of an algorithm,
using abstract operations, the template method
fixes their ordering.
129Structure of the Template Pattern
AbstractClass
... PrimitiveOp1() PrimitiveOp2() ...
TemplateMethod() PrimitiveOp1() PrimitiveOp2()
ConcreteClass
PrimitiveOp1() PrimitiveOp2()
130Structure of the Template Pattern
- Abstract Class
- Defines abstract primitive operations that
concrete subclasses define to implement steps of
an algorithm. - Implements a template method defining the
skeleton of an algorithm. The template method
calls primitive operations as well as operations
defined in Abstract Class or those of other
objects.
131Structure of the Template Pattern (Contd)
- Concrete Class Implements the primitive
operations to carry out subclass-specific steps
to the algorithm.
132The Master-Slave Pattern (Intent)
- Handles the computation of replicated services
within a software system to achieve fault
tolerance and robustness. - Independent components providing the same service
(slaves) are separated from a component (master)
responsible for invoking them and for selecting a
particular result from the results returned by
the slaves.
133The Master-Slave Pattern (Motivation)
- Fault tolerance is a critical factor in many
systems. - Replication of services and delegation of the
same task to several independent suppliers is a
common strategy to handle such cases.
134Example of the M/S Pattern
Slave1
RadLevel()
NuclearPP
Voter
Slave2
acceptableRL()
RadLevel()
RadLevel()
return max( slave1-gtRadLevel(), slave2-gtRadLevel
(), slave3-gtRadLevel())
Slave3
RadLevel()
135Structure of the M/S Pattern
Slave1
ServiceImp1()
forward request
forward request
Slave2
Master
Client
service()
Compute()
ServiceImp1()
request service
forward request
Slave3
ServiceImp1()
136Participants of the M/S Pattern
- Slave
- Implements a service.
- Master
- Organizes the invocation of replicated services.
- Decides which of the results returned by its
slaves is to be passed to its clients. - Client
- Requires a certain service in order to solve its
own task.
137References
- Gamma95 Gamma, E., Helm, R., Johnson, R.,
Vlissides, J., Design Patterns Elements of
Reusable Object-Oriented Software.
Addison-Wesley, 1995. - Coplien95 J. O. Complien, D.C. Schmidt, Pattern
Languages of Program Design. Addison-Wesley,
1995.