D
ESIGNP
ATTERNSRoohollah Abdipour
A
GENDAI
NTRODUCTIONDesign patterns are the answer to a question that commonly
arises “How can I … ?”
Patterns record successful solutions in software development for sharing between projects.
Gang of Four (GoF) Gamma, Helm, Johnson, Vlissides,
- founders of movement.
Gamma et al, Design Patterns: Elements of Reusable
I
NTRODUCTION(
CONT.)
Patterns solve software structural problems like:
Abstraction, Encapsulation
Information hiding
Separation of concerns Coupling and cohesion
Separation of interface and implementation Single point of reference
Divide and conquer
I
NTRODUCTION(
CONT.)
Patterns also solve non-functional problems like: Changeability Interoperability Efficiency Reliability Testability Reusability
T
YPES OFP
ATTERNThere are 3 types of pattern …
⚫ Creational: address problems of creating an object in a
flexible way. Separate creation, from operation/use.
⚫ Structural: address problems of using O-O constructs like
inheritance to organize classes and objects
⚫ Behavioral: address problems of assigning responsibilities to
classes. Suggest both static relationships and patterns of communication
(use cases)
P
ATTERNS, A
RCHITECTURES& F
RAMEWORKSThere can be confusion between patterns, architectures and frameworks.
Let’s try to distinguish them:
Architectures model software structure at the highest
possible level, and give the overall system view. An
architecture can use many different patterns in different components
P
ATTERNS, A
RCHITECTURES&
F
RAMEWORKS(
CONT.)
Patterns are more like small-scale or local architectures
for architectural components or sub-components
Frameworks are partially completed software systems
that may be targeted at a particular type of application. These are tailored by completing the unfinished
components
P
ATTERNS, A
RCHITECTURES&
F
RAMEWORKS(
CONT.)
Summary of Differences
⚫ Patterns are more general and abstract than frameworks. A pattern is a description of a solution, not a solution itself.
⚫ A pattern cannot be directly implemented. An implementation is an example of a pattern.
⚫ Patterns are more primitive than frameworks. A framework can employ several patterns.
P
ATTERNT
EMPLATESName: meaningful text that reflects the problem, e.g.
Bridge, Mediator, Flyweight
Problem addressed: intent of the pattern, objectives
achieved within certain constraints
Context: circumstances under which it can occur, used
to determine applicability
Forces: constraints or issues that solution must address, forces may conflict!
Solution: the static and dynamic relationships among the
pattern components. Structure, participants, collaboration. Solution must resolve all forces!
E
LEMENTS OFD
ESIGNP
ATTERNSDesign patterns have 4 essential elements:
⚫ Pattern name: increases vocabulary of designers ⚫ Problem: intent, context, when to apply
⚫ Solution: UML-like structure, abstract code ⚫ Consequences: results and tradeoffs
P
ATTERN: S
INGLETON(C
REATIONAL)
Name: Singleton Problem:
How can we guarantee that one and only one instance of a class can be created?
Context: In some applications it is important
to have exactly one instance of a class, e.g. sales of one company.
P
ATTERN: S
INGLETON(C
REATIONAL)(
CONT.)
Forces: Can make an object globally accessible as a
global variable, but this violates encapsulation.
Solution:
Create a class with a class operation getInstance(). When class is first accessed, this creates relevant object instance and returns object identity to client. On subsequent calls of getInstance(), no new
instance is created, but identity of existing object is returned.
S
INGLETONS
TRUCTURE Singleton -uniqueInstance -singletonData +getInstance( ) +getSingletonData( ) +singletonOperation( ) -Singleton( )Object identifier for singleton instance, class scope or static
Returns object identifier for unique instance, class-scope or static
Private constructor only accessible via getInstance()
getInstance( ) {
if ( uniqueInstance == null )
{ uniqueInstance = new Singleton( ) } return uniqueInstance
}
Class Singleton {
private static Singleton uniqueInstance = null; private Singleton( ) { .. } // private constructor public static Singleton getInstance( ) {
if (uniqueInstance == null)
uniqueInstance = new Singleton(); // call constructor
return uniqueInstance; }
}
C
OMMENTSTo specify a class has only one instance, we make
it a Singleton.
+ controlled access to single object instance through
Singleton encapsulation
+ Can tailor for any finite number of instances
- access requires additional message passing
- Pattern limits flexibility, significant redesign if
singleton class later gets many instances
5.6. P
ATTERN: F
AÇADE(S
TRUCTURAL)
Name: Façade
Problem:
How can we access a large number of classes
with a complex internal interaction in a simple
but safe way?
Solution:
Introduce a dedicated interface class that
F
ACADES
TRUCTUREFacade
subsystem classes
Facade (Non software example)
Provide a unified
interface to a set
of interfaces in a
subsystem.
<<façade>> SecurityManager +addAccessRight() +addActor() +addActorRole() +removeActor() AccessRight +addAccessRight() Actor +addActor() +removeActor() +changeSalary() ActorRole +addActorRole()
Method not in Facade
Pattern Name
C
OMMENTSClients communicate with the subsystem by sending requests to Façade which forwards them to the
appropriate subsystem object(s).
Although subsystem objects perform actual work,
Façade may have to translate its interface to subsystem interfaces.
Clients that use the Façade don’t have to access its subsystem objects directly.
Usually only one Façade object is required. Thus a Façade object is often a singleton.
Usually only one Façade object is required. Thus a Façade object is often a singleton.
Factory pattern can be used with Façade to provide an interface for creating subsystem objects in a subsystem independent way.
Factory can also be used as an alternative to Façade to hide platform-specific classes.
Mediator pattern is similar to Façade in abstracting functionality of classes.
5.7. P
ATTERN: M
EDIATOR(B
EHAVIORAL)
Problem:
How can we deal with two or more classes
which sometimes interact, but can also be used
separately?
Solution: Mediator promotes loose coupling
by keeping objects from referring to one another
explicitly. Put each interaction between objects
in a separate (Mediator) class. This class
A pattern for two objects which exist independently but have some coupling. This coupling is placed in its own class.
Used by e.g. ActionListener in graphics which couples together two graphical objects, e.g. window & button
Mediator (Non software example)
Loose coupling
between colleague
objects is achieved by
having colleagues
communicate with the
Mediator, rather than
one another.
Mediator (Software counterpart)
Gtalk Server
M
EDIATORS
TRUCTURE Mediator ConcreteMedi ator mediator 1 * * Colleague Concrete Colleague1 Concrete Colleague2Colleagues send and receive requests from a Mediator object. The mediator implements the cooperative
behavior by routing requests between appropriate colleagues.
E
XAMPLE: T
OP-D
OWND
ESIGN Mediator File_Selector mediator 1 * * ColleagueBrowser Button Text_Field
C
OMMENTSFaçade, unlike Mediator, abstracts a subsystem of objects to provide a convenient interface.
Unidirectional. Façade objects make requests of the
subsystem, but not vice-versa.
Mediator enables cooperative behaviour, that colleagues don’t or can’t provide. Multidirectional.
Observer pattern and Mediator both receive notification of changes.
Observer does so through an abstract mechanism. Allows source of notification to be independent of its observers. In Mediator, the source must know its mediator. This makes it possible for mediator to define reactions to each stimulus.
5.8. P
ATTERN: O
BSERVER(B
EHAVIORAL)
Name: Observer
Problem: Define a one-to-many dependency
among objects so that when one object changes state, all of its dependents are notified and updated automatically.
Solution: MVC, but refined by separating
abstract from concrete subjects and observers
Observer (Non software example)
When an object
changes its state,
all its dependants
are notified.
Structure of Observer Pattern
34
Getstate() setState()
ConcreteSubject notifies its observers whenever a change occurs that could make its observers state inconsistent with its own
After being informed of change, a ConcreteObserver queries the subject to reconcile its state with subjects.
Observer object that initiates change request postpones its update until it gets notification from subject. Notify() is not always called by subject. Can be called by an observer, or any other object.
:ConcreteSubject :ConcreteObserver :ConcreteObserver setState( ) notify( ) update( ) getState( ) update( ) getState( ) 36
5.9. P
ATTERN: M
OCKO
BJECTA pattern where coupling an objects coupling to another complex object is replaced by coupling to a simplified proxy.
C.f. dummy methods in whishful thinking
Coupling between objects could well be an interface. Then the mock and real objects implement this interface. Used e.g. in testing objects. (see Section 8)
I
TERATOR(B
EHAVIORAL)
Intent
⚫ Access elements of an aggregate sequentially without exposing its representation
Applicability
⚫ Require multiple traversal algorithms over an aggregate
⚫ Require a uniform traversal interface over different aggregates
⚫ When aggregate classes and traversal algorithm must vary independently
I
TERATOR(
CONT'
D)
I
TERATORE
XAMLEimport java.util.*; class IntSet {
private Hashtable ht = new Hashtable(); public static class Iterator {
private IntSet set;
private Enumeration e; private Integer current;
public Iterator( IntSet in ) { set = in; }
public void first() { e = set.ht.keys(); next(); } public boolean isDone() { return current == null; } public int currentItem() { return current.intValue(); }
public void next() { try { current = (Integer) e.nextElement();
} catch (NoSuchElementException e) { current = null; } }
}
public void add( int in ) { ht.put( new Integer( in ), "null" ); }
public boolean isMember( int i ) { return ht.containsKey(new Integer(i)); } public Hashtable getHashtable() { return ht; }
public Iterator createIterator() { return new Iterator( this ); } }
I
TERATORE
XAMPLEclass IteratorDemo {
public static void main( String[] args ) { IntSet set = new IntSet();
………. // Code to add elements to the set and other code
// Clients ask the collection object to create many iterator objects IntSet.Iterator it1 = set.createIterator();
IntSet.Iterator it2 = set.createIterator();
// Clients use the first(), isDone(), next(), currentItem() protocol System.out.print( "\nIterator: " );
for ( it1.first(), it2.first(); ! it1.isDone(); it1.next(), it2.next() )
System.out.print( it1.currentItem() + " " + it2.currentItem() + " " ); System.out.print( "\nEnumeration: " );
for (Enumeration e = set.getHashtable().keys(); e.hasMoreElements(); ) System.out.print( e.nextElement() + " " );
System.out.println(); }
I
TERATOR(
CONT'
D)
Consequences
+ Flexibility: aggregate and traversal are independent + Multiple iterators → multiple traversal algorithms
⚫ Additional communication overhead between iterator and aggregate
Implementation
⚫ Internal versus external iterators
⚫ Violating the object structure's encapsulation
⚫ Robust iterators
P
ATTERN: F
ACTORYName: (Abstract) Factory
Problem: Provide an interface for creating
families of related or dependent objects without specifying their concrete classes.
Control instantiation
Singleton is a special case of Factory where only one object can be created.
F
ACTORYS
TRUCTURE AbstractProduct ConcreteProd uct1 AbstractFactor y ConcreteFact ory FactoryMethod() AnOperation() FactoryMethod() Product = FactoryMethod() return new ConcreteProduct()44Normally, a single instance of a ConcreteFactory class is created at runtime.
This creates product objects having a particular implementation.
To create different product objects, clients should use a different concrete factory.
AbstractFactory defers creation of product objects to its ConcreteFactory subclasses.
MyClass
createObjectOfRequiredClass():RequiredClass
Factory design pattern
Client RequiredClass
Factory Class Model
create objects
F
ACTORYE
XAMPLEE.g. create objects of different types We can order a Car and get an
Aston Martin, MG, Jaguar etc
We don’t know which factory builds the car, just that they implement CarFactory. Owner has created the actual factory instance.
// we have a reference to owner
CarFactory aFactory = owner.makefactory();
Car myCar =aFactory.makeCar(“AstonMartin”);
class BritishFactory implements CarFactory{
public Car makeCar(String b) throws Exception {
if(b.equals(“AstonMartin”)) return new
AstonMartin();
else if (..) return ..;
else throw new Exception(b + “doesn’t
exist”);
}
}
Class AstonMartin extends Car {}
Class Jaguar extends Car {}
Interface CarFactory {
Public Car makeCar(String b) throws
Exception;
Abstract Factory classes are often implemented with the Factory Method pattern.
Can also be implemented using the Prototype pattern. A concrete factory is often a Singleton.
Comments
5.11 C
OMMANDName: Command
Problem: Need a flexible organization for
methods that allows them to be context sensitive in a structured way.
Solution: Place behaviour /operation in an
E
XAMPLESUndo. It’s difficult to undo effects of an arbitrary
method. Methods vary over time.
Choose menu option. Whether an option can be chosen
at any time depends on many factors.
C
OMMANDS
TRUCTURE Command ConcreteCom mand Execute() Execute() State Receiver.Action() Invoker Client 1 Receiver Action() 1 receiverClient creates a ConcreteCommand object and specifies its receiver.
An Invoker object stores the ConcreteCommand object The invoker issues a request by calling Execute on the command. When commands are undoable,
ConcreteCommand stores state for undoing the command before invoking Execute
ConcreteCommand object invokes operations on its receiver to carry out request
aClient aCommand anInvoker aReceiver
new Command(aReceiver)
Execute() storeCommand(aCommand)
C
OMMENTSPattern replaces function pointers (passing functions as
parameters) which is not available in some languages.
Pattern allows a class to call a receivers routine without knowledge of it. Gives high degree of decoupling
between caller and callee.
C
OMMAND(C
ONT.)
Client:
Command command = Command.getCommand (…);
Command.execute();
A Factory method first gives a Command object (means object can depend on current situation)
class Command {
public void execute() {
if (check-something) { //menu item
selectable?
this.getParameters(); //preparation
getTarget1().action1(); //do something
}
else
// do something else,
// like other action or target
}
}
R
ELATEDP
ATTERNSA Memento pattern can be used the keep the state a command needs to undo its effect.
A command that must be copied before being placed on the history list acts as a Prototype pattern.
G
UIDELINESC
HECKLISTIs there a pattern that addresses my problem?
Does the pattern provide an acceptable solution?
Is there a simpler solution? (pattern overuse)
Is the context of the pattern consistent with my
problem?
Are the consequences of using the pattern
acceptable?
Are there forces in my environment that conflict
with the use of the pattern?
B
ENEFITS ANDD
ANGERS+ support software reuse
+ language for discussing high-level problems + access to experience and knowledge
- limit creativity?
- needs a culture of reuse
References
• The Timeless Way of Building, Alexander; Oxford, 1979; ISBN 0-19-502402-8
• A Pattern Language, Alexander; Oxford, 1977; ISBN 0-19-501-919-9 • Design Patterns, Gamma, et al.; Addison-Wesley, 1995; ISBN
0-201-63361-2; CD version ISBN 0-201-63498-8
• Pattern-Oriented Software Architecture, Buschmann, et al.; Wiley, 1996; ISBN 0-471-95869-7
• Analysis Patterns, Fowler; Addison-Wesley, 1996; ISBN 0-201-89542-0
• Smalltalk Best Practice Patterns, Beck; Prentice Hall, 1997; ISBN 0-13-476904-X
• The Design Patterns Smalltalk Companion, Alpert, et al.; Addison-Wesley, 1998; ISBN 0-201-18462-1
• AntiPatterns, Brown, et al.; Wiley, 1998; ISBN 0-471-19713-0