Design Patterns - Georgia Institute of Technology
Download
Report
Transcript Design Patterns - Georgia Institute of Technology
Design Patterns
Mechanisms for improving
software reuse
Story
What are Design Patterns?
An example pattern
Why do we care about them?
Example Design Patterns
Creational
Structural
Behavioral
Design Patterns in Smalltalk
7/20/2015
Copyright 2000, Georgia Tech
2
References
Design Patterns: Elements of Reusable
Object-Oriented Software
“Gang of Four”: Erich Gamma, Richard
Helm, Ralph Johnson, John Vlissides
(Addison-Wesley, 1995)
Best-selling Computer Science book ever
The Design Patterns Smalltalk
Companion
Sherman R. Alpert, Kyle Brown, Bobby Woolf
7/20/2015(Addison-Wesley,
Copyright1998)
2000, Georgia Tech
3
What are Design Patterns?
Codified standard practices of expert designers
“Recorded experience in designing object-oriented
software” – Gang of Four
“A reusable implementation model or architecture
that can be applied to solve a particular recurring
class of problem” — Alpert et al.
Definitely not innovative, unique approaches
Instead, tried-and-true, worth reusing practices
Practices that address common design problems
Practices that help improve reusability
7/20/2015
Copyright 2000, Georgia Tech
4
Pieces of a Design Pattern
Pattern Name
Problem: When to apply the pattern
Solution: The elements that make up the design,
their relationships, responsibilities,
collaborators.
Not a concrete design or implementation, but a
template
Consequences: Results and tradeoffs of the
pattern
7/20/2015
Copyright 2000, Georgia Tech
5
Your first pattern: Observer
“Intent: Define a one-to-many dependency between
objects so that when one object changes state, all its
dependents are notified and updated automatically.” –
G4
Participants:
(Abstract) Subjects: Know observers and can attach/detach
them
(Abstract) Observers: Can update() when notified of changes
ConcreteSubjects maintain state for subject
ConcreteObservers maintain a relationship with the ConcreteSubject
7/20/2015
Copyright 2000, Georgia Tech
6
Observer Structure
*
Subj ect
dependents
addDependent: anObser ver
removeDependent: anObserver
chang ed: aSymbol
Obser ver
update: aSymbol
dependents do: [ :observer |
observer update: aSymbol]
Concr eteSubject
subjectState
1
s ubjec t
obser ver State
subjectState
subjectState: anObj ect
7/20/2015
Concr eteObserver
update: aSymbol
Copyright 2000, Georgia Tech
7
An instantiation of Observer:
MVC!
You’ve seen this before!
All the issues are the same!
Subjects are Models
Your application specific Models are
ConcreteSubjects
User Interface Components (Views) are Observers
The specific UI components you use in your
application are ConcreteObservers
Observer is also the pattern being used in Java’s
Listener class in Swing
7/20/2015
Copyright 2000, Georgia Tech
8
Using Observer
Use the observer pattern when…
A change to one object requires updating many
When an object should be able to notify other objects
without making assumptions about who those objects
are (loosely coupled)
When an abstraction has two aspects, one
dependent on the other, but you want to vary and
reuse them independently
Note: These are not just about UI!
7/20/2015
Copyright 2000, Georgia Tech
9
Consequences of Observer
Abstract coupling between Subject and
Observer
Could be an issue in large, multi-layered system
Requires support for broadcast communication
Freedom to add/remove observers anytime
Can be computationally expensive
Unexpected updates
Observer and subjects are blind to the costs of
sending each other messages
7/20/2015
Copyright 2000, Georgia Tech
10
Implementation Issues
How track observers?
Observing more than one subject is complex
Who triggers the update?
Beware that subject state is updated before
notifying
Avoid observer-specific update protocols: Push
vs. Pull
Specifying aspects of interest explicitly
Encapsulating complex update semantics
7/20/2015
Copyright 2000, Georgia Tech
11
Patterns in Architecture
“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” — Christopher Alexander
Alexander is an Architect who has been
collecting patterns in Architecture for years
Standard ways of solving problems
7/20/2015
Copyright 2000, Georgia Tech
12
Patterns in Cognitive Science
Experts do think in pattern-like elements
Sometimes called “chunks” or “plans”
Shown by Herb Simon for Chess
Shown by Elliot Soloway for Software
Can we teach these patterns to people to
make them better designers?
7/20/2015
Copyright 2000, Georgia Tech
13
Describing Design Patterns
Name and
classification
Intent
Also Known As (AKA)
Motivation
Applicability
Structure
Participants
7/20/2015
Collaborations
Consequences
Implementation
issues
Sample code
Known uses
Related Patterns
Copyright 2000, Georgia Tech
14
Classifications of Design Patterns
Creational
Make a system independent of how its objects are
created, composed, and represented
Structural
How classes and objects are composed to form
larger structures
Behavioral
The patterns of communication between objects
7/20/2015
Copyright 2000, Georgia Tech
15
Patterns for Reuse
Patterns build heavily on composition and
delegation
Inheritance is a “white box” form of reuse
Its faster and straightforward
But requires a lot of knowledge of superclass
Composition and delegation is “black box” reuse
Keeps details hidden away
In general, program to an interface, not an
implementation
7/20/2015
Copyright 2000, Georgia Tech
16
Design Patterns Solve Common
Reuse Problems
Example 1: Creating an object by
specifying a class explicitly
If you specify a class name when you create
an object, you’re committing to a particular
implementation (that class) as opposed to a
particular interface (e.g., features that you
need)
To avoid it, create objects indirectly
Solutions are Creational patterns
7/20/2015
Copyright 2000, Georgia Tech
17
Solution to #1:
Factory Method Pattern
Intent: Define an interface for creating an
object, but let subclasses decide which
class to instantiate
Have a factory method (perhaps, take a
parameter that tells you the kind of object
you want) decide which object to give you
Example: Application suite that can create
Word Processing, Spreadsheet, Draw
documents
7/20/2015
Copyright 2000, Georgia Tech
18
Factory Method Applicability
Use it when…
A class can’t anticipate the class of objects it
must create
A class wants its subclasses to specify the
objects it creates
You want to localize the knowledge of which
specific class gets created for a specific
purpose
7/20/2015
Copyright 2000, Georgia Tech
19
Factory Method Participants
Product: Defines the interface of objects that the
factory method creates (e.g., all documents can
open, close, save, etc.)
ConcreteProduct: Implements the Product
interface (e.g., a WP document)
Creator: Defines the Factory Method
ConcreteCreator: Overrides the Factory Method
to create an instance of ConcreteProduct
7/20/2015
Copyright 2000, Georgia Tech
20
Factory Method Structure
Product
Creator
FactoryMethod: someSpec
Concr eteCr eator
Concr etePr oduct
FactoryMethod
7/20/2015
Copyright 2000, Georgia Tech
21
Consequences of Factory Method
Disadvantage: You have to have a
ConcreteCreator class for every product
you create
You need to provide hooks for subclasses
Connects parallel class hierarchies
Makes class evolution and development a
little more complex
7/20/2015
Copyright 2000, Georgia Tech
22
Implementing Factory Method
in Smalltalk
Imagine a CarBuilder abstract class, with
subclasses FordBuilder and ToyotaBuilder
Each wants to build 4 cylinder cars
addFourCylinderEngine “in CarBuilder”
self car addEngine: self fourCylinderEngine
fourCylinderEngine “in FordBuilder”
^Ford4CylinderEngine new
fourCylinderEngine “in ToyotaBuilder”
^Toyota4CylinderEngine new
7/20/2015
Copyright 2000, Georgia Tech
23
Alternative Factory Method
Implementation in Smalltalk
Return the class itself!
addFourCylinderEngine “in CarBuilder”
self car addEngine: self fourCylinderEngine
fourCylinderEngine “in CarBuilder”
^self myFourCylinderEngineClass new
myFourCylinderEngineClass “in FordBuilder”
^Ford4CylinderEngine
myFourCylinderEngineClass “in ToyotaBuilder”
^Toyota4CylinderEngine
7/20/2015
Copyright 2000, Georgia Tech
24
Related Pattern: Abstract Factory
Intent: Provide an interface for creating
families of related or dependent objects.
In some sense, select a class which has
the Factory Methods you need
7/20/2015
Copyright 2000, Georgia Tech
25
Abstract Factory Example
CarPart
CarPartFactory
CarBody
CarEngine
FordFactor y
makeBody
makeEng ine
FordBody
7/20/2015
ToyotaBody
FordEngi ne
ToyotaFactor y
makeBody
makeEng ine
ToyotaEngi ne
Copyright 2000, Georgia Tech
26
Abstract Factory Code
myFactory := self factory. “FordFactory or
ToyotaFactory returned.”
myEngine := myFactory makeEngine.
myBody := myFactory makeBody.
7/20/2015
Copyright 2000, Georgia Tech
27
Problem #2: Hardware/software
dependence
Redesign/reuse problem #2:
Hardware/software dependence
You want to limit your dependency on
software specifics or hardware specifics
Can solve this with an Abstract Factory
Can also solve this with the Behavioral
Pattern, Bridge
7/20/2015
Copyright 2000, Georgia Tech
28
Bridge Pattern
Intent: Decouple an abstraction from its
implementation so that the two can vary
independently
Basically, separate the interface and
implementation so that the two can vary
independently
Classic example: All windowing systems offer
similar functionality, but vary in implementation/interface
7/20/2015
Copyright 2000, Georgia Tech
29
Bridge Pattern Example
Wi ndow
implementati on
Wi ndowImpl ementati on
MacWi ndowI mplementation
7/20/2015
Copyright 2000, Georgia Tech
Wi nW indowI mplementation
30
Interesting Uses for Bridges
Not just to hide platform dependencies!
IBM Smalltalk separated collections into
implementations and interfaces
If a Set was small, stored in a
LinearSetImplementation
If a Set was large, stored in a
LinearHashSetImplementation
Programmer-User only saw the same Set interface—
the implementation changed invisibly
7/20/2015
Copyright 2000, Georgia Tech
31
When to Bridge
You want to avoid a permanent binding
between an abstraction and its
implementation
Both abstraction and implementation
might be extensible via subclassing
Changes in implementation should not
impact clients of the abstraction
7/20/2015
Copyright 2000, Georgia Tech
32
Bridge Implementation Issues
What if only one implementor?
Still might be useful
In Java/C++, can avoid changing client, just
re-link
Choosing the right implementation object
May have to change later, depending on
size, platform, etc.
Can use a factory to choose implementation
for us!
7/20/2015
Copyright 2000, Georgia Tech
33
Problem #3: Dependence on
Specific Operations
Reuse/Redesign Problem #3: When you specify
a particular operation, you are committing to one
way of satisfying a request.
If you can remain flexible with how you respond
to requests, you make it easier to change, even
(in C++/Java/etc.) at run-time or compile-time
One solution design pattern: Command
7/20/2015
Copyright 2000, Georgia Tech
34
Command—A Behavioral Design
Pattern
Intent: Encapsulate a request as an object,
thereby letting you parameterize clients with
different requests, queue or log requests, and
support undoable operations.
AKA: Action, or Transaction pattern
Sometimes, you want to ask an object to do
something without knowing the actual message
name or even the receiver of the message.
Do this by making the request itself be an object
7/20/2015
Copyright 2000, Georgia Tech
35
Motivation for Command
An Application wants to have a Menu that
sends commands to Documents like
Open, Close, Paste, Copy
The MenuItem doesn’t necessarily know
which document gets the command
The MenuItem may not even know which
message the document understands
Further, the creation of an inverse (for Undo)
is not the Menu’s responsibility
7/20/2015
Copyright 2000, Georgia Tech
36
Command Structure
Cli ent (Applicati on)
Invoker (MenuItem)
Command
execute
Receiver (Document)
acti on
Concr eteCommand (Paste,Open)
receiver
execute
execute
receiver acti on
7/20/2015
Copyright 2000, Georgia Tech
37
Command Participants
Command: Declares the interface for an
operation
ConcreteCommand: Binds a Receiver and an
action
Implements Execute()
Client: Creates ConcreteCommand, sets its
receiver
Invoker: Asks command to carry out request
Receiver: Knows how to do the operation
7/20/2015
Copyright 2000, Georgia Tech
38
Use Command when you want
to...
Parameterize objects by an action to perform (e.g.,
menuItem and pushButton both do same Command
object)
Specify, queue, and execute requests at different times
Support undo or redo (put Commands in a stack or
queue)
Support logging changes
Structure a system around high-level operations built on
primitive operations
7/20/2015
Copyright 2000, Georgia Tech
39
Command Consequences
Command decouples the object invoking
operation from one that performs it
Commands are first-class objects that can be
subclassed, etc.
Commands can be assembled into macros
It’s easy to add new Commands—you don’t
actually have to change existing classes
7/20/2015
Copyright 2000, Georgia Tech
40
Smalltalk Pluggable Command
Create a class PluggableCommand with
instance variables receiver, selector, and
arguments
command := PluggableCommand
receiver: self
selector: #cut
arguments: (Array with: myTextPane)
7/20/2015
Copyright 2000, Georgia Tech
41
PluggableCommand execute
execute “PluggableCommand”
^self receiver perform: self selector
withArguments: self arguments
7/20/2015
Copyright 2000, Georgia Tech
42
Design Problem #4: Adapter
Design problem #4: Inability to alter
classes conveniently
Sometimes you have to change something
(e.g., you need an interface to be like this, but
it’s implemented like that), but you can’t easily
— it’s a system that you don’t have source to,
or it’s in another language, or it’s big and
complicated
Solution: Structural pattern adapter
7/20/2015
Copyright 2000, Georgia Tech
43
Structural pattern Adapter
Intent: Convert the interface of a class into
another interface clients expect.
Basically, put a “wrapper” around something,
so that it looks right
Pluggable components do this!
Essentially, they let a standard interface work for
any UI component
7/20/2015
Copyright 2000, Georgia Tech
44
Adapter Structure
Cli ent
Tar get
request: anyParam
Adaptee
Adapter
req uest: anyParam
adaptee
hardToReuseReq uest: somePar am
req uest: anyParam
adaptee har dToReuseRequest: anyPar am
7/20/2015
Copyright 2000, Georgia Tech
45
Adapter Participants
Target: Defines the domain-specific
interface for the Client
Client: Collaborates with objects using the
Target interface
Adaptee: Defines the existing interface
Adapter: Makes the adaptee more usable
by implementing the Target interface and
using it to adapt the adaptee
7/20/2015
Copyright 2000, Georgia Tech
46
Adapter Consequences
Adapter adapts for all subclasses of
adaptee, too
Adapter makes it harder to override
adaptee behavior—have to make adapter
talk to adaptee subclass
7/20/2015
Copyright 2000, Georgia Tech
47
Parameterized Adapters in
Smalltalk
Define a class ParameterizedAdapter with
instance variables adaptee, getBlock, and
setBlock.
adapter := ParameterizedAdapter on: someObject.
Adapter getBlock: [:x | “something that gets a
value for someObject”];
setBlock: [:x | “Something that sets a value for
someObject”].
7/20/2015
Copyright 2000, Georgia Tech
48
Arguments Against Patterns
Maybe these are things that should just be
language features?
Alexander’s approach has not been accepted in
Architecture
His efforts in defining patterns have only described a
few small classes of buildings (e.g., cottages)
Real experts have lots of chunks
Simon estimates 10,000 of them
John Anderson says that you can’t teach them
directly, only through experience
7/20/2015
Copyright 2000, Georgia Tech
49