Sie sind auf Seite 1von 32

Design Patterns

CS 580
By Robert Stehwien

Recommended Reading
and Lecture Sources
• “Design Patterns: Elements of Reusable Object-
Oriented Software” by Erich Gamma, Richard
Helm, Ralph Johnson, John Vlissides
• “Refactoring to Patterns” by Joshua Kerievsky
– http://www.industriallogic.com
• “Head First Design Patterns” by Eric Freeman &
Elisabeth Freeman with Kathy Sierra & Bert
Bates
• “Object-Oriented Design Heuristics” by Arthur J.
Riel

1
What’s a pattern?
• A pattern is a named abstraction from a concrete form
that represents a recurring solution to a particular
problem.
• Patterns = problem/solution pairs in context
• Patterns facilitate reuse of successful software
architectures and design
• Not code reuse
– Instead, solution/strategy reuse
– Sometimes, interface reuse
• Best practices
• “Patterns are discovered, not invented” - Richard Helm

Patterns and Language


• Most design patterns focus on OO
– Assume inheritance, polymorphism, encapsulation, etc.
• In procedural languages, might add OO features as
“patterns”
• Some languages provide or make it easier to implement
some patterns
– http://www.c2.com/cgi/wiki?AreDesignPatternsMissingLanguageFeatures

• Covering generic OO patterns not concurrency, domain


specific, UI, etc.

2
Categories of Patterns
• Design patterns vary in granularity and level
of abstraction.
• By categorizing patterns, it becomes easier
to recognize and learn them
• Categorized by purpose or scope
• Purpose reflects what the pattern does
• Scope specifies if the pattern applies to
classes or objects

Purpose
• Reflects what the pattern does
• Creational – facilitate object creation
• Structural -- deal with the composition of
classes or objects
• Behavioral -- deal with the way objects
interact and distribute responsibility

3
Scope

• Whether the pattern applies to classes or


objects
• Class Patterns:
– Deal with relationships between classes or
subclasses established through inheritance
– These relationships are fixed at compile time
• Objects patterns:
– Deal with object relationships that can be
changed at runtime

Other Ways to Organize Patterns

• Some patterns are frequently used with


other patterns, for example composite is
often used with visitor and/or iterator
• Some patterns are alternatives: Prototype is
usually an alternative for Abstract Factory
• Some patterns are very similar in structure,
such as Composite and Decorator

4
How do Design Patterns Solve
Design Problems?
• The meaning of OO is well-known
• The hard part is decomposing the
system into objects to exploit:
– encapsulation
– flexibility, extensibility
– ease of modification
– performance
– evolution
– reusability

Finding Objects

• Many objects in the design come from


the analysis model
• But OO designs often end up with
classes that have no counterpart in the
real world
• Design Patterns help the modeler to
identify less obvious abstractions and
the objects that can capture them.

5
Inheritance
• Inheritance is a mechanism for reuse
• You can define a new kind of object in
terms of the old one
• You get new implementations almost for
free, inheriting most of what you need from
an existing class
• This is only half the story!

Program to an interface,
not an implementation
• Inheritance permits defining a family of
objects with identical interfaces
• Polymorphism depends on this!
• All derived classes share the base class
interface
• Subclasses add or override operations,
rather than hiding operations
• All subclasses then respond to requests in
the interface of the abstract class

6
Inheritance properly used
• Clients are unaware of types of objects: heuristic
5.12 - “explicit case analysis on the type of an
object is usually an error. The designer should use
polymorphism”. Riel
• Clients only know about the abstract classes
defining the interface. heuristic 5.7: “All base
classes should be abstract”. Riel
• This reduces implementation dependencies
• Program to an interface, not an implementation
• Creational patterns help ensure this rule!

Two techniques for reuse


• Inheritance: White box
• Object Composition: Black box

7
Advantage of Inheritance for
Reuse
• Defined statically
• Supported directly by the language:
straightforward to use
• Easier to modify implementation being
reused

Disadvantage of Inheritance
• Can’t change inherited implementation at
run-time
• Parent classes often define part of their
subclasses physical representation
• Because inheritance exposes the parent
implementation it’s said to “break
encapsulation” (GOF p.19, Sny86)
• Change in parent => Change in subclass
• If inherited attribute is inappropriate?

8
Duck Example

Duck demo courtesy of “Head First Design Patterns”

Extending Duck
• Static ducks not enough to compete
• Ducks need to fly()
• Inheritance seems like a good way to go

9
Flying Duck 1

Sadly Rubber Duckies


• Don’t quack(); already overidden to
squeak
• Don’t fly at all; overide to do nothing?

• What about DecoyDucks


– They don’t quack or fly

10
Decoy and Rubber Ducks

What about Interfaces?

11
Object Composition:
Black Box Reuse
• Objects are accessed solely through their
interfaces: no break of encapsulation
• Any object can be replaced by another at
runtime: as long as they are the same type
• Favor object composition over class
inheritance. GOF p. 20
• But inheritance & composition work
together!

Delegation

• “a way of making composition as powerful


for reuse as inheritance”:
– GOF, p. 20
– [JZ91] Ralph Johnson and Jonathan Zweig,
Delegation in C++, JOOP, f(11):22-35, Nov.
91
– [Lie86] Henry Lieberman. Using prototypical
objects to implement shared behavior in OO
systems. OOPSLA, pp 214-223, Nov. ‘86

12
Delegation: Reuse
• In delegation, 2 objects handle a request
• Analogous to subclass deferring request to
parent
• In delegation, the receiver passes itself to
the delegate to let the delegated operation
refer to the receiver!

Delegating area() to Rectangle

Rectangle
Window
rectangle area()
area() width
height

return rectangle->area()
return width*height

13
Advantages of Delegation
• Can change behaviors at run-time
• Window can become circular at run-time
by replacing Rectangle with Circle,
(assuming Rectangle & Circle are same type!)
• There are run-time costs.
• Delegation in patterns: State, Strategy,
Visitor, Mediator, Bridge

Redesigned Duck

14
Encapsulated Quack Behavior

Encapsulated Fly Behavior

15
Strategy Pattern
• Surprise! That is the strategy pattern
• Strategy Pattern:
– Defines a family of algorithms, encapsulates
each one, and makes them interchangeable.
– Strategy lets the algorithm vary independently
from clients that use it

Patterns Make Design Resistant to Re-Design


Robustness to Change
• Algorithmic dependencies: Template Method, Visitor,
Iterator, Builder, Strategy.
• Creating an object by specifying a class explicitly:
Abstract Factory, Factory Method, Prototype
• Dependence on specific operations: Command, chain of
responsibility
• Dependence on object rep or impl: Abstract Factory,
Bridge, Proxy
• Tight coupling: Abstract Factory, Command, Facade,
Mediator, Observer, Bridge

16
Patterns Make Design Resistant to Re-Design
Robustness to Change
• Extending functionality by subclassing:
Command, Bridge, Composite, Decorator,
Observer, Strategy
• Inability to alter classes conveniently: Visitor,
Adapter, Decorator

Design Confidence
• Design Inexperience: “Is my design ok?”
• Patterns engender confidence
– used twice & blame the GOF
– still room for creativity

• Guidelines to prevent Under-Engineering


– Time constraints often force production of poorly
designed code
– Leads to unmaintainable code

17
Design Coverage
• Large portion of design can be covered by
patterns
• Seductively simple to implement
– most explained in a few pages
– add no “extra-value” to end-user
• You still have to write functionality:
patterns don’t solve the problem

Design Understanding
• “Most” people know the patterns
If you’re looking at someone’s design & you
identify a pattern, you immediately understand
much of the design
• Common design vocabulary
– “Let’s use a Builder here”
• Design language beyond language syntax
– problem oriented language
– program in rather than into the language

18
Common Problems
• Getting the “right” pattern
• Taming over-enthusiasm
– you “win” if you use the most patterns
– everything solved by the last pattern you
learned
• Over-Engineering
– More sophisticated or flexible than necessary

Criticisms
• Targets wrong problem
– Missing language features
• Lacks formal foundations
• Does not provide reuse (like components)
• Leads to inefficient solutions
• Does not differ significantly from other
abstractions
– Model-View-Controller predates GoF patterns

19
How to select a pattern
• Know a basic catalog
• Scan intent section
• Study patterns of like purpose
• Consider a cause of redesign

• Refactor toward or away from patterns to


avoid over/under design

Overview of Creational Patterns


• Abstract the instantiation process
• Help make a system independent of how its
objects are created, composed, represented
• A class creational pattern uses inheritance to
vary the class that’s instantiated
• An object creational pattern delegates
instantiation to another object

20
Creational Patterns
• Abstract Factory: Provide an interface for creating families of
related or dependent objects without specifying their concrete class.
• Builder: Separate the construction of a complex object from it
representation so that the same construction process can create
different representations.
• Factory Method: Define an interface for creating an object, but let
subclasses decide which class to instantiate. Factory Method lets a
class defer instantiation to subclasses.
• Prototype: Specify the kinds of objects to create using a protypical
instance, and create new objects by copying this prototype.
• Singleton: Ensure a class only has one instance, and provide a
global point of access to it.

Structural Patterns (1)


• Deal with the composition of classes or objects

• Adapter: Convert the interface of a class into another


interface clients expect. Adapter lets classes work
together that couldn’t otherwise because of incompatible
interfaces.
• Bridge: Decouple an abstraction from its implementation
so that the two can vary independently.
• Composite: Compose objects into tree structures to
represent part-whole hierarchies. Composite lets clients
treat individual objects and compositions of objects
uniformly.

21
Structural Patterns (2)
• Decorator: Attach additional responsibilities to
an object dynamically. Decorators provide a
flexible alternative to subclassing for extending
functionality.
• Façade: Provide a unified interface to a set of
interfaces in a subsystem. Façade defines a
higher-level interface that makes the subsystem
easier to use.
• Flyweight: Use sharing to support large
numbers of fine-grained objects efficiently.
• Proxy: Provide a surrogate or placeholder for
another object to control access to it.

Behavioral Patterns (1)


• Deal with the way objects interact and distribute
responsibility

• Chain of Responsibility: Avoid coupling the sender of a


request to its receiver by giving more than one object a
chance to handle the request. Chain the receiving
objects an dpass the request along the chain until an
object handles it.
• Command: Encapsulate a request as an object, thereby
letting you paramaterize clients with different requests,
queue or log requests, and support undoable operations.
• Interpreter: Given a language, define a representation
for its grammar along with an interpreter that uses the
representation to interpret sentences in the language.

22
Behavioral Patterns (2)
• Iterator: Provide a way to access the elements of an
aggregate object sequentially without exposing its
underlying representation.
• Mediator: Define an object that encapsulates how a set
of objects interact. Mediator promotes loose coupling by
keeping objects from referring to each other explicitly,
and lets you vary their interaction independently.
• Memento: Without violating encapsulation, capture and
externalize an object’s internal state so that the object
can be restored to this state later.
• Observer: Define a one-to-many dependency between
objects so that when one object changes state, all its
dependents are notified and updated automatically.

Behavioral Patterns (3)


• State: Allow an object to alter its behavior when its
internal state changes. The object will appear to change
its class.
• Strategy: Define a family of algorithms, encapsulate
each one, and make them interchangeable. Strategy
lets the algorithm vary independently from clients that
use it.
• Template Method: Define the skeleton of an algorithm
in an operation, deferring some steps to subclasses.
Template Method lets subclasseses redefine certain
steps of an algorithm without changing the algorithm’s
structure.
• Visitor: Represent an operation to be performed on the
elements of an object structure. Visitor lets you define a
new operation without changing the classes of the
elements on which it operates.

23
Study Guide (1)
• Courtesy of the author of "Refactoring to Patterns"
– http://www.industriallogic.com/papers/learning.html

• (C) Factory Method: Begin with Factory Method. This pattern is


used by a number of patterns in the book and throughout the
patterns literature.
• (B) Strategy: Strategy is used frequently throughout the book, and
an early knowledge of it helps in understanding other patterns.
• (S) Decorator: For an early dose of elegance, nothing is better than
the Decorator. The discussion of "skin" vs. "guts" is a great way to
differentiate Decorator from the previous pattern, Strategy.
• (S) Composite: The Composite pattern appears everywhere and is
often used with Iterator, Chain of Responsibility, Interpreter, and
Visitor patterns.
• (B) Iterator: Reenforce the reader's understanding of Composite by
studying Iterator.

Study Guide (2)


• (B) Template Method: The author's footnote to Iterator explains that
a method called "Traverse" in the Iterator example code is an
example of a Template Method. This pattern also reenforces
Strategy and Factory Method.
• (C) Abstract Factory: The reader now returns to the second-easiest
creational pattern, the Abstract Factory. This pattern also helps
reenforce Factory Method.
• (C) Builder: The reader now may compare another creational
pattern, the Builder, with the Abstract Factory.
• (C) Singleton: Singleton is often used to model Abstract Factories,
as the "Related Patterns" section of Singleton describes.
• (S) Proxy: The reader now has a chance to learn how Proxy is used
to control access to an object. This pattern leads directly into the
next pattern, Adapter.
• (S) Adapter: The Adapter pattern may be compared with what the
reader understands about Decorator, Proxy, and later, Bridge.

24
Study Guide (3)
• (S) Bridge: Finally, the reader learns how the Bridge pattern differs
from both the Adapter and Proxy patterns.
• (B) Mediator: Now the reader learns the Mediator pattern, in
preparation for understanding Observer and the Model-View-
Controller design.
• (B) Observer: Discover how the Mediator is used by the Observer to
implement the classic Model-View-Controller design.
• (B) Chain of Responsibility: After exploring how messages are
passed using the Observer and Mediator patterns, the reader now
may contrast how messages are handled by the Chain of
Responsibility pattern.
• (B) Memento: The reader now moves on to Memento. This pattern
leads directly into a discussion of undo and redo, which is related to
the next pattern, Command.
• (B) Command: The Command pattern is used in a number of ways,
one of which relates to the previous pattern, Mediator.

Study Guide (4)


• (C) Prototype: Perhaps the most complex creational pattern,
Prototype is often used with the Command pattern.
• (B) State: The reader may now study State to understand another
way an object's behavior changes.
• (B) Visitor: Visitor is often combined with the Composite and/or
Iterator patterns.
• (S) Flyweight: The Flyweight pattern is one of the more complex
patterns. An examples use of this pattern is described in the next
pattern, Interpreter.
• (B) Interpreter: The Interpreter pattern is complex. It makes
reference to and helps reinforce one's understanding of Flyweight
and Visitor.
• (S) Facade: The final pattern to read is Facade. Facade is relatively
straightforward and follows nicely after Interpreter since the example
code is similar in theme to example code in the Interpreter.

25
Factory Method:
Motivating example
• Consider class Number with derived
classes BigInt and Complex, with most
derived class operations as virtual in
Number.
• Users can use a pointer or reference to
Number, bind the pointer to any of the
member of the hierarchy and interact
without knowing what “it” is!

Factory Method:
Number Hierarchy
Number
Users of this hierarchy
can interact with any
“number”, treating them
all equally.

Complex BigInt But how does an object


get created?

26
Factory Method:
virtual constructors
• We may want the instantiation to be
accomplished from w/in the hierarchy
• perhaps when number becomes too large,
Number switches to a BigInt
• perhaps when the user takes the sqrt of a
negative number, “it” switches to a
Complex

When to use Factory Method


• A class can’t anticipate the class of objects
it must create
• a class wants its subclasses to specify the
objects it creates
• classes delegate responsibility to one of
several helper subclasses

27
Where to build/switch the
“number”?
Number let the Number constructor
build the object:

Number::Number() {
if (some condition)
this = new BigNumber;
Complex BigInt }

Factory Method:
Where to build/switch the “number”?
soln: use Number
class Number {
public:
Number(istream &);
Number* operator*(const Number& n) {
return rep->operator*(n);
}
private:
Number * rep;
enum NumType {COMPLEX, FLOAT, BIGINT};
NumType numParse(const string &);
};

28
Where to build/switch the
“number”?
Number::Number(istream & s) { The constructor
string buf; is the factory &
getline(cin, buf); it’s acting like a
switch (NumParse(buf) ) { “virtual” function
case COMPLEX:
rep = new Complex(buf); break;
case FLOAT:
rep = new Float(buf); break; Envelope/Letter
case BIGINT:
rep = new BigInt(buf); break;
}
} Note that the constructor
method is the factory!

Factory Method:
Defined
• Define an interface for creating an object, but let subclasses decide which
class to instantiate. Factory Method lets a class defer instantiation to
subclasses.
– A class used to create other objects

29
Factory Method:
Sequence Diagram

Decorator:
Defined
• Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending
functionality.
– Objects that wrap around other objects to add useful features
– Any calls that the decorator gets, it relays to the object that it contains, and adds
its own functionality along the way, either before or after the call.

30
Decorator Pattern: UML

Decorator pattern
• decorator: an object that modifies behavior of, or adds
features to, another object
– decorator must maintain the common interface of the object it
wraps up
• used so that we can add features to an existing simple
object without needing to disrupt the interface that client
code expects when using the simple object

• examples in Java:
– multilayered input streams adding useful I/O methods
– adding designs, scroll bars and borders to GUI controls

31
Decorator example: I/O
• normal InputStream class has only public int
read() method to read one letter at a time
• decorators such as BufferedReader or Scanner
add additional functionality to read the stream
more easily

// InputStreamReader/BufferedReader decorate InputStream


InputStream in = new FileInputStream("hardcode.txt");
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);

// because of decorator streams, I can read an


// entire line from the file in one call
// (InputStream only provides public int read() )

Decorator example: GUI


• normal GUI components don't have
scroll bars
• JScrollPane is a container with scroll
bars to which you can add any
component to make it scrollable

// JScrollPane decorates GUI components


JTextArea area = new JTextArea(20, 30);
JScrollPane scrollPane =
new JScrollPane(area);
contentPane.add(scrollPane);

32

Das könnte Ihnen auch gefallen