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