Dpatterns Overview Examples
Dpatterns Overview Examples
Therein lies valuable design knowledge Problem: capturing, communicating, and applying this knowledge
Names & specifies the design structure explicitly Distils design experience
Language- and implementation-independent A micro-architecture Adjunct to existing methodologies (Unified, OMT, etc.) No mechanical application
The solution needs to be translated into concrete terms in the application context by the developer
Goals
Codify good design
Distil and disseminate experience Aid to novices and experts alike Abstract how to think about design
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Facilitate restructuring/refactoring
Patterns are interrelated Additional flexibility
POSA catalogue
Pattern-Oriented Software Architecture, Buschmann, et al.; Wiley, 1996
Observer (Behavioral)
Intent
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Applicability
When an abstraction has two aspects, one dependent on the other When a change to one object requires changing others, and you don't know how many objects need to be changed When an object should notify other objects without making assumptions about who these objects are
Observer (Cont'd)
Structure
Subject
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Observer +update()
Observer (Cont'd)
Consequences
+ Modularity: subject and observers may vary independently + Extensibility: can define and add any number of observers + Customizability: different observers provide different views of subject Unexpected updates: observers don't know about each other Update overhead: might need hints
Implementation
Subject-observer mapping Dangling references Avoiding observer-specific update protocols: the push and push/pull models Registering modifications of interest explicitly
Observer (Cont'd)
Known uses
Smalltalk model-view-controller (MVC) Interviews (subjects and views) Andrew (data objects and views)
Benefits
Design reuse Uniform design vocabulary Enhance understanding, restructuring Basis for automation
Observer (Cont'd)
Structure
Subject
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Observer +update()
Subject
Overview
Motivation and Concept
Observer
Composite (Structural)
Intent
Treat individual objects and multiple, recursivelycomposed objects uniformly
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Applicability
Objects must be composed recursively, And there should be no distinction between individual and composed elements, And objects in the structure can be treated uniformly Part-Whole hierarchy of objects. Constant handling of objects as groups or individuals
Composite (Cont'd)
Structure
Component * +operation() +add(in c : Component) +remove(in c : Component) +getChild(in i : int) -children
Leaf +operation()
Composite (Cont'd)
Consequences
+ Uniformity: treat components the same regardless of complexity + Extensibility: new Component subclasses work wherever old ones do Overhead: might need prohibitive numbers of objects
Implementation
Do Components know their parents? Uniform interface for both leaves and composites? Don't allocate storage for children in Component base class Responsibility for deleting children
Composite (Cont'd)
Known Uses
ET++ VObjects InterViews Glyphs, Styles Unidraw Components, MacroCommands
Composite - Example
Strategy (Behavioral)
Intent
Define a family of algorithms, encapsulate each one, and make them interchangeable to let clients and algorithms vary independently
Applicability
When an object should be configurable with one of several algorithms, and all algorithms can be encapsulated, and one interface covers all encapsulations
Strategy (Cont'd)
Structure
ConcreteStrategyA +algorithmInterface()
ConcreteStrategyB +algorithmInterface()
ConcreteStrategyC +algorithmInterface()
Strategy (Cont'd)
Consequences
+ + Greater flexibility, reuse Can change algorithms dynamically Strategy creation & communication overhead Inflexible strategy interface
Implementation
Exchanging information between a strategy and its context Static strategy selection via templates
Known uses
Interviews text formatting RTL register allocation & scheduling strategies Et++SwapsManager calculation engines
Strategy - Example
template <class T> class Print : public Strategy<T>{ public: virtual void doAlgorithm(T* const); Print<class T> *clone(); };
Decorator (Structural)
Intent
Augment objects with new responsibilities
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Applicability
When extension by subclassing is impractical For responsibilities that can be withdrawn
Decorator Diagram
Structure
Component (Glyph)
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
1 -component
+operation()
ConcreteComponent +operation()
{ super.operation(); addedBehavior(); }
Decorator - Diagram
Decorator Overview
A Decorator, also known as a Wrapper, is an object that has an interface identical to an object that it contains. 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. Therefore, the Decorator Pattern is used for adding additional functionality to a particular object as opposed to a class of objects. It is easy to add functionality to an entire class of objects by subclassing an object, but it is impossible to extend a single object this way. With the Decorator Pattern, you can add functionality to a single object and leave others like it unmodified.
Decorator Comments
The Decorator pattern gives you a lot of flexibility, since you can change what the decorator does at runtime, as opposed to having the change be static and determined at compile time by subclassing. Since a Decorator complies with the interface that the object that it contains, the Decorator is indistinguishable from the object that it contains. That is, a Decorator is a concrete instance of the abstract class, and thus is indistinguishable from any other concrete instance, including other decorators. This can be used to great advantage, as you can recursively nest decorators without any other objects being able to tell the difference, allowing a near infinite amount of customization.
Decorator (Cont'd)
Consequences
+ + + Responsibilities can be added/removed at run-time Avoids subclass explosion Recursive nesting allows multiple responsibilities Interface occlusion Identity crisis
Implementation
Interface conformance Use a lightweight, abstract base class for Decorator Heavyweight base classes make Strategy more attractive
Decorator (Cont'd)
Known Uses
Embellishment objects from most OO-GUI toolkits ParcPlace PassivityWrapper InterViews DebuggingGlyph
Decorator Example
Decorator Example
class Book extends LibItem{ String author; intnoCopies; intonShelf; String title; public Book(String t, String a, int c){ title = t; noCopies= c; author = a; onShelf= c; } public String getTitle() { return title; } public int getCopies() { return noCopies; } public int copiesOnShelf() { return onShelf; } public void decCopiesOnShelf() { onShelf--; } public void incCopiesOnShelf() { onShelf++; } public String getAuthor() { return author; } public void borrowItem(String borrower) { System.out.println("borrowin Book"); } public void returnItem(String borrower) { } public void reserve(String reserver) { } } /* End class Book */
Decorator Example
abstract class Decorator extends LibItem{ LibItem item; public Decorator(LibItem li) { item = li; } public String getTitle() { return item.getTitle(); } // Following methods are // similarly implemented public String getAuthor() {... public intgetCopies() { ... public intcopiesOnShelf() { ... public void decCopiesOnShelf() { item.decCopiesOnShelf(); } // and similarly... public void incCopiesOnShelf() {...
Decorator Example
Applicability
When clients cannot anticipate groups of classes to instantiate
instantiate
ConcreteFactory1 +createProductA() +createProductB() ConcreteFactory2 +createProductA() +createProductB()
ProductA1
ProductA2
instantiate
AbstractProductB
instantiate
instantiate
ProductB1 ProductB2
Implementation
Parameterization as a way of controlling interface size Configuration with Prototypes
Known Uses
InterViews Kits ET++ WindowSystem
Overview
Motivation and Concept
Observer
Iterator (Behavioral)
Intent
Access elements of an aggregate sequentially without exposing its representation
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
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
Iterator (cont'd)
Structure
Iterator Aggregate (Glyph)
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
+createIterator()
ConcreteAgregate +createIterator() 1 *
ConcreteIterator
{ return ConcreteIterator(this); }
Iterator Examle
import 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 ); } }
Iterator Example
class 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(); } }
Iterator (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
Known Uses
Penpoint traversal driver/slave InterViews ListItr Unidraw Iterator
Overview
Example: WYSIWYG Editor (Cont'd)
Spelling checking & hyphenation
Iterator Visitor
Visitor (Behavioral)
Intent
Centralize operations on an object structure so that they can vary independently but still behave polymorphically
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Applicability
When classes define many unrelated operations Class relationships of objects in the structure rarely change, but the operations on them change often Algorithms over the structure maintain state that's updated during traversal
Visitor (cont'd)
Structure
Client * * * Visitor +VisitConcreteElement1(ConcreteElement1)() +VisitConcreteElement2(ConcreteElement2)() * ObjectStructure * 1 Element +accept(in v : Visitor)
Visitor (cont'd)
Consequences
+ + Flexibility: visitor and object structure are independent Localized functionality Circular dependency between Visitor and Element interfaces Visitor brittle to new ConcreteElement classes Double dispatch Overloading visit operations Catch-all operation General interface to elements of object structure
Implementation
Known Uses
ProgramNodeEnumerator in Smalltalk-80 compiler IRIS Inventor scene rendering
Formatting
Strategy
Embellishment
Decorator
Multiple Look&Feels
Abstract Factory
(User operations)
Command
Overview
Example: WYSIWYG Editor (Cont'd)
Spelling checking & hyphenation
Iterator Visitor
Applicability
To implement invariant aspects of an algorithm once and let subclasses define variant parts To localize common behavior in a class to increase code reuse To control subclass extensions
Implementation
Virtual vs. non-virtual template method Few vs. lots of primitive operations Naming conventions (do- prefix)
Known Uses
Just about all object-oriented systems (especially frameworks)
Singleton (Creational)
Intent
Ensure a class only ever has one instance, and provide a global point of access to it.
E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley
Applicability
When there must be exactly one instance of a class, and it must be accessible from a well-known access point When the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code
Singleton (cont'd)
Structure
{ return uniqueInstance; }
Singleton (cont'd)
Consequences
+ Reduces namespace pollution + Makes it easy to change your mind and allow more than one instance + Allow extension by subclassing Same drawbacks of a global if misused Implementation may be less efficient than a global Concurrency pitfalls
Implementation
Static instance operation Registering the singleton instance
Singleton (cont'd)
Known Uses
Unidraw's Unidraw object Smalltalk-80 ChangeSet, the set of changes to code InterViews Session object
Singleton - Example
class Singleton { public: static Singleton* Instance(); protected: Singleton(); Singleton(const Singleton&); Singleton& operator= (const Singleton&) private: static Singleton* pinstance; }; Singleton* Singleton::pinstance = 0; // initialize pointer Singleton* Singleton::Instance () { if (pinstance == 0) // is it the first call? { pinstance = new Singleton; // create sole instance } return pinstance; // address of sole instance } Singleton::Singleton() { //... perform necessary instance initializations }
Singleton - Example
// Client code Singleton *p1 = Singleton::Instance(); Singleton *p2 = p1->Instance(); Singleton & ref = * Singleton::Instance();
Although the above example uses a single instance, modifications to the function Instance() may permit a variable number of instances. For example, you can design a class that allows up to three instances.
Overview
Example: WYSIWYG Editor (Cont'd)
Spelling checking & hyphenation
Iterator Visitor
Faade
Faade
Faade
Faade - Example
Overview
Example: WYSIWYG Editor (Cont'd)
Spelling checking & hyphenation
Iterator Visitor
Analysis patterns
Typical solutions to recuring anlysis problems See Analysis Patterns, Fowler; Addison-Wesley, 1996
Architectural patterns
See POSA
Design patterns
Most GoF design patterns are applicable both at the architectural and detailed design
Idioms
Smalltalk Best Practice Patterns, Beck; Prentice Hall, 1997 Concurrent Programming in Java, Lea; Addison-Wesley, 1997 Advanced C++, Coplien, Addison-Wesley, 1992 Effective C++: 50 Specific Ways to Improve Your Programs and Design (2nd Edition), Scott Meyers, Addison-Wesley, (September 1997) More Effective C++: 35 New Ways to Improve Your Programs and Designs, Scott Meyers, Addison-Wesley (December 1995)
Observations
Patterns permit design at a more abstract level
Treat many class/object interactions as a unit Often beneficial after initial design Targets for class refactorings
Variation-oriented design
Consider what design aspects are variable Identify applicable pattern(s) Vary patterns to evaluate tradeoffs Repeat