Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
33 views

Design Patterns Were Mentioned Several Times So Far

The document introduces design patterns and the "Gang of Four" structure for documenting patterns. It discusses that patterns describe recurring problems and solutions, while idioms provide more specific solutions for narrow contexts. The "Gang of Four" structure includes naming the pattern, documenting the problem, describing the core solution, and considering consequences. It provides the Singleton pattern as an example. Finally, it previews familiar design patterns like Iterator, Adapter, and Factory Method that will be covered.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Design Patterns Were Mentioned Several Times So Far

The document introduces design patterns and the "Gang of Four" structure for documenting patterns. It discusses that patterns describe recurring problems and solutions, while idioms provide more specific solutions for narrow contexts. The "Gang of Four" structure includes naming the pattern, documenting the problem, describing the core solution, and considering consequences. It provides the Singleton pattern as an example. Finally, it previews familiar design patterns like Iterator, Adapter, and Factory Method that will be covered.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 23

Introduction to Design Patterns

• Design patterns were mentioned several times so far


– And the Singleton Pattern was discussed in detail
– Along with several C++ memory management idioms
• The lectures this week will focus on them in detail
– What they are and how they are structured
– Introduction to the main “Gang of Four” design patterns
• The first set of design patterns should feel familiar
– They use or help support C++ features we’ve discussed
– We’ve seen examples of some of them already
• The second set is useful for advanced design topics
– Different ways to set up how a group of objects interacts
– How to send an object from one machine to another

CSE 332: Design Patterns (Part I)


What’s a Pattern? What’s an Idiom?

• According to Alexander, a pattern:


– Describes a recurring problem
– Describes the core of a solution
– Is capable of generating many distinct designs

• An Idiom is more restricted


– Still describes a recurring problem
– Provides a more specific solution, with fewer variations
– Applies only to a narrow context
• e.g., the C++ language

CSE 332: Design Patterns (Part I)


“Gang of Four” Pattern Structure
• Gang of Four (GoF): Gamma, Johnson, Helm, Vlissides
– Authors of the popular “Design Patterns” book
• A pattern has a name
– e.g., the Command pattern
• A pattern documents a recurring problem
– e.g., Issuing requests to objects without knowing in advance what’s to
be requested or of what object
• A pattern describes the core of a solution
– e.g., class roles, relationships, and interactions
– Important: this is different than describing a design
• A pattern considers consequences of its use
– Trade-offs, unresolved forces, other patterns to use

CSE 332: Design Patterns (Part I)


Simple Pattern Form Example: “Singleton”
• Problem
– Want to ensure a single instance of a class, shared
throughout a program
• Context
– Need to address initialization versus usage ordering
• Solution
– Provide a global access method (static in C++)
– First use of the access method instantiates the class
– Constructors for instance can be made private
• Consequences
– Object is never created if it’s never used
– Object is shared efficiently among all uses

CSE 332: Design Patterns (Part I)


Singleton Class Template
• Parameterized by a template <class T> class Singleton {
concrete type public:
static T *instance();
• Notice constructor and private:
variable are private Singleton();
static T *instance_;
• Initialization of static };
s_instance variable // Initialize the static instance pointer
– Outside class declaration template <class T>
T *Singleton::instance_ = 0;
– Outside method definition
– Done before any method in // Global access point
compilation unit is called template <class T>
• Instance accessor method T *Singleton::instance() {
can then check // check for existing instance
– For a 0 instance pointer if (Singleton<T>::instance_ == 0) {
// may want a try/catch here
– And create a new instance if
Singleton<T>::instance_ =
so
new Singleton<T>;
• Same object is always }
returned by accessor return Singleton<T>::instance_;
};

CSE 332: Design Patterns (Part I)


Using the Singleton Template
• Need a single
instance
– E.g., a common Foo *f1 =
Singleton<Foo>::instance();
buffer of text tokens Foo *f2 =
from a file Singleton<Foo>::instance();

• Shared across
multiple points in the
code
• Need to share buffer
– Copying is wasteful
– Need to refer to
same object instance
• What about deleting
these instances?
CSE 332: Design Patterns (Part I)
A More Complete Pattern Form: “Command”
• Problem
– Want to issue requests to objects
– Don’t know in advance which request(s) will be made
– Don’t know in advance to what object(s) they will go
• Solution core
– Encapsulate function call parameters and target object
reference inside an “execute” method
• Consequences
– Decouples invocation/execution
– Commands are first-class objects (elevates functions)
– Easy to compose, add new ones
• Example we’ve seen already
– STL function objects
CSE 332: Design Patterns (Part I)
Structure Diagram Example: “Command”
• Shows fixed class/interface roles in the pattern
• Shows fixed relationships between roles
<<Client>> client role command role

<<Invoker>> * <<Command>>
execute ( )

inheritance
<<ConcreteCommand>>
<<Receiver>> execute ( )
action(args) state_

CSE 332: Design Patterns (Part I)


Collaboration Diagram Example: “Command”
• Shows dynamic interactions between pattern roles
– Labels show what interaction does (here, labels show methods called)
• Often used to diagram each of several key scenarios
– “Happy path” when everything works, plus different error cases

aClient aReceiver aCommand anInvoker


new Command(aReceiver)

StoreCommand(aCommand)
time

/ / / / / / / /
action() execute()

CSE 332: Design Patterns (Part I)


Pattern Example: Command
class OpenCommand : public Command {
public:
OpenCommand(Application*);
virtual void Execute();
protected:
virtual const char* AskUser();
private:
class Command { Application* application;
public: char* _response;
virtual ~Command(); };
virtual void Execute() = 0;
OpenCommand::OpenCommand(Application* a){
_application = a;
protected: }
Command();
}; void OpenCommand::Execute () {
const char* name = AskUser();
if (name != NULL) {
Document* doc = new Document(name);
_application->Add(doc);
doc->Open();
}
}

CSE 332: Design Patterns (Part I)


Idiom Example: Guard
• Problem
– Want to tie key scoped behaviors to actual program scopes
• e.g., program trace, resource acquisition/release, locking
– However, tying functions to functions is error-prone
• e.g., forgetting the release call, exceptional return paths
• Solution
– Design a special adapter class whose constructor and
destructor call the key scope entry and exit behaviors
– Create a guard object on the program call stack (in a scope)
• Context limitations
– Mainly limited to languages with constructor/destructor

CSE 332: Design Patterns (Part I)


Part I: Familiar Design Patterns
• First, a few more patterns related to course so far
– Iterator: access elements sequentially no matter how stored
– Adapter: converts interface you get into one you want
– Factory method: creates a related type polymorphically

• Next lecture we’ll examine other important patterns


– Bridge: allow interface, implementation to vary separately
– Chain of responsibility: give request to chain of handlers
– Composite: common interface to composite/simple objects
– Interpreter: build a representation for a simple language
– Observer: tell registered observers when state changes
– Strategy/template method: vary steps/all of an algorithm
– Proxy: forward requests from placeholder to another object
– Memento: package up object state without violating encapsulation
– Visitor: allow various operations on fixed set of objects (2-way dispatch)
CSE 332: Design Patterns (Part I)
Iterator Pattern
• Problem
– Want to access aggregated elements sequentially
• E.g., traverse a list of names and print them out
– Don’t want to know details of how they’re stored
• E.g., in a linked list, or an array, or a balanced binary tree
• Solution core
– Provide a separate interface for iteration over each container
• Consequences
– Frees user from knowing details of how elements are stored
– Decouples containers from algorithms (crucial in C++ STL)
• Examples we’ve seen before
– C++ pointers, C++ STL list<int>::iterator

CSE 332: Design Patterns (Part I)


Iterator Pattern Structure Diagram
• Each container may have a different iterator type
• Iterator knows the internals of the container
• Object-oriented form shown below (for user-defined types)
• Slightly different with built-in types, templates
– E.g., no inheritance relationship, may use traits, etc.
<<Iterator>>

first()
next()
<<Container>> is_done()
create_iterator() current_item()

<<ConcreteAggregate>>
creates <<ConcreteIterator>>
has-a
CSE 332: Design Patterns (Part I)
Object-Oriented Iterator Example
class StringIterator {
public:
• Object-oriented version of
iterator is natural to implement
StringIterator (char * s) as a class in C++
: s_ (s), current_ (s) {}
• Constructor stores passed
void first () { pointer to C-style string s,
current_ = s_;
} positions current_ at s
• first (re)positions iterator at
void next () {
++current_; the start of the string
} • next moves iterator to the next
bool is_done () { position
return *current_ == 0; • is_done tests whether iterator
}
is at the end of the string
char * current_item () {
return current_;
• current_item returns a pointer
} to the character at the current
iterator position
private:

char *s_;
char *current_;

};
CSE 332: Design Patterns (Part I)
Using an Object-Oriented Iterator
unsigned int letter_count • Iterators naturally support
(StringIterator& si, char c) use in looping constructs
{
unsigned int count = 0;
• Here we show a for loop
for (si.first (); – first is used to initialize
! si.is_done ( ); – is_done used for loop test
si.next ()) – next used to increment
if (*si.current_item () == c) – current_item is used in
++count; loop body’s value comparison
return count; • When the loop completes,
}
the function shown has
– Iterated through entire string
– Counted occurrences of the
character value in the string
– Returned the occurrence
count

CSE 332: Design Patterns (Part I)


Using a Procedural Iterator.

unsigned int letter_count • This pattern is not limited to


(char * si, char * start, char c) C++ or even to object-oriented
{ languages
unsigned int count = 0; – For example, C code to the left
for (si = start; • Some changes are needed
*si != 0; – Need to pass in start of string
++si) (not encapsulated in iterator
if (*si == c) class)
++count; – Syntax for pointer operators
return count; instead of method invocations
} • Solution core clearly the same
– Program pretty much the same
– Result of function is the same
– Looks a lot like STL examples

CSE 332: Design Patterns (Part I)


Adapter Pattern
• Problem
– Have an object with an interface that’s close to but not
exactly what we need
• Context
– Want to re-use an existing class
– Can’t change its interface
– Impractical to extend class hierarchy more generally
• Solution
– Wrap a particular class or object with the interface
needed (2 forms: class form and object forms)
• Consequences
– Implementation you’re given gets interface you want

CSE 332: Design Patterns (Part I)


Adapter Pattern Structure Diagram (Class Form)

Interface Impl
method () = 0; impl_method ();

public private

Adapter
method ();

• Abstract base class provides desired interface


• Concrete Impl class provides the implementation
• Adapter glues them together via inheritance

CSE 332: Design Patterns (Part I)


Adapter Pattern Structure Diagram (Object Form)

Interface
method () = 0;

Adapter Impl
method (); impl_method ();

• Abstract base class provides desired interface


• Concrete Impl class provides the implementation
• Adapter class glues them together via delegation

CSE 332: Design Patterns (Part I)


Factory Method Pattern
• Problem
– You want a class to
Container
Iterator create a related class
first()=0; polymorphically
Iterator * next()=0;
make_iterator()=0; current()=0; • Context
is_done()=0; – Each class knows
which version of the
related class it should
create
Array Array_Iterator • Solution
first(); next();
Iterator * – Declare abstract
current();
make_iterator();
is_done(); method that derived
classes override
Linked_List List_Iterator • Consequences
first();next();
Iterator *
current(); – Type created matches
make_iterator(); type(s) it’s used with
is_done();

CSE 332: Design Patterns (Part I)


Object-Oriented vs. Generic Variations
• Use Factory Method pattern if you have inheritance
hierarchies of classes (with abstract base classes)
• Use the Traits idiom when you want a generic
programming version of this technique
– E.g., when you have unrelated classes capable of providing
common interfaces (like STL vectors and linked lists)
• Traits version relies on templates and compile-time
dispatching of calls
• Inheritance based version relies on run-time dynamic
resolution of calls (virtual functions and overriding)

CSE 332: Design Patterns (Part I)


Summary
• We’ve looked at a number of important patterns so far
– Singleton: share a class instance across multiple uses
– Command: package up a function as an object
– Iterator: access elements sequentially no matter how stored
– Adapter: converts interface you get into one you want
– Factory method: creates a related type polymorphically
• Next time: Design Patterns II
– Bridge: allow interface, implementation to vary separately
– Chain of responsibility: give request to chain of handlers
– Composite: common interface to composite/simple objects
– Interpreter: build a representation for a simple language
– Observer: tell registered observers when state changes
– Strategy/template method: vary steps/all of an algorithm
– Proxy: forward requests from placeholder to another object
– Memento: package up object state without violating encapsulation
– Visitor: allow various operations on fixed set of objects (2-way dispatch)

CSE 332: Design Patterns (Part I)

You might also like