Design Patterns

205
Design Patterns Arranged by Marko Čičak Note: all content in this book can be found at http://sourcemaking.com/design_patterns Novi Sad, 2010.

description

This book contains all Design Patterns from Computer Science. All content of this book can be found at http://sourcemaking.com/design_patterns

Transcript of Design Patterns

Page 1: Design Patterns

Design PatternsArranged by Marko Čičak

Note: all content in this book can be found at

http://sourcemaking.com/design_patterns

Novi Sad, 2010.

Page 2: Design Patterns

2 of 205

Table of Contents

Introduction............................................................................................................1Uses of Design Patterns...............................................................................................................1Criticism......................................................................................................................................3Targets the wrong problem..........................................................................................................3Lacks formal foundations.............................................................................................................3Leads to inefficient solutions.......................................................................................................3Does not differ significantly from other abstractions..................................................................3

Creational patterns.................................................................................................5Introduction.................................................................................................................................5Abstract Factory Design Pattern..................................................................................................6Problem........................................................................................................................................6Discussion....................................................................................................................................6Structure......................................................................................................................................6Example.......................................................................................................................................7Check list.....................................................................................................................................8Rules of thumb.............................................................................................................................8Builder Design Pattern...............................................................................................................16Factory Method Design Pattern.................................................................................................28Object Pool Design Pattern........................................................................................................36Prototype Design Pattern...........................................................................................................41Singleton Design Pattern...........................................................................................................51

Structural patterns...............................................................................................58Introduction...............................................................................................................................58Adapter Design Pattern..............................................................................................................59Bridge Design Pattern................................................................................................................68Composite Design Pattern.........................................................................................................80Decorator Design Pattern..........................................................................................................91Facade Design Pattern...............................................................................................................94Flyweight Design Pattern.........................................................................................................102Proxy Design Pattern...............................................................................................................112

Behavioral patterns.............................................................................................122Introduction.............................................................................................................................122Chain of Responsibility............................................................................................................124Command Design Pattern........................................................................................................132Interpreter Design Pattern......................................................................................................143Iterator Design Pattern............................................................................................................156Mediator Design Pattern..........................................................................................................166Memento Design Pattern.........................................................................................................176Null Object Design Pattern......................................................................................................182Observer Design Pattern..........................................................................................................184State Design Pattern................................................................................................................187Strategy Design Pattern...........................................................................................................189Template Method Design Pattern............................................................................................191Visitor Design Pattern..............................................................................................................194

Page 3: Design Patterns

Introduction 3 of 205

In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. A design pattern isn't a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.

Introduction

Uses of Design PatternsDesign patterns can speed up the development process by providing tested, proven development paradigms. Effective software design requires considering issues that may not become visible until later in the implementation. Reusing design patterns helps to prevent subtle issues that can cause major problems and improves code readability for coders and architects familiar with the patterns.

Often, people only understand how to apply certain software design techniques to certain problems. These techniques are difficult to apply to a broader range of problems. Design patterns provide general solutions, documented in a format that doesn't require specifics tied to a particular problem.

In addition, patterns allow developers to communicate using well-known, well understood names for software interactions. Common design patterns can be improved over time, making them more robust than ad-hoc designs.

Creational design patterns

This design patterns is all about class instantiation. This pattern can be further divided into class-creation patterns and object-creational patterns. While class-creation patterns use inheritance effectively in the instantiation process, object-creation patterns use delegation effectively to get the job done.

• Abstract Factory

◦ Creates an instance of several families of classes

• Builder

◦ Separates object construction from its representation

• Factory Method

◦ Creates an instance of several derived classes

• Object Pool

◦ Avoid expensive acquisition and release of resources by recycling objects that are no longer in use

• Prototype

◦ A fully initialized instance to be copied or cloned

• Singleton

◦ A class of which only a single instance can exist

Page 4: Design Patterns

Introduction 4 of 205

Structural design patterns

This design patterns is all about Class and Object composition. Structural class-creation patterns use inheritance to compose interfaces. Structural object-patterns define ways to compose objects to obtain new functionality.

• Adapter

◦ Match interfaces of different classes

• Bridge

◦ Separates an object’s interface from its implementation

• Composite

◦ A tree structure of simple and composite objects

• Decorator

◦ Add responsibilities to objects dynamically

• Facade

◦ A single class that represents an entire subsystem

• Flyweight

◦ A fine-grained instance used for efficient sharing

• Private Class Data

◦ Restricts accessor/mutator access

• Proxy

◦ An object representing another object

Behavioral design patterns

This design patterns is all about Class's objects communication. Behavioral patterns are those patterns that are most specifically concerned with communication between objects.

• Chain of responsibility

◦ A way of passing a request between a chain of objects

• Command

◦ Encapsulate a command request as an object

• Interpreter

◦ A way to include language elements in a program

• Iterator

◦ Sequentially access the elements of a collection

• Mediator

◦ Defines simplified communication between classes

• Memento

Page 5: Design Patterns

Introduction 5 of 205

◦ Capture and restore an object's internal state

• Null Object

◦ Designed to act as a default value of an object

• Observer

◦ A way of notifying change to a number of classes

• State

◦ Alter an object's behavior when its state changes

• Strategy

◦ Encapsulates an algorithm inside a class

• Template method

◦ Defer the exact steps of an algorithm to a subclass

• Visitor

◦ Defines a new operation to a class without change

CriticismThe concept of design patterns has been criticized by some in the field of computer science.

Targets the wrong problemThe need for patterns results from using computer languages or techniques with insufficient abstraction ability. Under ideal factoring, a concept should not be copied, but merely referenced. But if something is referenced instead of copied, then there is no "pattern" to label and catalog. Paul Graham writes in the essay Revenge of the Nerds.

Peter Norvig provides a similar argument. He demonstrates that 16 out of the 23 patterns in the Design Patterns book (which is primarily focused on C++) are simplified or eliminated (via direct language support) in Lisp or Dylan.

Lacks formal foundationsThe study of design patterns has been excessively ad hoc, and some have argued that the concept sorely needs to be put on a more formal footing. At oopsla 1999, the Gang of Four were (with their full cooperation) subjected to a show trial, in which they were "charged" with numerous crimes against computer science. They were "convicted" by ⅔ of the "jurors" who attended the trial.

Leads to inefficient solutionsThe idea of a design pattern is an attempt to standardize what are already accepted best practices. In principle this might appear to be beneficial, but in practice it often results in the unnecessary duplication of code. It is almost always a more efficient solution to use a well-factored implementation rather than a "just barely good enough" design pattern.

Does not differ significantly from other abstractionsSome authors allege that design patterns don't differ significantly from other forms of

Page 6: Design Patterns

Introduction 6 of 205

abstraction, and that the use of new terminology (borrowed from the architecture community) to describe existing phenomena in the field of programming is unnecessary. The Model-View-Controller paradigm is touted as an example of a "pattern" which predates the concept of "design patterns" by several years. It is further argued by some that the primary contribution of the Design Patterns community (and the Gang of Four book) was the use of Alexander's pattern language as a form of documentation; a practice which is often ignored in the literature.

Page 7: Design Patterns

Creational patterns 7 of 205

Creational patterns

IntroductionIn software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation.

• Abstract Factory

◦ Creates an instance of several families of classes

• Builder

◦ Separates object construction from its representation

• Factory Method

◦ Creates an instance of several derived classes

• Object Pool

◦ Avoid expensive acquisition and release of resources by recycling objects that are no longer in use

• Prototype

◦ A fully initialized instance to be copied or cloned

• Singleton

◦ A class of which only a single instance can exist

Rules of thumb

1. Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementory: Abstract Factory might store a set of Prototypes from which to clone and return product objects, Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementation.

2. Abstract Factory, Builder, and Prototype define a factory object that’s responsible for knowing and creating the class of product objects, and make it a parameter of the system. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object (aka prototype) building a product by copying a prototype object.

3. Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype.

4. Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.

5. Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.

Page 8: Design Patterns

Creational patterns 8 of 205

6. Builder is to creation as Strategy is to algorithm.

7. Builder often builds a Composite.

8. Factory Methods are usually called within Template methods.

9. Factory Method: creation through inheritance. Prototype: creation through delegation.

10. Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

11. Prototype doesn’t require subclassing, but it does require an Initialize operation. Factory Method requires subclassing, but doesn’t require Initialize.

12. Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.

Abstract Factory Design Pattern

Intent

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

A hierarchy that encapsulates: many possible “platforms”, and the construction of a suite of “products”.

The new operator considered harmful.

ProblemIf an application is to be portable, it needs to encapsulate platform dependencies. These “platforms” might include: windowing system, operating system, database, etc. Too often, this encapsulatation is not engineered in advance, and lots of #ifdef case statements with options for all currently supported platforms begin to procreate like rabbits throughout the code.

DiscussionProvide a level of indirection that abstracts the creation of families of related or dependent objects without directly specifying their concrete classes. The “factory” object has the responsibility for providing creation services for the entire platform family. Clients never create platform objects directly, they ask the factory to do that for them.

This mechanism makes exchanging product families easy because the specific class of the factory object appears only once in the application - where it is instantiated. The application can wholesale replace the entire family of products simply by instantiating a different concrete instance of the abstract factory.

Because the service provided by the factory object is so pervasive, it is routinely implemented as a Singleton.

StructureThe Abstract Factory defines a Factory Method per product. Each Factory Method encapsulates the new operator and the concrete, platform-specific, product classes. Each “platform” is then modeled with a Factory derived class.

Page 9: Design Patterns

Creational patterns 9 of 205

ExampleThe purpose of the Abstract Factory is to provide an interface for creating families of related objects, without specifying concrete classes. This pattern is found in the sheet metal stamping equipment used in the manufacture of Japanese automobiles. The stamping equipment is an Abstract Factory which creates auto body parts. The same machinery is used to stamp right hand doors, left hand doors, right front fenders, left front fenders, hoods, etc. for different models of cars. Through the use of rollers to change the stamping dies, the concrete classes produced by the machinery can be changed within three minutes.

Page 10: Design Patterns

Creational patterns 10 of 205

Check listDecide if “platform independence” and creation services are the current source of pain.

Map out a matrix of “platforms” versus “products”.

Define a factory interface that consists of a factory method per product.

Define a factory derived class for each platform that encapsulates all references to the new operator.

The client should retire all references to new, and use the factory methods to create the product objects.

Rules of thumbSometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementary: Abstract Factory might store a set of Prototypes from which to clone and return product objects, Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementation.

Abstract Factory, Builder, and Prototype define a factory object that’s responsible for knowing and creating the class of product objects, and make it a parameter of the system. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object (aka prototype) building a product by copying a prototype object.

Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype.

Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.

Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.

Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

Abstract Factory in C++

#include <iostream.h>

class Shape {  public:    Shape() {      id_ = total_++;    }    virtual void draw() = 0;  protected:    int id_;    static int total_;};int Shape::total_ = 0;

class Circle : public Shape {

Page 11: Design Patterns

Creational patterns 11 of 205

  public:    void draw() {      cout << "circle " << id_ << ": draw" << endl;    }};class Square : public Shape {  public:    void draw() {      cout << "square " << id_ << ": draw" << endl;    }};class Ellipse : public Shape {  public:    void draw() {      cout << "ellipse " << id_ << ": draw" << endl;    }};class Rectangle : public Shape {  public:    void draw() {      cout << "rectangle " << id_ << ": draw" << endl;    }};

class Factory {  public:    virtual Shape* createCurvedInstance() = 0;    virtual Shape* createStraightInstance() = 0;};

class SimpleShapeFactory : public Factory {  public:    Shape* createCurvedInstance() {      return new Circle;    }    Shape* createStraightInstance() {      return new Square;    }};

class RobustShapeFactory : public Factory {  public:    Shape* createCurvedInstance()   {      return new Ellipse;    }    Shape* createStraightInstance() {      return new Rectangle;    }};

int main() {#ifdef SIMPLE  Factory* factory = new SimpleShapeFactory;#elif ROBUST  Factory* factory = new RobustShapeFactory;

Page 12: Design Patterns

Creational patterns 12 of 205

#endif  Shape* shapes[3];

  shapes[0] = factory­>createCurvedInstance();   // shapes[0] = new Ellipse;  shapes[1] = factory­>createStraightInstance(); // shapes[1] = new Rectangle;  shapes[2] = factory­>createCurvedInstance();   // shapes[2] = new Ellipse;

  for (int i=0; i < 3; i++) {    shapes[i]­>draw();  }}

output:

ellipse 0: drawrectangle 1: drawellipse 2: draw

Abstract Factory in C++: Before and after

Trying to maintain portability across multiple “platforms” routinely requires lots of preprocessor “case” statements. The Factory pattern suggests defining a creation services interface in a Factory base class, and implementing each “platform” in a separate Factory derived class.

Before

The client creates “product” objects directly, and must embed all possible platform permutations in nasty looking code.

#define MOTIF

class Widget {public:   virtual void draw() = 0;};

class MotifButton : public Widget {public:   void draw() { cout << "MotifButton\n"; }};class MotifMenu : public Widget {public:   void draw() { cout << "MotifMenu\n"; }};

class WindowsButton : public Widget {public:   void draw() { cout << "WindowsButton\n"; }};class WindowsMenu : public Widget {public:   void draw() { cout << "WindowsMenu\n"; }};

Page 13: Design Patterns

Creational patterns 13 of 205

void display_window_one() {#ifdef MOTIF   Widget* w[] = { new MotifButton,                   new MotifMenu };#else // WINDOWS   Widget* w[] = { new WindowsButton,                   new WindowsMenu };#endif   w[0]­>draw();  w[1]­>draw();}

void display_window_two() {#ifdef MOTIF   Widget* w[] = { new MotifMenu,                   new MotifButton };#else // WINDOWS   Widget* w[] = { new WindowsMenu,                   new WindowsButton };#endif   w[0]­>draw();  w[1]­>draw();}

int main() {#ifdef MOTIF   Widget* w = new MotifButton;#else // WINDOWS   Widget* w = new WindowsButton;#endif   w­>draw();   display_window_one();   display_window_two();}

output:

MotifButtonMotifButtonMotifMenuMotifMenuMotifButton

After

The client: creates a platform- specific “factory” object, is careful to eschew use of “new”, and delegates all creation requests to the factory.

#define WINDOWS

class Widget {public:   virtual void draw() = 0;};

class MotifButton : public Widget {public:

Page 14: Design Patterns

Creational patterns 14 of 205

   void draw() { cout << "MotifButton\n"; }};class MotifMenu : public Widget {public:   void draw() { cout << "MotifMenu\n"; }};

class WindowsButton : public Widget {public:   void draw() { cout << "WindowsButton\n"; }};class WindowsMenu : public Widget {public:   void draw() { cout << "WindowsMenu\n"; }};

class Factory {public:   virtual Widget* create_button() = 0;   virtual Widget* create_menu() = 0;};

class MotifFactory : public Factory {public:   Widget* create_button() {      return new MotifButton; }   Widget* create_menu()   {      return new MotifMenu; }};

class WindowsFactory : public Factory {public:   Widget* create_button() {      return new WindowsButton; }   Widget* create_menu()   {      return new WindowsMenu; }};

Factory* factory;

void display_window_one() {   Widget* w[] = { factory­>create_button(),                   factory­>create_menu() };   w[0]­>draw();  w[1]­>draw();}

void display_window_two() {   Widget* w[] = { factory­>create_menu(),                   factory­>create_button() };   w[0]­>draw();  w[1]­>draw();}

int main() {#ifdef MOTIF   factory = new MotifFactory;#else // WINDOWS

Page 15: Design Patterns

Creational patterns 15 of 205

   factory = new WindowsFactory;#endif

   Widget* w = factory­>create_button();   w­>draw();   display_window_one();   display_window_two();}

output:

WindowsButtonWindowsButtonWindowsMenuWindowsMenuWindowsButton

Abstract Factory in Java

Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype. Abstract Factory might store a set of Prototypes from which to clone and return product objects.

• Factory Method: creation through inheritance.• Prototype: creation through delegation.• Virtual constructor: defer choice of object to create until run-time.

public class FactoryFmProto{    static class Expression    {        protected String str;        public Expression(String s)        {            str = s;        }        public Expression cloan()        {            return null;        }        public String toString()        {            return str;        }    }

    static abstract class Factory    {        protected Expression prototype = null;        public Expression makePhrase()        {            return prototype.cloan();        }        public abstract Expression makeCompromise();

Page 16: Design Patterns

Creational patterns 16 of 205

        public abstract Expression makeGrade();    }

    static class PCFactory extends Factory    {        public PCFactory()        {            prototype = new PCPhrase();        }        public Expression makeCompromise()        {            return new Expression("\"do it your way, any way, or no way\"");        }        public Expression makeGrade()        {            return new Expression("\"you pass, self­esteem intact\"");        }    }

    static class NotPCFactory extends Factory    {        public NotPCFactory()        {            prototype = new NotPCPhrase();        }        public Expression makeCompromise()        {            return new Expression("\"my way, or the highway\"");        }        public Expression makeGrade()        {            return new Expression("\"take test, deal with the results\"");        }    }

    public static void main(String[] args)    {        Factory factory;        if (args.length > 0)            factory = new PCFactory();        else            factory = new NotPCFactory();        for (int i = 0; i < 3; i++)            System.out.print(factory.makePhrase() + "  ");        System.out.println();        System.out.println(factory.makeCompromise());        System.out.println(factory.makeGrade());    }

    static class PCPhrase extends Expression    {        static String[] list =         {            "\"animal companion\"", "\"vertically challenged\"",                 "\"factually inaccurate\"", "\"chronologically gifted\""        };

Page 17: Design Patterns

Creational patterns 17 of 205

        private static int next = 0;        public PCPhrase()        {            super(list[next]);            next = (next + 1) % list.length;        }        public Expression cloan()        {            return new PCPhrase();        }    }

    static class NotPCPhrase extends Expression    {        private static String[] list =         {            "\"pet\"", "\"short\"", "\"lie\"", "\"old\""        };        private static int next = 0;        public NotPCPhrase()        {            super(list[next]);            next = (next + 1) % list.length;        }        public Expression cloan()        {            return new NotPCPhrase();        }    }}

output:

D:\Java\patterns> java FactoryFmProto"short" "lie" "old" "my way, or the highway" "take test, deal with the results" 

D:\Java\patterns> java FactoryFmProto 1 "vertically challenged" "factually inaccurate" "chronologically gifted" "do it your way, any way, or no way" "you pass, self­esteem intact"

Abstract Factory in Java 2

public abstract class CPU{  ...} // class CPU

class EmberCPU extends CPU{  ...} // class EmberCPU

class EmberToolkit extends ArchitectureToolkit

Page 18: Design Patterns

Creational patterns 18 of 205

{  public CPU createCPU()  {    return new EmberCPU();  } // createCPU()

  public MMU createMMU()  {    return new EmberMMU();  } // createMMU()  ...} // class EmberFactory

public abstract class ArchitectureToolkit{  private static final EmberToolkit emberToolkit = new EmberToolkit();  private static final EnginolaToolkit enginolaToolkit = new EnginolaToolkit();  ...

  // Returns a concrete factory object that is an instance of the  // concrete factory class appropriate for the given architecture.  static final ArchitectureToolkit getFactory(int architecture)  {    switch (architecture)    {      case ENGINOLA:        return enginolaToolkit;

      case EMBER:        return emberToolkit;        ...    } // switch    String errMsg = Integer.toString(architecture);    throw new IllegalArgumentException(errMsg);  } // getFactory()

  public abstract CPU createCPU();  public abstract MMU createMMU();  ...} // AbstractFactory public class Client{  public void doIt()  {    AbstractFactory af;    af = AbstractFactory.getFactory(AbstractFactory.EMBER);    CPU cpu = af.createCPU();    ...  } // doIt} // class Client

Builder Design Pattern

Page 19: Design Patterns

Creational patterns 19 of 205

Intent

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Parse a complex representation, create one of several targets.

Problem

An application needs to create the elements of a complex aggregate. The specification for the aggregate exists on secondary storage and one of many representations needs to be built in primary storage.

Discussion

Separate the algorithm for interpreting (i.e. reading and parsing) a stored persistence mechanism (e.g. RTF files) from the algorithm for building and representing one of many target products (e.g. ASCII, TeX, text widget). The focus/distinction is on creating complex aggregates.

The “director” invokes “builder” services as it interprets the external format. The “builder” creates part of the complex object each time it is called and maintains all intermediate state. When the product is finished, the client retrieves the result from the “builder”.

Affords finer control over the construction process. Unlike creational patterns that construct products in one shot, the Builder pattern constructs the product step by step under the control of the “director”.

Structure

The Reader encapsulates the parsing of the common input. The Builder hierarchy makes possible the polymorphic creation of many peculiar representations or targets.

Page 20: Design Patterns

Creational patterns 20 of 205

Example

The Builder pattern separates the construction of a complex object from its representation so that the same construction process can create different representations. This pattern is used by fast food restaurants to construct children’s meals. Children’s meals typically consist of a main item, a side item, a drink, and a toy (e.g., a hamburger, fries, Coke, and toy dinosaur). Note that there can be variation in the content of the children’s meal, but the construction process is the same. Whether a customer orders a hamburger, cheeseburger, or chicken, the process is the same. The employee at the counter directs the crew to assemble a main item, side item, and toy. These items are then placed in a bag. The drink is placed in a cup and remains outside of the bag. This same process is used at competing restaurants.

Check list

1. Decide if a common input and many possible representations (or outputs) is the problem at hand.

2. Encapsulate the parsing of the common input in a Reader class.

3. Design a standard protocol for creating all possible output representations. Capture the steps of this protocol in a Builder interface.

4. Define a Builder derived class for each target representation.

5. The client creates a Reader object and a Builder object, and registers the latter with the former.

6. The client asks the Reader to “construct”.

7. The client asks the Builder to return the result.

Rules of thumb

• Sometimes creational patterns are complementory: Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.

• Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the

Page 21: Design Patterns

Creational patterns 21 of 205

product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.

• Builder often builds a Composite.

• Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

Builder in C++

Builder design pattern demo

Discussion. The forte of Builder is constructing a complex object step by step. An abstract base class declares the standard construction process, and concrete derived classes define the appropriate implementation for each step of the process. In this example, “distributed work packages” have been abstracted to be persistent and platform independent.

This means that the platform-specific mechanism for implementing files, queues, and concurrency pathways is defined in each platform’s concrete derived class. A single “reader” object (i.e. parser) retrieves the archived specification for a DistrWorkPackage and proceeds to delegate each build step to the builder object that was registered by the client. Upon completion, the client retrieves the end result from the builder.

#include <iostream.h>#include <stdio.h>#include <string.h>

enum PersistenceType{  File, Queue, Pathway};

struct PersistenceAttribute{  PersistenceType type;  char value[30];};

class DistrWorkPackage{  public:    DistrWorkPackage(char *type)    {        sprintf(_desc, "Distributed Work Package for: %s", type);    }    void setFile(char *f, char *v)    {        sprintf(_temp, "\n  File(%s): %s", f, v);        strcat(_desc, _temp);    }    void setQueue(char *q, char *v)    {        sprintf(_temp, "\n  Queue(%s): %s", q, v);        strcat(_desc, _temp);    }    void setPathway(char *p, char *v)

Page 22: Design Patterns

Creational patterns 22 of 205

    {        sprintf(_temp, "\n  Pathway(%s): %s", p, v);        strcat(_desc, _temp);    }    const char *getState()    {        return _desc;    }  private:    char _desc[200], _temp[80];};

class Builder{  public:    virtual void configureFile(char*) = 0;    virtual void configureQueue(char*) = 0;    virtual void configurePathway(char*) = 0;    DistrWorkPackage *getResult()    {        return _result;    }  protected:    DistrWorkPackage *_result;};

class UnixBuilder: public Builder{  public:    UnixBuilder()    {        _result = new DistrWorkPackage("Unix");    }    void configureFile(char *name)    {        _result­>setFile("flatFile", name);    }    void configureQueue(char *queue)    {        _result­>setQueue("FIFO", queue);    }    void configurePathway(char *type)    {        _result­>setPathway("thread", type);    }};

class VmsBuilder: public Builder{  public:    VmsBuilder()    {        _result = new DistrWorkPackage("Vms");    }    void configureFile(char *name)    {

Page 23: Design Patterns

Creational patterns 23 of 205

        _result­>setFile("ISAM", name);    }    void configureQueue(char *queue)    {        _result­>setQueue("priority", queue);    }    void configurePathway(char *type)    {        _result­>setPathway("LWP", type);    }};

class Reader{  public:    void setBuilder(Builder *b)    {        _builder = b;    }    void construct(PersistenceAttribute[], int);  private:    Builder *_builder;};

void Reader::construct(PersistenceAttribute list[], int num){  for (int i = 0; i < num; i++)    if (list[i].type == File)      _builder­>configureFile(list[i].value);    else if (list[i].type == Queue)      _builder­>configureQueue(list[i].value);    else if (list[i].type == Pathway)      _builder­>configurePathway(list[i].value);}

const int NUM_ENTRIES = 6;PersistenceAttribute input[NUM_ENTRIES] = {  {    File, "state.dat"  }  ,   {    File, "config.sys"  }  ,   {    Queue, "compute"  }  ,   {    Queue, "log"  }  ,   {    Pathway, "authentication"

Page 24: Design Patterns

Creational patterns 24 of 205

  }  ,   {    Pathway, "error processing"  }};

int main(){  UnixBuilder unixBuilder;  VmsBuilder vmsBuilder;  Reader reader;

  reader.setBuilder(&unixBuilder);  reader.construct(input, NUM_ENTRIES);  cout << unixBuilder.getResult()­>getState() << endl;

  reader.setBuilder(&vmsBuilder);  reader.construct(input, NUM_ENTRIES);  cout << vmsBuilder.getResult()­>getState() << endl;}

output:

Distributed Work Package for: Unix File(flatFile): state.dat File(flatFile): config.sys Queue(FIFO): compute Queue(FIFO): log Pathway(thread): authentication Pathway(thread): error processing 

Distributed Work Package for: Vms File(ISAM): state.dat File(ISAM): config.sys Queue(priority): compute Queue(priority): log Pathway(LWP): authentication Pathway(LWP): error processing

Builder in Java: Before and after

Before

This implementation is arguably preferable. Each table class encapsulates a different layout.

class JTable_Table{    private JTable m_table;

    public JTable_Table(String[][] matrix)    {        m_table = new JTable(matrix[0].length, matrix.length);        TableModel model = m_table.getModel();        for (int i = 0; i < matrix.length; ++i)          for (int j = 0; j < matrix[i].length; ++j)            model.setValueAt(matrix[i][j], j, i);

Page 25: Design Patterns

Creational patterns 25 of 205

    }    public Component get_table()    {        return m_table;    }}

class GridLayout_Table{    private JPanel m_table = new JPanel();

    public GridLayout_Table(String[][] matrix)    {        m_table.setLayout(new GridLayout(matrix[0].length, matrix.length));        m_table.setBackground(Color.white);        for (int i = 0; i < matrix[i].length; ++i)          for (int j = 0; j < matrix.length; ++j)            m_table.add(new Label(matrix[j][i]));    }    public Component get_table()    {        return m_table;    }}

class GridBagLayout_Table{    private JPanel m_table = new JPanel();

    public GridBagLayout_Table(String[][] matrix)    {        GridBagConstraints c = new GridBagConstraints();        m_table.setLayout(new GridBagLayout());        m_table.setBackground(Color.white);        for (int i = 0; i < matrix.length; ++i)        for (int j = 0; j < matrix[i].length; ++j)        {            c.gridx = i;            c.gridy = j;            m_table.add(new Label(matrix[i][j]), c);        }    }    public Component get_table()    {        return m_table;    }}

public class BuilderDemo{    public static String[][] read_data_file(String file_name)    {        String[][] matrix = null;        try        {            BufferedReader br = new BufferedReader(new FileReader(file_name));

Page 26: Design Patterns

Creational patterns 26 of 205

            String line, cell = "";            String[] tokens;            boolean first_line = true;            int row = 0, col = 0;            while ((line = br.readLine()) != null)            {                // Use "whitespace" to tokenize each line                // java.sun.com/docs/books/tutorial/extra/                //    regex/pre_char_classes.html                tokens = line.split("\\s");                int i = 0;                if (first_line)                {                    matrix = new String[Integer.parseInt(tokens[0])                      ][Integer.parseInt(tokens[1])];                    i = 2;                    first_line = false;                }                for (; i < tokens.length; ++i)                if (tokens[i].equals(""))                {                    matrix[col][row++] = cell;                    cell = "";                    col = 0;                }                else if (tokens[i].equals(""))                {                    matrix[col++][row] = cell;                    cell = "";                }                else                {                    cell += " " + tokens[i];                }            }            matrix[col][row] = cell;            br.close();        }        catch (Exception ex)        {            ex.printStackTrace();        }        return matrix;    }    public static void main(String[] args)    {        JFrame frame = new JFrame("BuilderDemo ­ " + args[0]);        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        String[][] matrix = read_data_file("BuilderDemo.dat");        if (args[0].equals("JTable_Table"))          frame.getContentPane().add(new JTable_Table(matrix).get_table());        else if (args[0].equals("GridLayout_Table"))          frame.getContentPane().add(new GridLayout_Table(matrix).get_table());        else if (args[0].equals("GridBagLayout_Table"))          frame.getContentPane().add(new GridBagLayout_Table(matrix).get_table()            );

Page 27: Design Patterns

Creational patterns 27 of 205

        frame.pack();        frame.setVisible(true);    }}

After

The main() creates a reader/parser, and configures it with a builder (an object that implements a standard interface and knows how to create one of many possible “results”. The reader reads and parses the common input and delegates the construction to the configured builder.

This implementation demonstrates the spirit of the Builder pattern, but it is more intricate, and probably cannot be justified for this fairly limited context.

class Reader{    private Builder m_builder;

    public Reader(Builder b)    {        m_builder = b;    }

    public void construct(String file_name)    {        try        {            BufferedReader br = new BufferedReader(new FileReader(file_name));            String line, cell = "";            String[] tokens;            boolean first_line = true;            while ((line = br.readLine()) != null)            {                tokens = line.split("\\s");                int i = 0;                if (first_line)                {                    m_builder.set_width_and_height(Integer.parseInt(tokens[0]),                      Integer.parseInt(tokens[1]));                    i = 2;                    first_line = false;                }                for (; i < tokens.length; ++i)                if (tokens[i].equals(""))                {                    m_builder.build_cell(cell);                    cell = "";                    m_builder.start_row();                }                else if (tokens[i].equals(""))                {                    m_builder.build_cell(cell);                    cell = "";                }                else

Page 28: Design Patterns

Creational patterns 28 of 205

                {                    cell += " " + tokens[i];                }            }            m_builder.build_cell(cell);            br.close();        }        catch (Exception ex)        {            ex.printStackTrace();        }    }}

interface Builder{  void set_width_and_height(int width, int height);  void start_row();  void build_cell(String value);  Component get_result();}

class JTable_Builder implements Builder{    private JTable m_table;    private TableModel m_model;    private int i = 0, j = 0;

    public void set_width_and_height(int width, int height)    {        m_table = new JTable(height, width);        m_model = m_table.getModel();    }    public void start_row()    {        ++i;        j = 0;    }    public void build_cell(String value)    {        m_model.setValueAt(value, i, j++);    }    public Component get_result()    {        return m_table;    }}

class GridLayout_Builder implements Builder{    private JPanel m_panel = new JPanel();

    public void set_width_and_height(int width, int height)    {        m_panel.setLayout(new GridLayout(height, width));        m_panel.setBackground(Color.white);

Page 29: Design Patterns

Creational patterns 29 of 205

    }    public void start_row(){}    public void build_cell(String value)    {        m_panel.add(new Label(value));    }    public Component get_result()    {        return m_panel;    }}

class GridBagLayout_Builder implements Builder{    private JPanel m_panel = new JPanel();    private GridBagConstraints c = new GridBagConstraints();    private int i = 0, j = 0;

    public void set_width_and_height(int width, int height)    {        m_panel.setLayout(new GridBagLayout());        m_panel.setBackground(Color.white);    }    public void start_row()    {        ++i;        j = 0;    }    public void build_cell(String value)    {        c.gridx = j++;        c.gridy = i;        m_panel.add(new Label(value), c);    }    public Component get_result()    {        return m_panel;    }}

public class BuilderDemo{  public static void main(String[] args)  {    Builder target = null;    try    {      target = (Builder)Class.forName(args[0]).newInstance();    }    catch (Exception ex)    {      ex.printStackTrace();    }    Reader parser = new Reader(target);    parser.construct("BuilderDemo.dat");

Page 30: Design Patterns

Creational patterns 30 of 205

    JFrame frame = new JFrame("BuilderDemo ­ " + args[0]);    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    frame.getContentPane().add(target.get_result());    frame.pack();    frame.setVisible(true);  }}

Another Builder in Java Example

/* "Product" */class Pizza {  private String dough = "";  private String sauce = "";  private String topping = "";

  public void setDough(String dough)     { this.dough = dough; }  public void setSauce(String sauce)     { this.sauce = sauce; }  public void setTopping(String topping) { this.topping = topping; }}

/* "Abstract Builder" */abstract class PizzaBuilder {  protected Pizza pizza;

  public Pizza getPizza() { return pizza; }  public void createNewPizzaProduct() { pizza = new Pizza(); }

  public abstract void buildDough();  public abstract void buildSauce();  public abstract void buildTopping();}

/* "ConcreteBuilder" */class HawaiianPizzaBuilder extends PizzaBuilder {  public void buildDough()   { pizza.setDough("cross"); }  public void buildSauce()   { pizza.setSauce("mild"); }  public void buildTopping() { pizza.setTopping("ham+pineapple"); }}

/* "ConcreteBuilder" */class SpicyPizzaBuilder extends PizzaBuilder {  public void buildDough()   { pizza.setDough("pan baked"); }  public void buildSauce()   { pizza.setSauce("hot"); }  public void buildTopping() { pizza.setTopping("pepperoni+salami"); }}

/* "Director" */class Waiter {  private PizzaBuilder pizzaBuilder;

  public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }  public Pizza getPizza() { return pizzaBuilder.getPizza(); }

  public void constructPizza() {

Page 31: Design Patterns

Creational patterns 31 of 205

    pizzaBuilder.createNewPizzaProduct();    pizzaBuilder.buildDough();    pizzaBuilder.buildSauce();    pizzaBuilder.buildTopping();  }}

/* A customer ordering a pizza. */class BuilderExample {  public static void main(String[] args) {    Waiter waiter = new Waiter();    PizzaBuilder hawaiian_pizzabuilder = new HawaiianPizzaBuilder();    PizzaBuilder spicy_pizzabuilder = new SpicyPizzaBuilder();

    waiter.setPizzaBuilder( hawaiian_pizzabuilder );    waiter.constructPizza();

    Pizza pizza = waiter.getPizza();  }}

Factory Method Design Pattern

Intent

• Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

• Defining a “virtual” constructor.• The new operator considered harmful.

Problem

A framework needs to standardize the architectural model for a range of applications, but allow for individual applications to define their own domain objects and provide for their instantiation.

Discussion

Factory Method is to creating objects as Template Method is to implementing an algorithm. A superclass specifies all standard and generic behavior (using pure virtual “placeholders” for creation steps), and then delegates the creation details to subclasses that are supplied by the client.

Factory Method makes a design more customizable and only a little more complicated. Other design patterns require new classes, whereas Factory Method only requires a new operation.

People often use Factory Method as the standard way to create objects; but it isn’t necessary if: the class that’s instantiated never changes, or instantiation takes place in an operation that subclasses can easily override (such as an initialization operation).

Factory Method is similar to Abstract Factory but without the emphasis on families.

Factory Methods are routinely specified by an architectural framework, and then implemented by the user of the framework.

Page 32: Design Patterns

Creational patterns 32 of 205

Structure

The implementation of Factory Method discussed in the Gang of Four (below) largely overlaps with that of Abstract Factory. For that reason, the presentation in this chapter focuses on the approach that has become popular since.

An increasingly popular definition of factory method is: a static method of a class that returns an object of that class’ type. But unlike a constructor, the actual object it returns might be an instance of a subclass. Unlike a constructor, an existing object might be reused, instead of a new object created. Unlike a constructor, factory methods can have different and more descriptive names (e.g. Color.make_RGB_color(float red, float green, float blue) and Color.make_HSB_color(float hue, float saturation, float brightness)

The client is totally decoupled from the implementation details of derived classes. Polymorphic creation is now possible.

Page 33: Design Patterns

Creational patterns 33 of 205

Example

The Factory Method defines an interface for creating objects, but lets subclasses decide which classes to instantiate. Injection molding presses demonstrate this pattern. Manufacturers of plastic toys process plastic molding powder, and inject the plastic into molds of the desired shapes. The class of toy (car, action figure, etc.) is determined by the mold.

Check list

1. If you have an inheritance hierarchy that exercises polymorphism, consider adding a polymorphic creation capability by defining a static factory method in the base class.

2. Design the arguments to the factory method. What qualities or characteristics are necessary and sufficient to identify the correct derived class to instantiate?

3. Consider designing an internal “object pool” that will allow objects to be reused instead of created from scratch.

4. Consider making all constructors private or protected.

Rules of thumb

• Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.

• Factory Methods are usually called within Template Methods.• Factory Method: creation through inheritance. Prototype: creation through delegation.• Often, designs start out using Factory Method (less complicated, more customizable,

subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

• Prototype doesn’t require subclassing, but it does require an Initialize operation. Factory Method requires subclassing, but doesn’t require Initialize.

• The advantage of a Factory Method is that it can return the same instance multiple times, or can return a subclass rather than an object of that exact type.

• Some Factory Method advocates recommend that as a matter of language design (or failing that, as a matter of style) absolutely all constructors should be private or protected. It’s no one else’s business whether a class manufactures a new object or recycles an old one.

• The new operator considered harmful. There is a difference between requesting an object and creating one. The new operator always creates an object, and fails to encapsulate object creation. A Factory Method enforces that encapsulation, and allows an object to be requested without inextricable coupling to the act of creation.

Factory Method in C++: Before and after

Page 34: Design Patterns

Creational patterns 34 of 205

Before

The architect has done an admirable job of decoupling the client from Stooge concrete derived classes, and, exercising polymorphism. But there remains coupling where instances are actually created. If we design an “extra level of indirection” (a “factory method”) and have clients use it (instead of “new”), then the last bit of coupling goes away. The “factory method” (aka “virtual constructor”) can be defined in the Stooge base class, or, in a separate “factory” class. Note that main() is no longer dependent on Stooge derived classes.

class Stooge{  public:    virtual void slap_stick() = 0;};

class Larry: public Stooge{  public:    void slap_stick()    {        cout << "Larry: poke eyes\n";    }};class Moe: public Stooge{  public:    void slap_stick()    {        cout << "Moe: slap head\n";    }};class Curly: public Stooge{  public:    void slap_stick()    {        cout << "Curly: suffer abuse\n";    }};

int main(){  vector<Stooge*> roles;  int choice;

  while (true)  {    cout << "Larry(1) Moe(2) Curly(3) Go(0): ";    cin >> choice;    if (choice == 0)      break;    else if (choice == 1)      roles.push_back(new Larry);    else if (choice == 2)      roles.push_back(new Moe);    else      roles.push_back(new Curly);

Page 35: Design Patterns

Creational patterns 35 of 205

  }  for (int i = 0; i < roles.size(); i++)    roles[i]­>slap_stick();  for (int i = 0; i < roles.size(); i++)    delete roles[i];}

output:

Larry(1) Moe(2) Curly(3) Go(0): 2 Larry(1) Moe(2) Curly(3) Go(0): 1 Larry(1) Moe(2) Curly(3) Go(0): 3 Larry(1) Moe(2) Curly(3) Go(0): 0 Moe: slap head Larry: poke eyes Curly: suffer abuse

After

A factory method is a static method of a class that returns an object of that class’ type. But unlike a constructor, the actual object it returns might be an instance of a subclass. Another advantage of a factory method is that it can return existing instances multiple times.

class Stooge{  public:    // Factory Method    static Stooge *make_stooge(int choice);    virtual void slap_stick() = 0;};

int main(){  vector<Stooge*> roles;  int choice;  while (true)  {    cout << "Larry(1) Moe(2) Curly(3) Go(0): ";    cin >> choice;    if (choice == 0)      break;    roles.push_back(Stooge::make_stooge(choice));  }  for (int i = 0; i < roles.size(); i++)    roles[i]­>slap_stick();  for (int i = 0; i < roles.size(); i++)    delete roles[i];}

class Larry: public Stooge{  public:    void slap_stick()    {        cout << "Larry: poke eyes\n";    }

Page 36: Design Patterns

Creational patterns 36 of 205

};class Moe: public Stooge{  public:    void slap_stick()    {        cout << "Moe: slap head\n";    }};class Curly: public Stooge{  public:    void slap_stick()    {        cout << "Curly: suffer abuse\n";    }};

Stooge *Stooge::make_stooge(int choice){  if (choice == 1)    return new Larry;  else if (choice == 2)    return new Moe;  else    return new Curly;}

Another Factory Method C++ source code example

Discussion. Frameworks are applications (or subsystems) with “holes” in them. Each framework specifies the infrastructure, superstructure, and flow of control for its “domain”, and the client of the framework may: exercise the framework’s default behavior “as is”, extend selected pieces of the framework, or replace selected pieces.

The Factory Method pattern addresses the notion of “creation” in the context of frameworks. In this example, the framework knows WHEN a new document should be created, not WHAT kind of Document to create. The “placeholder” Application::CreateDocument() has been declared by the framework, and the client is expected to “fill in the blank” for his/her specific document(s). Then, when the client asks for Application::NewDocument(), the framework will subsequently call the client’s MyApplication::CreateDocument().

#include <iostream.h>

/* Abstract base class declared by framework */class Document{  public:    Document(char *fn)    {        strcpy(name, fn);    }    virtual void Open() = 0;    virtual void Close() = 0;    char *GetName()    {

Page 37: Design Patterns

Creational patterns 37 of 205

        return name;    }  private:    char name[20];};

/* Concrete derived class defined by client */class MyDocument: public Document{  public:    MyDocument(char *fn): Document(fn){}    void Open()    {        cout << "   MyDocument: Open()" << endl;    }    void Close()    {        cout << "   MyDocument: Close()" << endl;    }};

/* Framework declaration */class Application{  public:    Application(): _index(0)    {        cout << "Application: ctor" << endl;    }    /* The client will call this "entry point" of the framework */    NewDocument(char *name)    {        cout << "Application: NewDocument()" << endl;        /* Framework calls the "hole" reserved for client customization */        _docs[_index] = CreateDocument(name);        _docs[_index++]­>Open();    }    void OpenDocument(){}    void ReportDocs();    /* Framework declares a "hole" for the client to customize */    virtual Document *CreateDocument(char*) = 0;  private:    int _index;    /* Framework uses Document's base class */    Document *_docs[10];};

void Application::ReportDocs(){  cout << "Application: ReportDocs()" << endl;  for (int i = 0; i < _index; i++)    cout << "   " << _docs[i]­>GetName() << endl;}

/* Customization of framework defined by client */class MyApplication: public Application

Page 38: Design Patterns

Creational patterns 38 of 205

{  public:    MyApplication()    {        cout << "MyApplication: ctor" << endl;    }    /* Client defines Framework's "hole" */    Document *CreateDocument(char *fn)    {        cout << "   MyApplication: CreateDocument()" << endl;        return new MyDocument(fn);    }};

int main(){  /* Client's customization of the Framework */  MyApplication myApp;

  myApp.NewDocument("foo");  myApp.NewDocument("bar");  myApp.ReportDocs();}

output:

Application: ctorMyApplication: ctorApplication: NewDocument()   MyApplication: CreateDocument()   MyDocument: Open()Application: NewDocument()   MyApplication: CreateDocument()   MyDocument: Open()Application: ReportDocs()   foo   bar

Factory Method in Java

public interface ImageReader {    public DecodedImage getDecodedImage();}

public class GifReader implements ImageReader {    public GifReader( InputStream in ) {     // check that it's a gif, throw exception if it's not, then if it is decode it.    }

    public DecodedImage getDecodedImage() {       return decodedImage;    }}

public class JpegReader implements ImageReader {    //...}

Page 39: Design Patterns

Creational patterns 39 of 205

Object Pool Design Pattern

Intent

Object pooling can offer a significant performance boost; it is most effective in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high, and the number of instantiations in use at any one time is low.

Problem

Object pools (otherwise known as resource pools) are used to manage the object caching. A client with access to a Object pool can avoid creating a new Objects by simply asking the pool for one that has already been instantiated instead. Generally the pool will be a growing pool, i.e. the pool itself will create new objects if the pool is empty, or we can have a pool, which restricts the number of objects created.

It is desirable to keep all Reusable objects that are not currently in use in the same object pool so that they can be managed by one coherent policy. To achieve this, the Reusable Pool class is designed to be a singleton class.

Discussion

The Object Pool lets others “check out” objects from its pool, when those objects are no longer needed by their processes, they are returned to the pool in order to be reused.

However, we don’t want a process to have to wait for a particular object to be released, so the Object Pool also instantiates new objects as they are required, but must also implement a facility to clean up unused objects periodically.

Structure

The general idea for the Connection Pool pattern is that if instances of a class can be reused, you avoid creating instances of the class by reusing them.

• Reusable - Instances of classes in this role collaborate with other objects for a limited amount of time, then they are no longer needed for that collaboration.

• Client - Instances of classes in this role use Reusable objects.

• ReusablePool - Instances of classes in this role manage Reusable objects for use by Client objects.

Usually, it is desirable to keep all Reusable objects that are not currently in use in the same object pool so that they can be managed by one coherent policy. To achieve this, the ReusablePool class is designed to be a singleton class. Its constructor(s) are private, which forces other classes to call its getInstance method to get the one instance of the ReusablePool class.

A Client object calls a ReusablePool object’s acquireReusable method when it needs a Reusable object. A ReusablePool object maintains a collection of Reusable objects. It uses the collection of Reusable objects to contain a pool of Reusable objects that are not currently in use.

Page 40: Design Patterns

Creational patterns 40 of 205

If there are any Reusable objects in the pool when the acquireReusable method is called, it removes a Reusable object from the pool and returns it. If the pool is empty, then the acquireReusable method creates a Reusable object if it can. If the acquireReusable method cannot create a new Reusable object, then it waits until a Reusable object is returned to the collection.

Client objects pass a Reusable object to a ReusablePool object’s releaseReusable method when they are finished with the object. The releaseReusable method returns a Reusable object to the pool of Reusable objects that are not in use.

In many applications of the Object Pool pattern, there are reasons for limiting the total number of Reusable objects that may exist. In such cases, the ReusablePool object that creates Reusable objects is responsible for not creating more than a specified maximum number of Reusable objects. If ReusablePool objects are responsible for limiting the number of objects they will create, then the ReusablePool class will have a method for specifying the maximum number of objects to be created. That method is indicated in the above diagram as setMaxPoolSize.

Example

Do you like bowling? If you do, you probably know that you should change your shoes when you getting the bowling club. Shoe shelf is wonderful example of Object Pool. Once you want to play, you’ll get your pair (aquireReusable) from it. After the game, you’ll return shoes back to the shelf (releaseReusable).

Check list

1. Create ObjectPool class with private array of Objects inside

2. Create acquare and release methods in ObjectPool class

3. Make sure that your ObjectPool is Singleton

Page 41: Design Patterns

Creational patterns 41 of 205

Rules of thumb

• The Factory Method pattern can be used to encapsulate the creation logic for objects. However, it does not manage them after their creation, the object pool pattern keeps track of the objects it creates.

• Object Pools are usually implemented as Singletons.

Object Pool in Java

// ObjectPool Class

public abstract class ObjectPool<T> {  private long expirationTime;

  private Hashtable<T, Long> locked, unlocked;

  public ObjectPool() {    expirationTime = 30000; // 30 seconds    locked = new Hashtable<T, Long>();    unlocked = new Hashtable<T, Long>();  }

  protected abstract T create();

  public abstract boolean validate(T o);

  public abstract void expire(T o);

  public synchronized T checkOut() {    long now = System.currentTimeMillis();    T t;    if (unlocked.size() > 0) {      Enumeration<T> e = unlocked.keys();      while (e.hasMoreElements()) {        t = e.nextElement();        if ((now ­ unlocked.get(t)) > expirationTime) {          // object has expired          unlocked.remove(t);          expire(t);          t = null;        } else {          if (validate(t)) {            unlocked.remove(t);            locked.put(t, now);            return (t);          } else {            // object failed validation            unlocked.remove(t);            expire(t);            t = null;          }        }      }    }    // no objects available, create a new one

Page 42: Design Patterns

Creational patterns 42 of 205

    t = create();    locked.put(t, now);    return (t);  }

  public synchronized void checkIn(T t) {    locked.remove(t);    unlocked.put(t, System.currentTimeMillis());  }}

//The three remaining methods are abstract //and therefore must be implemented by the subclass

public class JDBCConnectionPool extends ObjectPool<Connection> {

  private String dsn, usr, pwd;

  public JDBCConnectionPool(String driver, String dsn, String usr, String pwd) {    super();    try {      Class.forName(driver).newInstance();    } catch (Exception e) {      e.printStackTrace();    }    this.dsn = dsn;    this.usr = usr;    this.pwd = pwd;  }

  @Override  protected Connection create() {    try {      return (DriverManager.getConnection(dsn, usr, pwd));    } catch (SQLException e) {      e.printStackTrace();      return (null);    }  }

  @Override  public void expire(Connection o) {    try {      ((Connection) o).close();    } catch (SQLException e) {      e.printStackTrace();    }  }

  @Override  public boolean validate(Connection o) {    try {      return (!((Connection) o).isClosed());    } catch (SQLException e) {      e.printStackTrace();      return (false);

Page 43: Design Patterns

Creational patterns 43 of 205

    }  }}

JDBCConnectionPool will allow the application to borrow and return database connections:

public class Main {  public static void main(String args[]) {    // Do something...    ...

    // Create the ConnectionPool:    JDBCConnectionPool pool = new JDBCConnectionPool(      "org.hsqldb.jdbcDriver", "jdbc:hsqldb://localhost/mydb",      "sa", "secret");

    // Get a connection:    Connection con = pool.checkOut();

    // Use the connection    ...

    // Return the connection:    pool.checkIn(con);   }}

Prototype Design Pattern

Intent

• Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

• Co-opt one instance of a class for use as a breeder of all future instances.

• The new operator considered harmful.

Problem

Application “hard wires” the class of object to create in each “new” expression.

Discussion

Declare an abstract base class that specifies a pure virtual “clone” method, and, maintains a dictionary of all “cloneable” concrete derived classes. Any class that needs a “polymorphic constructor” capability: derives itself from the abstract base class, registers its prototypical instance, and implements the clone() operation.

The client then, instead of writing code that invokes the “new” operator on a hard-wired class name, calls a “clone” operation on the abstract base class, supplying a string or enumerated data type that designates the particular concrete derived class desired.

Page 44: Design Patterns

Creational patterns 44 of 205

Structure

The Factory knows how to find the correct Prototype, and each Product knows how to spawn new instances of itself.

Example

The Prototype pattern specifies the kind of objects to create using a prototypical instance. Prototypes of new products are often built prior to full production, but in this example, the prototype is passive and does not participate in copying itself. The mitotic division of a cell - resulting in two identical cells - is an example of a prototype that plays an active role in copying itself and thus, demonstrates the Prototype pattern. When a cell splits, two cells of identical genotvpe result. In other words, the cell clones itself.

Check list

1. Add a clone() method to the existing “product” hierarchy.

2. Design a “registry” that maintains a cache of prototypical objects. The registry could be encapsulated in a new Factory class, or in the base class of the “product” hierarchy.

3. Design a factory method that: may (or may not) accept arguments, finds the correct prototype object, calls clone() on that object, and returns the result.

4. The client replaces all references to the new operator with calls to the factory method.

Page 45: Design Patterns

Creational patterns 45 of 205

Rules of thumb

• Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used properly. At other times they are complementory: Abstract Factory might store a set of Prototypes from which to clone and return product objects. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.

• Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.

• Factory Method: creation through inheritance. Protoype: creation through delegation.

• Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Protoype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

• Prototype doesn’t require subclassing, but it does require an “initialize” operation. Factory Method requires subclassing, but doesn’t require Initialize.

• Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.

• Prototype co-opts one instance of a class for use as a breeder of all future instances.

• Prototypes are useful when object initialization is expensive, and you anticipate few variations on the initialization parameters. In this context, Prototype can avoid expensive “creation from scratch”, and support cheap cloning of a pre-initialized prototype.

• Prototype is unique among the other creational patterns in that it doesn’t require a class – only an object. Object-oriented languages like Self and Omega that do away with classes completely rely on prototypes for creating new objects.

Prototype in C++: Before and after

Before

The architect has done an admirable job of decoupling the client from Stooge concrete derived classes, and, exercising polymorphism. But there remains coupling where instances are actually created.

class Stooge{  public:    virtual void slap_stick() = 0;};

class Larry: public Stooge{  public:    void slap_stick()    {        cout << "Larry: poke eyes\n";    }};class Moe: public Stooge{  public:    void slap_stick()

Page 46: Design Patterns

Creational patterns 46 of 205

    {        cout << "Moe: slap head\n";    }};class Curly: public Stooge{  public:    void slap_stick()    {        cout << "Curly: suffer abuse\n";    }};

int main(){  vector roles;  int choice;

  while (true)  {    cout << "Larry(1) Moe(2) Curly(3) Go(0): ";    cin >> choice;    if (choice == 0)      break;    else if (choice == 1)      roles.push_back(new Larry);    else if (choice == 2)      roles.push_back(new Moe);    else      roles.push_back(new Curly);  }  for (int i = 0; i < roles.size(); i++)    roles[i]­>slap_stick();  for (int i = 0; i < roles.size(); i++)    delete roles[i];}

output:

Larry(1) Moe(2) Curly(3) Go(0): 2 Larry(1) Moe(2) Curly(3) Go(0): 1 Larry(1) Moe(2) Curly(3) Go(0): 3 Larry(1) Moe(2) Curly(3) Go(0): 0 Moe: slap head Larry: poke eyes Curly: suffer abuse

After

A clone() method has been added to the Stooge hierarchy. Each derived class implements that method by returning an instance of itself. A Factory class has been introduced that main- tains a suite of “breeder” objects (aka proto- types), and knows how to delegate to the correct prototype.

class Stooge {public:   virtual Stooge* clone() = 0;

Page 47: Design Patterns

Creational patterns 47 of 205

   virtual void slap_stick() = 0;};

class Factory {public:   static Stooge* make_stooge( int choice );private:   static Stooge* s_prototypes[4];};

int main() {   vector roles;   int             choice;

   while (true) {      cout << "Larry(1) Moe(2) Curly(3) Go(0): ";      cin >> choice;      if (choice == 0)         break;      roles.push_back(         Factory::make_stooge( choice ) );   }

   for (int i=0; i < roles.size(); ++i)      roles[i]­>slap_stick();   for (int i=0; i < roles.size(); ++i)      delete roles[i];}

class Larry : public Stooge {public:   Stooge*   clone() { return new Larry; }   void slap_stick() {      cout << "Larry: poke eyes\n"; }};class Moe : public Stooge {public:   Stooge*   clone() { return new Moe; }   void slap_stick() {      cout << "Moe: slap head\n"; }};class Curly : public Stooge {public:   Stooge*   clone() { return new Curly; }   void slap_stick() {      cout << "Curly: suffer abuse\n"; }};

Stooge* Factory::s_prototypes[] = {   0, new Larry, new Moe, new Curly};Stooge* Factory::make_stooge( int choice ) {   return s_prototypes[choice]­>clone();}

Page 48: Design Patterns

Creational patterns 48 of 205

Prototype in C++

Prototype design pattern demo

Discussion. Image base class provides the mechanism for storing, finding, and cloning the prototype for all derived classes. Each derived class specifies a private static data member whose initialization “registers” a prototype of itself with the base class. When the client asks for a “clone” of a certain type, the base class finds the prototype and calls clone() on the correct derived class.

#include <iostream.h>

enum imageType{  LSAT, SPOT};

class Image{  public:    virtual void draw() = 0;    static Image *findAndClone(imageType);  protected:    virtual imageType returnType() = 0;    virtual Image *clone() = 0;    // As each subclass of Image is declared, it registers its prototype    static void addPrototype(Image *image)    {        _prototypes[_nextSlot++] = image;    }  private:    // addPrototype() saves each registered prototype here    static Image *_prototypes[10];    static int _nextSlot;};

Image *Image::_prototypes[];int Image::_nextSlot;

// Client calls this public static member function when it needs an instance// of an Image subclassImage *Image::findAndClone(imageType type){  for (int i = 0; i < _nextSlot; i++)    if (_prototypes[i]­>returnType() == type)      return _prototypes[i]­>clone();}

class LandSatImage: public Image{  public:    imageType returnType()    {        return LSAT;    }    void draw()

Page 49: Design Patterns

Creational patterns 49 of 205

    {        cout << "LandSatImage::draw " << _id << endl;    }    // When clone() is called, call the one­argument ctor with a dummy arg    Image *clone()    {        return new LandSatImage(1);    }  protected:    // This is only called from clone()    LandSatImage(int dummy)    {        _id = _count++;    }  private:    // Mechanism for initializing an Image subclass ­ this causes the    // default ctor to be called, which registers the subclass's prototype    static LandSatImage _landSatImage;    // This is only called when the private static data member is inited    LandSatImage()    {        addPrototype(this);    }    // Nominal "state" per instance mechanism    int _id;    static int _count;};

// Register the subclass's prototypeLandSatImage LandSatImage::_landSatImage;// Initialize the "state" per instance mechanismint LandSatImage::_count = 1;

class SpotImage: public Image{  public:    imageType returnType()    {        return SPOT;    }    void draw()    {        cout << "SpotImage::draw " << _id << endl;    }    Image *clone()    {        return new SpotImage(1);    }  protected:    SpotImage(int dummy)    {        _id = _count++;    }  private:    SpotImage()    {

Page 50: Design Patterns

Creational patterns 50 of 205

        addPrototype(this);    }    static SpotImage _spotImage;    int _id;    static int _count;};

SpotImage SpotImage::_spotImage;int SpotImage::_count = 1;

// Simulated stream of creation requestsconst int NUM_IMAGES = 8;imageType input[NUM_IMAGES] = {  LSAT, LSAT, LSAT, SPOT, LSAT, SPOT, SPOT, LSAT};

int main(){  Image *images[NUM_IMAGES];

  // Given an image type, find the right prototype, and return a clone  for (int i = 0; i < NUM_IMAGES; i++)    images[i] = Image::findAndClone(input[i]);

  // Demonstrate that correct image objects have been cloned  for (i = 0; i < NUM_IMAGES; i++)    images[i]­>draw();

  // Free the dynamic memory  for (i = 0; i < NUM_IMAGES; i++)    delete images[i];}

output:

LandSatImage::draw 1 LandSatImage::draw 2 LandSatImage::draw 3 SpotImage::draw 1 LandSatImage::draw 4 SpotImage::draw 2 SpotImage::draw 3 LandSatImage::draw 5 

Prototype in Java

Abstract Factory might store a set of Prototypes from which to clone and return product objects.

public class FactoryProto {  interface Xyz {    Xyz cloan();  }

  static class Tom implements Xyz {    public Xyz    cloan()    {

Page 51: Design Patterns

Creational patterns 51 of 205

      return new Tom();    }    public String toString() {      return "ttt";    }  }

  static class Dick implements Xyz {    public Xyz    cloan()    {      return new Dick();    }    public String toString() {      return "ddd";    }  }

  static class Harry implements Xyz {    public Xyz    cloan()    {      return new Harry();    }    public String toString() {      return "hhh";    }  }

  static class Factory {    private static java.util.Map prototypes = new java.util.HashMap();    static {      prototypes.put( "tom",   new Tom() );      prototypes.put( "dick",  new Dick() );      prototypes.put( "harry", new Harry() );    }    public static Xyz makeObject( String s ) {      return ((Xyz)prototypes.get(s)).cloan();    }  }

  public static void main( String[] args ) {    for (int i=0; i < args.length; i++) {      System.out.print( Factory.makeObject( args[i] ) + "  " );    }  }}

output:

D:\Java\patterns> java FactoryProto tom dick tom harry tom ttt ddd ttt hhh ttt 

Prototype in Java 2

Prototype design pattern

1. Create a “contract” with clone() and getName() entries

2. Design a “registry” that maintains a cache of prototypical objects

Page 52: Design Patterns

Creational patterns 52 of 205

3. Populate the registry with an initializePrototypes() function

4. The registry has a findAndClone() “virtual constructor” that can transform a String into its correct object (it calls clone() which then calls “new”)

5. All classes relate themselves to the clone() contract

6. Client uses the findAndClone() virtual ctor instead of the “new” operator

interface Prototype {  Object clone();  String getName();}// 1. The clone() contractinterface Command {  void execute();}

class PrototypesModule {  // 2. "registry" of prototypical objs  private static Prototype[] prototypes = new Prototype[9];  private static int total = 0;

  // Adds a feature to the Prototype attribute of the PrototypesModule class  // obj  The feature to be added to the Prototype attribute  public static void addPrototype( Prototype obj ) {    prototypes[total++] = obj;  }

  public static Object findAndClone( String name ) {    // 4. The "virtual ctor"    for ( int i = 0; i < total; i++ ) {      if ( prototypes[i].getName().equals( name ) ) {        return prototypes[i].clone();      }    }    System.out.println( name + " not found" );    return null;  }}

// 5. Sign­up for the clone() contract.// Each class calls "new" on itself FOR the client.class This implements Prototype, Command {  public Object clone() {    return new This();  }  public String getName() {    return "This";  }  public void execute() {    System.out.println( "This: execute" );  }}

class That implements Prototype, Command {  public Object clone() {

Page 53: Design Patterns

Creational patterns 53 of 205

    return new That();  }  public String getName() {    return "That";  }  public void execute() {    System.out.println( "That: execute" );  }}

class TheOther implements Prototype, Command {  public Object clone() {    return new TheOther();  }  public String getName() {    return "TheOther";  }  public void execute() {    System.out.println( "TheOther: execute" );  }}

public class PrototypeDemo {  // 3. Populate the "registry"  public static void initializePrototypes() {    PrototypesModule.addPrototype( new This() );    PrototypesModule.addPrototype( new That() );    PrototypesModule.addPrototype( new TheOther() );  }  public static void main( String[] args ) {    initializePrototypes();    Object[] objects = new Object[9];    int total = 0;

    // 6. Client does not use "new"    for (int i=0; i < args.length; i++) {      objects[total] = PrototypesModule.findAndClone( args[i] );      if (objects[total] != null) total++;    }    for (int i=0; i < total; i++) {      ((Command)objects[i]).execute();    }  }}

C:> java PrototypeDemo Garbage This That Nothing TheOther Garbage not found Nothing not found This: execute That: execute TheOther: execute

Singleton Design Pattern

Page 54: Design Patterns

Creational patterns 54 of 205

Intent

• Ensure a class has only one instance, and provide a global point of access to it.

• Encapsulated “just-in-time initialization” or “initialization on first use”.

Problem

Application needs one, and only one, instance of an object. Additionally, lazy initialization and global access are necessary.

Discussion

Make the class of the single instance object responsible for creation, initialization, access, and enforcement. Declare the instance as a private static data member. Provide a public static member function that encapsulates all initialization code, and provides access to the instance.

The client calls the accessor function (using the class name and scope resolution operator) whenever a reference to the single instance is required.

Singleton should be considered only if all three of the following criteria are satisfied:

• Ownership of the single instance cannot be reasonably assigned

• Lazy initialization is desirable

• Global access is not otherwise provided for

If ownership of the single instance, when and how initialization occurs, and global access are not issues, Singleton is not sufficiently interesting.

The Singleton pattern can be extended to support access to an application-specific number of instances.

The “static member function accessor” approach will not support subclassing of the Singleton class. If subclassing is desired, refer to the discussion in the book.

Deleting a Singleton class/instance is a non-trivial design problem.

Structure

Make the class of the single instance responsible for access and “initialization on first use”. The single instance is a private static attribute. The accessor function is a public static method.

Example

The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance. It is named after the singleton set, which is defined to be a set containing one element. The office of the President of the United States is a Singleton. The United States Constitution specifies the means by which a president is elected, limits the term of office, and defines the order of succession. As a result, there can be at most one active president at any

Page 55: Design Patterns

Creational patterns 55 of 205

given time. Regardless of the personal identity of the active president, the title, “The President of the United States” is a global point of access that identifies the person in the office.

Check list

1. Define a private static attribute in the “single instance” class.

2. Define a public static accessor function in the class.

3. Do “lazy initialization” (creation on first use) in the accessor function.

4. Define all constructors to be protected or private.

5. Clients may only use the accessor function to manipulate the Singleton.

Rules of thumb

• Abstract Factory, Builder, and Prototype can use Singleton in their implementation.

• Facade objects are often Singletons because only one Facade object is required.

• State objects are often Singletons.

• The advantage of Singleton over global variables is that you are absolutely sure of the number of instances when you use Singleton, and, you can change your mind and manage any number of instances.

• The Singleton design pattern is one of the most inappropriately used patterns. Singletons are intended to be used when a class must have exactly one instance, no more, no less. Designers frequently use Singletons in a misguided attempt to replace global variables. A Singleton is, for intents and purposes, a global variable. The Singleton does not do away with the global; it merely renames it.

• When is Singleton unnecessary? Short answer: most of the time. Long answer: when it’s simpler to pass an object resource as a reference to the objects that need it, rather than letting objects access the resource globally. The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object. Finding the right balance of exposure and protection for an object is critical for maintaining flexibility.

• Our group had a bad habit of using global data, so I did a study group on Singleton. The next thing I know Singletons appeared everywhere and none of the problems related to global data went away. The answer to the global data question is not, “Make it a Singleton.” The answer is, “Why in the hell are you using global data?” Changing the name doesn’t change the problem. In fact, it may make it worse because it gives you the opportunity to say, “Well I’m not doing that, I’m doing this” – even though this and that are the same thing.

Page 56: Design Patterns

Creational patterns 56 of 205

Singleton in C++: Before and after

Before

A global variable is default initialized - when it is declared - but it is not initialized in earnest until its first use. This requires that the initialization code be replicated throughout the application.

class GlobalClass{    int m_value;  public:    GlobalClass(int v = 0)    {        m_value = v;    }    int get_value()    {        return m_value;    }    void set_value(int v)    {        m_value = v;    }};

// Default initializationGlobalClass *global_ptr = 0;

void foo(void){  // Initialization on first use  if (!global_ptr)    global_ptr = new GlobalClass;  global_ptr­>set_value(1);  cout << "foo: global_ptr is " << global_ptr­>get_value() << '\n';}

void bar(void){  if (!global_ptr)    global_ptr = new GlobalClass;  global_ptr­>set_value(2);  cout << "bar: global_ptr is " << global_ptr­>get_value() << '\n';}

int main(){  if (!global_ptr)    global_ptr = new GlobalClass;  cout << "main: global_ptr is " << global_ptr­>get_value() << '\n';  foo();  bar();}

output:main: global_ptr is 0 foo: global_ptr is 1 

Page 57: Design Patterns

Creational patterns 57 of 205

bar: global_ptr is 2

After

Make the class responsible for its own global pointer and "initialization on first use" (by using a private static pointer and a public static accessor method). The client uses only the public accessor method.

class GlobalClass{    int m_value;    static GlobalClass *s_instance;    GlobalClass(int v = 0)    {        m_value = v;    }  public:    int get_value()    {        return m_value;    }    void set_value(int v)    {        m_value = v;    }    static GlobalClass *instance()    {        if (!s_instance)          s_instance = new GlobalClass;        return s_instance;    }};

// Allocating and initializing GlobalClass's// static data member.  The pointer is being// allocated ­ not the object inself.GlobalClass *GlobalClass::s_instance = 0;

void foo(void){  GlobalClass::instance()­>set_value(1);  cout << "foo: global_ptr is " << GlobalClass::instance()­>get_value() << '\n';}

void bar(void){  GlobalClass::instance()­>set_value(2);  cout << "bar: global_ptr is " << GlobalClass::instance()­>get_value() << '\n';}

int main(){  cout << "main: global_ptr is " << GlobalClass::instance()­>get_value() << '\n';  foo();  bar();}

Page 58: Design Patterns

Creational patterns 58 of 205

output:main: global_ptr is 0 foo: global_ptr is 1 bar: global_ptr is 2

Singleton in C++

Singleton design pattern

1. Define a private static attribute in the “single instance” class

2. Define a public static accessor function in the class

3. Do “lazy initialization” (creation on demand) in the accessor function

4. Define all constructors to be protected or private

5. Clients may only use the accessor function to manipulate the Singleton

6. Inheritance can be supported, but static functions may not be overridden. The base class must be declared a friend of the derived class (in order to access the protected constructor).

#include <iostream>#include <string>#include <stdlib.h>using namespace std;

class Number{  public:    // 2. Define a public static accessor func    static Number *instance();     static void setType(string t)    {      type = t;      delete inst;      inst = 0;    }    virtual void setValue(int in)    {      value = in;    }    virtual int getValue()    {      return value;    }  protected:    int value;    // 4. Define all ctors to be protected    Number()    {        cout << ":ctor: ";    }   // 1. Define a private static attribute  private:    static string type;

Page 59: Design Patterns

Creational patterns 59 of 205

    static Number *inst; };

string Number::type = "decimal";Number *Number::inst = 0;

class Octal: public Number{  // 6. Inheritance can be supported  public:    friend class Number;    void setValue(int in)    {      char buf[10];      sprintf(buf, "%o", in);      sscanf(buf, "%d", &value);    }  protected:    Octal(){}};

Number *Number::instance(){  if (!inst)    // 3. Do "lazy initialization" in the accessor function    if (type == "octal")      inst = new Octal();    else      inst = new Number();  return inst;}

int main(){  // Number  myInstance; ­ error: cannot access protected constructor  // 5. Clients may only use the accessor function to manipulate the Singleton  Number::instance()­>setValue(42);  cout << "value is " << Number::instance()­>getValue() << endl;  Number::setType("octal");  Number::instance()­>setValue(64);  cout << "value is " << Number::instance()­>getValue() << endl;}

output::ctor: value is 42 :ctor: value is 100

Singleton in Java

University of Maryland Computer Science researcher Bill Pugh has written about the code issues underlying the Singleton pattern when implemented in Java. Pugh’s efforts on the “Double-checked locking” idiom led to changes in the Java memory model in Java 5 and to what is generally regarded as the standard method to implement Singletons in Java. The technique is known as the initialization on demand holder idiom, is as lazy as possible, and works in all known versions of Java. It takes advantage of language guarantees about class initialization, and will therefore work correctly in all Java-compliant compilers and virtual machines.

Page 60: Design Patterns

Creational patterns 60 of 205

The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).

public class Singleton {  // Private constructor prevents instantiation from other classes  private Singleton() {}   /**   * SingletonHolder is loaded on the first execution of Singleton.getInstance()    * or the first access to SingletonHolder.INSTANCE, not before.   */  private static class SingletonHolder {     private static final Singleton INSTANCE = new Singleton();  }

  public static Singleton getInstance() {    return SingletonHolder.INSTANCE;  }}

Page 61: Design Patterns

Structural patterns 61 of 205

Structural patterns

IntroductionIn Software Engineering, Structural Design Patterns are Design Patterns that ease the design by identifying a simple way to realize relationships between entities.

• Adapter

◦ Match interfaces of different classes

• Bridge

◦ Separates an object’s interface from its implementation

• Composite

◦ A tree structure of simple and composite objects

• Decorator

◦ Add responsibilities to objects dynamically

• Facade

◦ A single class that represents an entire subsystem

• Flyweight

◦ A fine-grained instance used for efficient sharing

• Private Class Data

◦ Restricts accessor/mutator access

• Proxy

◦ An object representing another object

Rules of thumb

1. Adapter makes things work after they’re designed; Bridge makes them work before they are.

2. Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.

3. Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.

4. Adapter changes an object’s interface, Decorator enhances an object’s responsibilities. Decorator is thus more transparent to the client. As a consequence, Decorator supports recursive composition, which isn’t possible with pure Adapters.

5. Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.

6. Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. Composite could use Chain of responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.

Page 62: Design Patterns

Structural patterns 62 of 205

7. Composite can let you compose a Mediator out of smaller pieces through recursive composition.

8. Decorator lets you change the skin of an object. Strategy lets you change the guts.

9. Decorator is designed to let you add responsibilities to objects without subclassing. Composite’s focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.

10. Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.

11. Facade defines a new interface, whereas Adapter reuses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.

12. Facade objects are often Singleton because only one Facade object is required.

13. Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely “adds value”, and it is known/referenced by the colleague objects. In contrast, Facade defines a simpler interface to a subsystem, it doesn’t add new functionality, and it is not known by the subsystem classes.

14. Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.

15. Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.

16. Flyweight is often combined with Composite to implement shared leaf nodes.

17. Flyweight explains when and how State objects can be shared.

Adapter Design Pattern

Intent

• Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

• Wrap an existing class with a new interface.

• Impedance match an old component to a new system

Problem

An “off the shelf” component offers compelling functionality that you would like to reuse, but its “view of the world” is not compatible with the philosophy and architecture of the system currently being developed.

Discussion

Reuse has always been painful and elusive. One reason has been the tribulation of designing something new, while reusing something old. There is always something not quite right between the old and the new. It may be physical dimensions or misalignment. It may be timing or synchronization. It may be unfortunate assumptions or competing standards.

It is like the problem of inserting a new three-prong electrical plug in an old two-prong wall

Page 63: Design Patterns

Structural patterns 63 of 205

outlet – some kind of adapter or intermediary is necessary.

Adapter is about creating an intermediary abstraction that translates, or maps, the old component to the new system. Clients call methods on the Adapter object which redirects them into calls to the legacy component. This strategy can be implemented either with inheritance or with aggregation.

Adapter functions as a wrapper or modifier of an existing class. It provides a different or translated view of that class.

Structure

Below, a legacy Rectangle component’s display() method expects to receive “x, y, w, h” parameters. But the client wants to pass “upper left x and y” and “lower right x and y”. This incongruity can be reconciled by adding an additional level of indirection – i.e. an Adapter object.

The Adapter could also be thought of as a “wrapper”.

Page 64: Design Patterns

Structural patterns 64 of 205

Example

The Adapter pattern allows otherwise incompatible classes to work together by converting the interface of one class into an interface expected by the clients. Socket wrenches provide an example of the Adapter. A socket attaches to a ratchet, provided that the size of the drive is the same. Typical drive sizes in the United States are 1/2” and 1/4”. Obviously, a 1/2” drive ratchet will not fit into a 1/4” drive socket unless an adapter is used. A 1/2” to 1/4” adapter has a 1/2” female connection to fit on the 1/2” drive ratchet, and a 1/4” male connection to fit in the 1/4” drive socket.

Check list

1. Identify the players: the component(s) that want to be accommodated (i.e. the client), and the component that needs to adapt (i.e. the adaptee).

2. Identify the interface that the client requires.

3. Design a “wrapper” class that can “impedance match” the adaptee to the client.

4. The adapter/wrapper class “has a” instance of the adaptee class.

5. The adapter/wrapper class “maps” the client interface to the adaptee interface.

6. The client uses (is coupled to) the new interface

Rules of thumb

• Adapter makes things work after they’re designed; Bridge makes them work before they are.

• Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.

• Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.

• Adapter is meant to change the interface of an existing object. Decorator enhances

Page 65: Design Patterns

Structural patterns 65 of 205

another object without changing its interface. Decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn’t possible with pure Adapters.

• Facade defines a new interface, whereas Adapter reuses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.

Adapter in C++

Adapter design pattern demo

Discussion. LegacyRectangle’s interface is not compatible with the system that would like to reuse it. An abstract base class is created that specifies the desired interface. An “adapter” class is defined that publicly inherits the interface of the abstract class, and privately inherits the implementation of the legacy component. This adapter class “maps” or “impedance matches” the new interface to the old implementation.

#include <iostream.h>

typedef int Coordinate;typedef int Dimension;

// Desired interfaceclass Rectangle{  public:    virtual void draw() = 0;};

// Legacy componentclass LegacyRectangle{  public:    LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2)    {        x1_ = x1;        y1_ = y1;        x2_ = x2;        y2_ = y2;        cout << "LegacyRectangle:  create.  (" << x1_ << "," << y1_ << ") => ("          << x2_ << "," << y2_ << ")" << endl;    }    void oldDraw()    {        cout << "LegacyRectangle:  oldDraw.  (" << x1_ << "," << y1_ <<           ") => (" << x2_ << "," << y2_ << ")" << endl;    }  private:    Coordinate x1_;    Coordinate y1_;    Coordinate x2_;    Coordinate y2_;

Page 66: Design Patterns

Structural patterns 66 of 205

};

// Adapter wrapperclass RectangleAdapter: public Rectangle, private LegacyRectangle{  public:    RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h):      LegacyRectangle(x, y, x + w, y + h)    {        cout << "RectangleAdapter: create.  (" << x << "," << y <&lt;           "), width = " &lt;&lt; w &lt;&lt; ", height = " &lt;&lt; h &lt;&lt; endl;    }    virtual void draw()    {        cout &lt;&lt; "RectangleAdapter: draw." &lt;&lt; endl;        oldDraw();    }};

int main(){  Rectangle *r = new RectangleAdapter(120, 200, 60, 40);  r­>draw();}output:LegacyRectangle: create. (120,200) => (180,240) RectangleAdapter: create. (120,200), width = 60, height = 40 RectangleAdapter: draw. LegacyRectangle: oldDraw. (120,200) => (180,240)

Adapter in C++: External Polymorphism

1. Specify the new desired interface

2. Design a “wrapper” class that can “impedance match” the old to the new

3. The client uses (is coupled to) the new interface

4. The adapter/wrapper “maps” to the legacy implementation

#include "stdafx.h"#include <iostream>

using namespace std;class ExecuteInterface {  public:    // 1. Specify the new interface    virtual ~ExecuteInterface(){}    virtual void execute() = 0;};

// 2. Design a "wrapper" or "adapter" classtemplate <class TYPE>class ExecuteAdapter: public ExecuteInterface {  public:    ExecuteAdapter(TYPE *o, void(TYPE:: *m)()) {

Page 67: Design Patterns

Structural patterns 67 of 205

      object = o;      method = m;    }    ~ExecuteAdapter() {      delete object;    }

    // 4. The adapter/wrapper "maps" the new to the legacy implementation    void execute() {  /* the new */      (object­>*method)();    }  private:    TYPE *object; // ptr­to­object attribute

    void(TYPE:: *method)(); /* the old */     // ptr­to­member­function attribute};

// The old: three totally incompatible classes// no common base class,class Fea {  public:  // no hope of polymorphism  ~Fea() {    cout << "Fea::dtor" << endl;  }  void doThis() {    cout << "Fea::doThis()" << endl;  }};

class Feye {  public:~Feye() {    cout << "Feye::dtor" << endl;  }  void doThat() {    cout << "Feye::doThat()" << endl;  }};

class Pheau {  public:  ~Pheau() {    cout << "Pheau::dtor" << endl;  }  void doTheOther() {    cout << "Pheau::doTheOther()" << endl;  }};

/* the new is returned */ExecuteInterface **initialize() {  ExecuteInterface **array = new ExecuteInterface *[3];

  /* the old is below */

Page 68: Design Patterns

Structural patterns 68 of 205

  array[0] = new ExecuteAdapter < Fea > (new Fea(), &Fea::doThis);  array[1] = new ExecuteAdapter < Feye > (new Feye(), &Feye::doThat);  array[2] = new ExecuteAdapter < Pheau > (new Pheau(), &Pheau::doTheOther);  return array;}

int main() {  ExecuteInterface **objects = initialize();  for (int i = 0; i < 3; i++) {   objects[i]­>execute();  }   // 3. Client uses the new (polymporphism)  for (i = 0; i < 3; i++) {    delete objects[i];  }  delete objects;  return 0;}

output:

Fea::doThis() Feye::doThat() Pheau::doTheOther() Fea::dtor Feye::dtor Pheau::dtor

Adapter in Java: Before and after

Before

Because the interface between Line and Rectangle objects is incapatible, the user has to recover the type of each shape and manually supply the correct arguments.

class LegacyLine{    public void draw(int x1, int y1, int x2, int y2)    {        System.out.println("line from (" + x1 + ',' + y1 + ") to (" + x2 + ','           + y2 + ')');    }}

class LegacyRectangle{    public void draw(int x, int y, int w, int h)    {        System.out.println("rectangle at (" + x + ',' + y + ") with width " + w          + " and height " + h);    }}

public class AdapterDemo

Page 69: Design Patterns

Structural patterns 69 of 205

{    public static void main(String[] args)    {        Object[] shapes =         {            new LegacyLine(), new LegacyRectangle()        };        // A begin and end point from a graphical editor        int x1 = 10, y1 = 20;        int x2 = 30, y2 = 60;        for (int i = 0; i < shapes.length; ++i)          if (shapes[i].getClass().getName().equals("LegacyLine"))            ((LegacyLine)shapes[i]).draw(x1, y1, x2, y2);          else if (shapes[i].getClass().getName().equals("LegacyRectangle"))            ((LegacyRectangle)shapes[i]).draw(Math.min(x1, x2), Math.min(y1, y2)              , Math.abs(x2 ­ x1), Math.abs(y2 ­ y1));    }}line from (10,20) to (30,60) rectangle at (10,20) with width 20 and height 40

After

The Adapter’s “extra level of indirection” takes care of mapping a user-friendly common interface to legacy-specific peculiar interfaces.

class LegacyLine{    public void draw(int x1, int y1, int x2, int y2)    {        System.out.println("line from (" + x1 + ',' + y1 + ") to (" + x2 + ','           + y2 + ')');    }}

class LegacyRectangle{    public void draw(int x, int y, int w, int h)    {        System.out.println("rectangle at (" + x + ',' + y + ") with width " + w          + " and height " + h);    }}

interface Shape{  void draw(int x1, int y1, int x2, int y2);}

class Line implements Shape{    private LegacyLine adaptee = new LegacyLine();    public void draw(int x1, int y1, int x2, int y2)    {        adaptee.draw(x1, y1, x2, y2);    }}

Page 70: Design Patterns

Structural patterns 70 of 205

class Rectangle implements Shape{    private LegacyRectangle adaptee = new LegacyRectangle();    public void draw(int x1, int y1, int x2, int y2)    {        adaptee.draw(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 ­ x1),          Math.abs(y2 ­ y1));    }}

public class AdapterDemo{    public static void main(String[] args)    {        Shape[] shapes =         {            new Line(), new Rectangle()        };        // A begin and end point from a graphical editor        int x1 = 10, y1 = 20;        int x2 = 30, y2 = 60;        for (int i = 0; i < shapes.length; ++i)          shapes[i].draw(x1, y1, x2, y2);    }}

output:

line from (10,20) to (30,60) rectangle at (10,20) with width 20 and height 40

Adapter in Java

Another Adapter source code example

1. Identify the desired interface.

2. Design a “wrapper” class that can “impedance match” the old to the new.

3. The adapter/wrapper class “has a” instance of the legacy class.

4. The adapter/wrapper class “maps” (or delegates) to the legacy object.

5. The client uses (is coupled to) the new interface.

/* The OLD */class SquarePeg {   private double width;   public SquarePeg( double w )       { width = w; }   public double getWidth()           { return width; }   public void   setWidth( double w ) { width = w; }}

/* The NEW */class RoundHole {

Page 71: Design Patterns

Structural patterns 71 of 205

   private int radius;   public RoundHole( int r ) {      radius = r;      System.out.println( "RoundHole: max SquarePeg is " + r * Math.sqrt(2) );   }   public int getRadius() { return radius; }}

// Design a "wrapper" class that can "impedance match" the old to the newclass SquarePegAdapter {

   // The adapter/wrapper class "has a" instance of the legacy class   private SquarePeg sp;

   public SquarePegAdapter( double w ) { sp = new SquarePeg( w ); }

   // Identify the desired interface   public void makeFit( RoundHole rh ) {      // The adapter/wrapper class delegates to the legacy object      double amount = sp.getWidth() ­ rh.getRadius() * Math.sqrt(2);      System.out.println( "reducing SquarePeg " + sp.getWidth() + " by " + ((amount < 0) ? 0 : amount) + " amount" );      if (amount > 0) {         sp.setWidth( sp.getWidth() ­ amount );         System.out.println( "   width is now " + sp.getWidth() );      }   }}

class AdapterDemoSquarePeg {   public static void main( String[] args ) {      RoundHole        rh = new RoundHole( 5 );      SquarePegAdapter spa;

      for (int i=6; i < 10; i++) {         spa = new SquarePegAdapter( (double) i );         // The client uses (is coupled to) the new interface         spa.makeFit( rh );      }   }}

output:

RoundHole: max SquarePeg is 7.0710678118 reducing SquarePeg 6.0 by 0.0 amount reducing SquarePeg 7.0 by 0.0 amount reducing SquarePeg 8.0 by 0.9289321881345245 amount width is now 7.0710678118654755 reducing SquarePeg 9.0 by 1.9289321881345245 amount width is now 7.0710678118654755

Bridge Design Pattern

Intent

• Decouple an abstraction from its implementation so that the two can vary independently.

Page 72: Design Patterns

Structural patterns 72 of 205

• Publish interface in an inheritance hierarchy, and bury implementation in its own inheritance hierarchy.

• Beyond encapsulation, to insulation

Problem

“Hardening of the software arteries” has occurred by using subclassing of an abstract base class to provide alternative implementations. This locks in compile-time binding between interface and implementation. The abstraction and implementation cannot be independently extended or composed.

Motivation

Consider the domain of “thread scheduling”.

There are two types of thread schedulers, and two types of operating systems or “platforms”. Given this approach to specialization, we have to define a class for each permutation of these two dimensions. If we add a new platform (say … Java’s Virtual Machine), what would our hierarchy look like?

What if we had three kinds of thread schedulers, and four kinds of platforms? What if we had five kinds of thread schedulers, and ten kinds of platforms? The number of classes we would have to define is the product of the number of scheduling schemes and the number of platforms.

The Bridge design pattern proposes refactoring this exponentially explosive inheritance hierarchy into two orthogonal hierarchies – one for platform-independent abstractions, and the other for platform-dependent implementations.

Page 73: Design Patterns

Structural patterns 73 of 205

Discussion

Decompose the component’s interface and implementation into orthogonal class hierarchies. The interface class contains a pointer to the abstract implementation class. This pointer is initialized with an instance of a concrete implementation class, but all subsequent interaction from the interface class to the implementation class is limited to the abstraction maintained in the implementation base class. The client interacts with the interface class, and it in turn “delegates” all requests to the implementation class.

The interface object is the “handle” known and used by the client; while the implementation object, or “body”, is safely encapsulated to ensure that it may continue to evolve, or be entirely replaced (or shared at run-time.

Use the Bridge pattern when:

• you want run-time binding of the implementation,

• you have a proliferation of classes resulting from a coupled interface and numerous implementations,

• you want to share an implementation among multiple objects,

• you need to map orthogonal class hierarchies.

Consequences include:

• decoupling the object’s interface,

• improved extensibility (you can extend (i.e. subclass) the abstraction and implementation hierarchies independently),

• hiding details from clients.

Bridge is a synonym for the “handle/body” idiom. This is a design mechanism that encapsulates an implementation class inside of an interface class. The former is the body, and the latter is the handle. The handle is viewed by the user as the actual class, but the work is done in the body. “The handle/body class idiom may be used to decompose a complex abstraction into smaller, more manageable classes. The idiom may reflect the sharing of a single resource by multiple classes that control access to it (e.g. reference counting).”

Structure

The Client doesn’t want to deal with platform-dependent details. The Bridge pattern encapsulates this complexity behind an abstraction “wrapper”.

Bridge emphasizes identifying and decoupling “interface” abstraction from “implementation” abstraction.

Page 74: Design Patterns

Structural patterns 74 of 205

Example

The Bridge pattern decouples an abstraction from its implementation, so that the two can vary independently. A household switch controlling lights, ceiling fans, etc. is an example of the Bridge. The purpose of the switch is to turn a device on or off. The actual switch can be implemented as a pull chain, simple two position switch, or a variety of dimmer switches.

Check list

1. Decide if two orthogonal dimensions exist in the domain. These independent concepts could be: abstraction/platform, or domain/infrastructure, or front-end/back-end, or interface/implementation.

2. Design the separation of concerns: what does the client want, and what do the platforms provide.

3. Design a platform-oriented interface that is minimal, necessary, and sufficient. Its goal is to decouple the abstraction from the platform.

Page 75: Design Patterns

Structural patterns 75 of 205

4. Define a derived class of that interface for each platform.

5. Create the abstraction base class that “has a” platform object and delegates the platform-oriented functionality to it.

6. Define specializations of the abstraction class if desired.

Rules of thumb

• Adapter makes things work after they’re designed; Bridge makes them work before they are.

• Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.

• State, Strategy, Bridge (and to some degree Adapter) have similar solution structures. They all share elements of the “handle/body” idiom. They differ in intent - that is, they solve different problems.

• The structure of State and Bridge are identical (except that Bridge admits hierarchies of envelope classes, whereas State allows only one). The two patterns use the same structure to solve different problems: State allows an object’s behavior to change along with its state, while Bridge’s intent is to decouple an abstraction from its implementation so that the two can vary independently.

• If interface classes delegate the creation of their implementation classes (instead of creating/coupling themselves directly), then the design usually uses the Abstract Factory pattern to create the implementation objects.

Bridge in C++

Bridge design pattern demo

Discussion. The motivation is to decouple the Time interface from the Time implementation, while still allowing the abstraction and the realization to each be modelled with their own inheritance hierarchy. The implementation classes below are straight-forward. The interface classes are a little more subtle. Routinely, a Bridge pattern interface hierarchy “hasa” implementation class. Here the interface base class “hasa” a pointer to the implementation base class, and each class in the interface hierarchy is responsible for populating the base class pointer with the correct concrete implementation class. Then all requests from the client are simply delegated by the interface class to the encapsulated implementation class.

#include <iostream.h>#include <iomanip.h>#include <string.h>

class TimeImp {  public:    TimeImp(int hr, int min) {        hr_ = hr;        min_ = min;    }    virtual void tell() {        cout << "time is " << setw(2) << setfill(48) << hr_ << min_ << endl;    }  protected:    int hr_, min_;};

Page 76: Design Patterns

Structural patterns 76 of 205

class CivilianTimeImp: public TimeImp {  public:    CivilianTimeImp(int hr, int min, int pm): TimeImp(hr, min) {        if (pm)          strcpy(whichM_, " PM");        else          strcpy(whichM_, " AM");    }

    /* virtual */    void tell() {        cout << "time is " << hr_ << ":" << min_ << whichM_ << endl;    }  protected:    char whichM_[4];};

class ZuluTimeImp: public TimeImp {  public:    ZuluTimeImp(int hr, int min, int zone): TimeImp(hr, min) {        if (zone == 5)          strcpy(zone_, " Eastern Standard Time");        else if (zone == 6)          strcpy(zone_, " Central Standard Time");    }

    /* virtual */    void tell() {        cout << "time is " << setw(2) << setfill(48) << hr_ << min_ << zone_ <<          endl;    }  protected:    char zone_[30];};

class Time {  public:    Time(){}    Time(int hr, int min) {        imp_ = new TimeImp(hr, min);    }    virtual void tell() {        imp_­>tell();    }  protected:    TimeImp *imp_;};

class CivilianTime: public Time {  public:    CivilianTime(int hr, int min, int pm) {        imp_ = new CivilianTimeImp(hr, min, pm);    }};

Page 77: Design Patterns

Structural patterns 77 of 205

class ZuluTime: public Time {  public:    ZuluTime(int hr, int min, int zone) {        imp_ = new ZuluTimeImp(hr, min, zone);    }};

int main() {  Time *times[3];  times[0] = new Time(14, 30);  times[1] = new CivilianTime(2, 30, 1);  times[2] = new ZuluTime(14, 30, 6);  for (int i = 0; i < 3; i++)    times[i]­>tell();}

output:

time is 1430 time is 2:30 PM time is 1430 Central Standard Time

Bridge in Java 1

class Node {    public int  value;    public Node prev, next;    public Node( int i ) { value = i; }}

class StackArray {    private int[] items = new int[12];    private int   total = ­1;    public void push( int i ) { if ( ! isFull()) items[++total] = i; }    public boolean isEmpty()  { return total == ­1; }    public boolean isFull()   { return total == 11; }    public int top() {        if (isEmpty()) return ­1;        return items[total];    }    public int pop() {        if (isEmpty()) return ­1;        return items[total­­];}   }

class StackList {    private Node last;    public void push( int i ) {        if (last == null)            last = new Node( i );        else {            last.next = new Node( i );            last.next.prev = last;            last = last.next;    }   }    public boolean isEmpty() { return last == null; }

Page 78: Design Patterns

Structural patterns 78 of 205

    public boolean isFull()  { return false; }    public int top() {        if (isEmpty()) return ­1;        return last.value;    }    public int pop() {        if (isEmpty()) return ­1;        int ret = last.value;        last = last.prev;        return ret;}   }

class StackFIFO extends StackArray {    private StackArray temp = new StackArray();    public int pop() {        while ( ! isEmpty())            temp.push( super.pop() );        int ret =  temp.pop();        while ( ! temp.isEmpty())            push( temp.pop() );        return ret;}  }

class StackHanoi extends StackArray {    private int totalRejected = 0;    public int reportRejected()   { return totalRejected; }    public void push( int in ) {        if ( ! isEmpty()  &&  in > top())            totalRejected++;        else super.push( in );}   }

class BridgeDisc {    public static void main( String[] args ) {               StackArray[]   stacks   =   {  new  StackArray(),  new  StackFIFO(),  new StackHanoi() };        StackList    stack2 = new StackList();        for (int i=1, num; i < 15; i++) {            stacks[0].push( i );            stack2.push( i );            stacks[1].push( i );        }        java.util.Random rn = new java.util.Random();        for (int i=1, num; i < 15; i++)            stacks[2].push( rn.nextInt(20) );        while ( ! stacks[0].isEmpty())            System.out.print( stacks[0].pop() + "  " );        System.out.println();        while ( ! stack2.isEmpty())            System.out.print( stack2.pop() + "  " );        System.out.println();        while ( ! stacks[1].isEmpty())            System.out.print( stacks[1].pop() + "  " );        System.out.println();        while ( ! stacks[2].isEmpty())            System.out.print( stacks[2].pop() + "  " );

Page 79: Design Patterns

Structural patterns 79 of 205

        System.out.println();        System.out.println( "total rejected is "            + ((StackHanoi)stacks[2]).reportRejected() );}   }

output:

12 11 10 9 8 7 6 5 4 3 2 1 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 0 0 1 12 16 18 total rejected is 8

Bridge in Java 2

Bridge design pattern source code example

1. Create an implementation/body base class

2. Derive the separate implementations from the common abstraction

3. Create an interface/wrapper class that “hasa” and delegates to the impl

4. Embellish the interface class with derived classes if desired

// Create an interface/wrapper class that "has a"// implementation object and delegates all requests to itclass Stack {protected StackImp imp;  public Stack( String s ) {     if (s.equals("java")) {      imp = new StackJava();    }    else {      imp = new StackMine();    }  }  public Stack() {    this( "java" );  }  public void push( int in ) {    imp.push( new Integer(in) );  }  public int pop() {    return ((Integer)imp.pop()).intValue();  }  public boolean isEmpty() {    return imp.empty();  }}

// Embellish the interface class with derived classes if desiredclass StackHanoi extends Stack {     private int totalRejected = 0;  public StackHanoi()           { super( "java" ); }  public StackHanoi( String s ) { super( s ); }

Page 80: Design Patterns

Structural patterns 80 of 205

  public int reportRejected()   { return totalRejected; }  public void push( int in ) {    if ( ! imp.empty()  &&  in > ((Integer)imp.peek()).intValue())      totalRejected++;    else      imp.push( new Integer(in) );  }}

// Create an implementation/body base classinterface StackImp {             Object push( Object o );  Object peek();  boolean empty();  Object  pop();}

class StackJava extends java.util.Stack implements StackImp { }

// Derive the separate implementations from the common abstractionclass StackMine implements StackImp {  private Object[] items = new Object[20];  private int total = ­1;

  public Object push( Object o ) {    return items[++total] = o;  }  public Object peek() {    return items[total];  }   public Object pop() {    return items[total­­];  }  public boolean empty() {    return total == ­1;  }}

class BridgeDemo {  public static void main(String[] args) {    Stack[] stacks = { new Stack("java"), new Stack("mine"),                       new StackHanoi("java"), new StackHanoi("mine") };    for (int i=0, num; i < 20; i++) {      num = (int) (Math.random() * 1000) % 40;      for (int j=0; j < stacks.length; j++) stacks[j].push( num );    }    for (int i=0, num; i < stacks.length; i++) {      while ( ! stacks[i].isEmpty()) {        System.out.print( stacks[i].pop() + "  " );      }      System.out.println();    }       System.out.println(  "total   rejected   is   "  + ((StackHanoi)stacks[3]).reportRejected() );  }}

Page 81: Design Patterns

Structural patterns 81 of 205

output:

30 3 6 10 0 14 23 39 2 5 30 20 13 31 9 4 30 11 15 36 30 3 6 10 0 14 23 39 2 5 30 20 13 31 9 4 30 11 15 36 0 2 4 11 15 36 0 2 4 11 15 36 total rejected is 14

Bridge in Java 3

Another Bridge design pattern example

1. Create an implementation/body abstraction

2. Derive the separate implementations from the common abstraction

3. Create an interface/handle class that “has a” and delegates to the impl

4. Embellish the interface class with derived classes if desired

class Node {    public int  value;    public Node prev, next;    public Node( int i ) { value = i; }}

class Stack {    private StackImpl impl;    public Stack( String s ) {        if      (s.equals("array")) impl = new StackArray();        else if (s.equals("list"))  impl = new StackList();        else System.out.println( "Stack: unknown parameter" );    }    public Stack()                { this( "array" ); }    public void    push( int in ) { impl.push( in ); }    public int     pop()          { return impl.pop(); }    public int     top()          { return impl.top(); }    public boolean isEmpty()      { return impl.isEmpty(); }    public boolean isFull()       { return impl.isFull(); }}

class StackHanoi extends Stack {    private int totalRejected = 0;    public StackHanoi()           { super( "array" ); }    public StackHanoi( String s ) { super( s ); }    public int reportRejected()   { return totalRejected; }    public void push( int in ) {        if ( ! isEmpty()  &&  in > top()) {            totalRejected++;        }        else {            super.push( in );        }    }}

Page 82: Design Patterns

Structural patterns 82 of 205

class StackFIFO extends Stack {    private StackImpl temp = new StackList();    public StackFIFO() {        super( "array" );    }    public StackFIFO( String s ) {        super( s );    }    public int pop() {        while ( ! isEmpty()) {            temp.push( super.pop() );        }        int ret =  temp.pop();        while ( ! temp.isEmpty()) {            push( temp.pop() );        }        return ret;    }}

interface StackImpl {    void    push( int i );    int     pop();    int     top();    boolean isEmpty();    boolean isFull();}

class StackArray implements StackImpl {    private int[] items = new int[12];    private int   total = ­1;    public void push( int i ) {        if ( ! isFull()) {            items[++total] = i;        }        public boolean isEmpty() {          return total == ­1;        }        public boolean isFull() {          return total == 11;        }        public int top() {            if (isEmpty()) return ­1;            return items[total];        }        public int pop() {            if (isEmpty()) return ­1;            return items[total­­];        }    }}

class StackList implements StackImpl {    private Node last;    public void push( int i ) {        if (last == null)

Page 83: Design Patterns

Structural patterns 83 of 205

            last = new Node( i );        else {            last.next = new Node( i );            last.next.prev = last;            last = last.next;        }    }    public boolean isEmpty() {        return last == null;    }    public boolean isFull() {        return false;    }    public int top() {        if (isEmpty()) return ­1;        return last.value;    }    public int pop() {        if (isEmpty()) return ­1;        int ret = last.value;        last = last.prev;        return ret;    }}

class BridgeDisc {    public static void main( String[] args ) {        Stack[] stacks = { new Stack( "array" ), new Stack( "list" ),                           new StackFIFO(), new StackHanoi() };        for (int i=1, num; i < 15; i++) {            for (int j=0; j < 3; j++) {                stacks[j].push( i );            }        }        java.util.Random rn = new java.util.Random();        for (int i=1, num; i < 15; i++) {            stacks[3].push( rn.nextInt(20) );        }        for (int i=0, num; i < stacks.length; i++) {            while ( ! stacks[i].isEmpty()) {                System.out.print( stacks[i].pop() + "  " );            }            System.out.println();        }               System.out.println("total   rejected   is   "  + ((StackHanoi)stacks[3]).reportRejected() );    }}

output:

12 11 10 9 8 7 6 5 4 3 2 1 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 0 0 1 12 16 18 total rejected is 8

Page 84: Design Patterns

Structural patterns 84 of 205

Composite Design Pattern

Intent

• Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

• Recursive composition

• “Directories contain entries, each of which could be a directory.”

• 1-to-many “has a” up the “is a” hierarchy

Problem

Application needs to manipulate a hierarchical collection of “primitive” and “composite” objects. Processing of a primitive object is handled one way, and processing of a composite object is handled differently. Having to query the “type” of each object before attempting to process it is not desirable.

Discussion

Define an abstract base class (Component) that specifies the behavior that needs to be exercised uniformly across all primitive and composite objects. Subclass the Primitive and Composite classes off of the Component class. Each Composite object “couples” itself only to the abstract type Component as it manages its “children”.

Use this pattern whenever you have “composites that contain components, each of which could be a composite”.

Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Primitives and Composites uniformly requires that these methods be moved to the abstract Component class. See the “Opinions” section below for a discussion of “safety” versus “transparency” issues.

Structure

Composites that contain Components, each of which could be a Composite.

Menus that contain menu items, each of which could be a menu.

Row-column GUI layout managers that contain widgets, each of which could be a row-column

Page 85: Design Patterns

Structural patterns 85 of 205

GUI layout manager.

Directories that contain files, each of which could be a directory.

Containers that contain Elements, each of which could be a Container.

Example

The Composite composes objects into tree structures and lets clients treat individual objects and compositions uniformly. Although the example is abstract, arithmetic expressions are Composites. An arithmetic expression consists of an operand, an operator (+ - * /), and another operand. The operand can be a number, or another arithmetic expresssion. Thus, 2 + 3 and (2 + 3) + (4 * 6) are both valid expressions.

Check list

1. Ensure that your problem is about representing “whole-part” hierarchical relationships.

2. Consider the heuristic, “Containers that contain containees, each of which could be a container.” For example, “Assemblies that contain components, each of which could be an assembly.” Divide your domain concepts into container classes, and containee classes.

3. Create a “lowest common denominator” interface that makes your containers and containees interchangeable. It should specify the behavior that needs to be exercised uniformly across all containee and container objects.

4. All container and containee classes declare an “is a” relationship to the interface.

5. All container classes declare a one-to-many “has a” relationship to the interface.

6. Container classes leverage polymorphism to delegate to their containee objects.

7. Child management methods [e.g. addChild(), removeChild()] should normally be defined in the Composite class. Unfortunately, the desire to treat Leaf and Composite objects uniformly may require that these methods be promoted to the abstract Component class. See the Gang of Four for a discussion of these “safety” versus “transparency” trade-offs.

Rules of thumb

• Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.

Page 86: Design Patterns

Structural patterns 86 of 205

• Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.

• Composite can let you compose a Mediator out of smaller pieces through recursive composition.

• Decorator is designed to let you add responsibilities to objects without subclassing. Composite’s focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.

• Flyweight is often combined with Composite to implement shared leaf nodes.

Opinions

The whole point of the Composite pattern is that the Composite can be treated atomically, just like a leaf. If you want to provide an Iterator protocol, fine, but I think that is outside the pattern itself. At the heart of this pattern is the ability for a client to perform operations on an object without needing to know that there are many objects inside.

Being able to treat a heterogeneous collection of objects atomically (or transparently) requires that the “child management” interface be defined at the root of the Composite class hierarchy (the abstract Component class). However, this choice costs you safety, because clients may try to do meaningless things like add and remove objects from leaf objects. On the other hand, if you “design for safety”, the child management interface is declared in the Composite class, and you lose transparency because leaves and Composites now have different interfaces.

Smalltalk implementations of the Composite pattern usually do not have the interface for managing the components in the Component interface, but in the Composite interface. C++ implementations tend to put it in the Component interface. This is an extremely interesting fact, and one that I often ponder. I can offer theories to explain it, but nobody knows for sure why it is true.

My Component classes do not know that Composites exist. They provide no help for navigating Composites, nor any help for altering the contents of a Composite. This is because I would like the base class (and all its derivatives) to be reusable in contexts that do not require Composites. When given a base class pointer, if I absolutely need to know whether or not it is a Composite, I will use dynamic_cast to figure this out. In those cases where dynamic_cast is too expensive, I will use a Visitor.

Common complaint: “if I push the Composite interface down into the Composite class, how am I going to enumerate (i.e. traverse) a complex structure?” My answer is that when I have behaviors which apply to hierarchies like the one presented in the Composite pattern, I typically use Visitor, so enumeration isn’t a problem - the Visitor knows in each case, exactly what kind of object it’s dealing with. The Visitor doesn’t need every object to provide an enumeration interface.

Composite doesn’t force you to treat all Components as Composites. It merely tells you to put all operations that you want to treat “uniformly” in the Component class. If add, remove, and similar operations cannot, or must not, be treated uniformly, then do not put them in the Component base class. Remember, by the way, that each pattern’s structure diagram doesn’t define the pattern; it merely depicts what in our experience is a common realization thereof. Just because Composite’s structure diagram shows child management operations in the Component base class doesn’t mean all implementations of the pattern must do the same.

Composite in C++ 1

Page 87: Design Patterns

Structural patterns 87 of 205

Composite design pattern

1. Identify the scalar/primitive classes and vector/container classes

2. Create an “interface” (lowest common denominator) that can make all concrete classes “interchangeable”

3. All concrete classes declare an “is a” relationship to the interface

4. All “container” classes couple themselves to the interface (recursive composition, Composite “has a” set of children up the “is a” hierarchy)

5. “Container” classes use polymorphism as they delegate to their children

#include <iostream>#include <vector>using namespace std;

// 2. Create an "interface" (lowest common denominator)class Component{  public:    virtual void traverse() = 0;};

class Leaf: public Component{    // 1. Scalar class   3. "isa" relationship    int value;  public:    Leaf(int val)    {        value = val;    }    void traverse()    {        cout << value << ' ';    }};

class Composite: public Component{    // 1. Vector class   3. "isa" relationship    vector < Component * > children; // 4. "container" coupled to the interface  public:    // 4. "container" class coupled to the interface    void add(Component *ele)    {        children.push_back(ele);    }    void traverse()    {        for (int i = 0; i < children.size(); i++)        // 5. Use polymorphism to delegate to children          children[i]­>traverse();    }};

int main()

Page 88: Design Patterns

Structural patterns 88 of 205

{  Composite containers[4];

  for (int i = 0; i < 4; i++)    for (int j = 0; j < 3; j++)      containers[i].add(new Leaf(i *3+j));

  for (i = 1; i < 4; i++)    containers[0].add(&(containers[i]));

  for (i = 0; i < 4; i++)  {    containers[i].traverse();    cout << endl;  }}

output:

0 1 2 3 4 5 6 7 8 9 10 11 3 4 5 6 7 8 9 10 11

Composite in C++ 2

Composite design pattern - multiple container classes

#include <iostream>#include <vector>using namespace std;

class Component{  public:    virtual void traverse() = 0;};

class Primitive: public Component{    int value;  public:    Primitive(int val)    {        value = val;    }    void traverse()    {        cout << value << "  ";    }};

class Composite: public Component{    vector < Component * > children;

Page 89: Design Patterns

Structural patterns 89 of 205

    int value;  public:    Composite(int val)    {        value = val;    }    void add(Component *c)    {        children.push_back(c);    }    void traverse()    {        cout << value << "  ";        for (int i = 0; i < children.size(); i++)          children[i]­>traverse();    }};

class Row: public Composite{  public:    // Two different kinds of "con­    Row(int val): Composite(val){}    // tainer" classes.  Most of the    void traverse()    {        // "meat" is in the Composite        cout << "Row"; // base class.        Composite::traverse();    }};

class Column: public Composite{  public:    Column(int val): Composite(val){}    void traverse()    {        cout << "Col";        Composite::traverse();    }};

int main(){  Row first(1);                 // Row1  Column second(2);             //   |  Column third(3);              //   +­­ Col2  Row fourth(4);                //   |     |  Row fifth(5);                 //   |     +­­ 7  first.add(&second);           //   +­­ Col3  first.add(&third);            //   |     |  third.add(&fourth);           //   |     +­­ Row4  third.add(&fifth);            //   |     |     |  first.add(&Primitive(6));     //   |     |     +­­ 9  second.add(&Primitive(7));    //   |     +­­ Row5

Page 90: Design Patterns

Structural patterns 90 of 205

  third.add(&Primitive(8));     //   |     |     |  fourth.add(&Primitive(9));    //   |     |     +­­ 10  fifth.add(&Primitive(10));    //   |     +­­ 8  first.traverse();             //   +­­ 6  cout << '\n';                 }

output:

Row1 Col2 7 Col3 Row4 9 Row5 10 8 6

Composite in Java: Before and after

Before

class File{    public File(String name)    {        m_name = name;    }    public void ls()    {        System.out.println(Composite.g_indent + m_name);    }    private String m_name;}

class Directory{    public Directory(String name)    {        m_name = name;    }    public void add(Object obj)    {        m_files.add(obj);    }    public void ls()    {        System.out.println(Composite.g_indent + m_name);        Composite.g_indent.append("   ");        for (int i = 0; i < m_files.size(); ++i)        {            Object obj = m_files.get(i);            // Recover the type of this object            if (obj.getClass().getName().equals("Directory"))              ((Directory)obj).ls();            else              ((File)obj).ls();        }        Composite.g_indent.setLength(CompositeDemo.g_indent.length() ­ 3);    }    private String m_name;    private ArrayList m_files = new ArrayList();

Page 91: Design Patterns

Structural patterns 91 of 205

}

publicclass CompositeDemo{    public static StringBuffer g_indent = new StringBuffer();

    public static void main(String[] args)    {        Directory one = new Directory("dir111"), two = new Directory("dir222"),          thr = new Directory("dir333");        File a = new File("a"), b = new File("b"), c = new File("c"), d = new          File("d"), e = new File("e");        one.add(a);        one.add(two);        one.add(b);        two.add(c);        two.add(d);        two.add(thr);        thr.add(e);        one.ls();    }}

output:

dir111    a    dir222        c        d        dir333            e    b

After

// Define a "lowest common denominator"interface AbstractFile{  public void ls();}

// File implements the "lowest common denominator"class File implements AbstractFile{    public File(String name)    {        m_name = name;    }    public void ls()    {        System.out.println(CompositeDemo.g_indent + m_name);    }    private String m_name;}

Page 92: Design Patterns

Structural patterns 92 of 205

// Directory implements the "lowest common denominator"class Directory implements AbstractFile{    public Directory(String name)    {        m_name = name;    }    public void add(Object obj)    {        m_files.add(obj);    }    public void ls()    {        System.out.println(CompositeDemo.g_indent + m_name);        CompositeDemo.g_indent.append("   ");        for (int i = 0; i < m_files.size(); ++i)        {            // Leverage the "lowest common denominator"            AbstractFile obj = (AbstractFile)m_files.get(i);            obj.ls();        }        CompositeDemo.g_indent.setLength(CompositeDemo.g_indent.length() ­ 3);    }    private String m_name;    private ArrayList m_files = new ArrayList();}

publicclass CompositeDemo{    public static StringBuffer g_indent = new StringBuffer();

    public static void main(String[] args)    {        Directory one = new Directory("dir111"), two = new Directory("dir222"),          thr = new Directory("dir333");        File a = new File("a"), b = new File("b"), c = new File("c"), d = new          File("d"), e = new File("e");        one.add(a);        one.add(two);        one.add(b);        two.add(c);        two.add(d);        two.add(thr);        thr.add(e);        one.ls();    }}

Composite in Java: User-configurable "views" of a Composite

A second static attribute is used to remember the “current level” of the traversal.

import java.util.List;import java.util.ArrayList;

Page 93: Design Patterns

Structural patterns 93 of 205

abstract class Entity {    protected static StringBuffer indent = new StringBuffer();    protected static int level = 1;    public abstract void traverse( int[] levels );    protected boolean printThisLevel( int[] levels ) {        for (int i=0; i < levels.length; i++)            if (level == levels[i])                return true;        return false;}   }

class Product extends Entity {    private int value;    public Product( int val ) { value = val; }    public void traverse( int[] levels ) {        if (printThisLevel( levels ))            System.out.println( indent.toString() + value );}   }

class Box extends Entity {    private List children = new ArrayList();    private int  value;    public Box( int val )       { value = val; }    public void add( Entity c ) { children.add( c ); }    public void traverse( int[] levels ) {        if (printThisLevel( levels )) {            System.out.println( indent.toString() + value );            indent.append( "   " );        }        level++;        for (int i=0; i < children.size(); i++)            ((Entity)children.get(i)).traverse( levels );        level­­;        if (printThisLevel( levels ))            indent.setLength( indent.length() ­ 3 );}   }

public class CompositeLevelsAns {    public static void main( String[] args ) {        Box root = initialize();        int[] levels = new int[args.length];        for (int i=0; i < args.length; i++)            levels[i] = Integer.parseInt( args[i] );        root.traverse( levels );    }

    private static Box initialize() {        Box[] nodes = new Box[7];        nodes[1] = new Box( 1 );        int[] s = { 1, 4, 7 };        for (int i=0; i < 3; i++) {            nodes[2] = new Box( 21+i );            nodes[1].add( nodes[2] );            int lev = 3;            for (int j=0; j < 4; j++) {                nodes[lev­1].add( new Product( lev*10 + s[i] ) );

Page 94: Design Patterns

Structural patterns 94 of 205

                nodes[lev] = new Box( lev*10 + s[i]+1 );                nodes[lev­1].add( nodes[lev] );                nodes[lev­1].add( new Product( lev*10 + s[i]+2 ) );                lev++;        }   }        return nodes[1];}   }D:\java> java CompositeLevelsAns 2 4 6 21    41    42        61        62        63    4322    44    45        64        65        66    4623    47    48        67        68        69    49D:\java> java CompositeLevelsAns 3 6 3132    61    62    63333435    64    65    66363738    67    68    6939D:\java> java CompositeLevelsAns 1 2 3 4 5 61     21        31        32            41            42                51                52                    61                    62                    63                53

Page 95: Design Patterns

Structural patterns 95 of 205

            43        33    22        34        35            44            45                54                55                    64                    65                    66                56            46        36    23        37        38            47            48                57                58                    67                    68                    69                59            49        39***************************************/For further examples follow these pages:

http://sourcemaking.com/design_patterns/composite/java/3http://sourcemaking.com/design_patterns/composite/java/2

Decorator Design Pattern

Intent

• Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

• Client-specified embellishment of a core object by recursively wrapping it.

• Wrapping a gift, putting it in a box, and wrapping the box.

Problem

You want to add behavior or state to individual objects at run-time. Inheritance is not feasible because it is static and applies to an entire class.

Discussion

Suppose you are working on a user interface toolkit and you wish to support adding borders and scroll bars to windows. You could define an inheritance hierarchy like…

Page 96: Design Patterns

Structural patterns 96 of 205

But the Decorator pattern suggests giving the client the ability to specify whatever combination of “features” is desired.

 Widget*  aWidget = new BorderDecorator(                        new HorizontalScrollBarDecorator(                          new VerticalScrollBarDecorator(                            new Window( 80, 24 )))); aWidget­>draw();

This flexibility can be achieved with the following design

Another example of cascading (or chaining) features together to produce a custom object might look like …

 Stream*  aStream = new CompressingStream(                        new ASCII7Stream(                          new FileStream( "fileName.dat" ))); aStream­>putString( "Hello world" );

The solution to this class of problems involves encapsulating the original object inside an abstract wrapper interface. Both the decorator objects and the core object inherit from this abstract interface. The interface uses recursive composition to allow an unlimited number of decorator “layers” to be added to each core object.

Note that this pattern allows responsibilities to be added to an object, not methods to an object’s interface. The interface presented to the client must remain constant as successive layers are specified.

Page 97: Design Patterns

Structural patterns 97 of 205

Also note that the core object’s identity has now been “hidden” inside of a decorator object. Trying to access the core object directly is now a problem.

Structure

The client is always interested in CoreFunctionality.doThis(). The client may, or may not, be interested in OptionalOne.doThis() and OptionalTwo.doThis(). Each of these classes always delegate to the Decorator base class, and that class always delegates to the contained “wrappee” object.

Example

The Decorator attaches additional responsibilities to an object dynamically. The ornaments that are added to pine or fir trees are examples of Decorators. Lights, garland, candy canes, glass ornaments, etc., can be added to a tree to give it a festive look. The ornaments do not change the tree itself which is recognizable as a Christmas tree regardless of particular ornaments used. As an example of additional functionality, the addition of lights allows one to “light up” a Christmas tree.

Although paintings can be hung on a wall with or without frames, frames are often added, and it is the frame which is actually hung on the wall. Prior to hanging, the paintings may be matted and framed, with the painting, matting, and frame forming a single visual component.

Page 98: Design Patterns

Structural patterns 98 of 205

Check list

1. Ensure the context is: a single core (or non-optional) component, several optional embellishments or wrappers, and an interface that is common to all.

2. Create a “Lowest Common Denominator” interface that makes all classes interchangeable.

3. Create a second level base class (Decorator) to support the optional wrapper classes.

4. The Core class and Decorator class inherit from the LCD interface.

5. The Decorator class declares a composition relationship to the LCD interface, and this data member is initialized in its constructor.

6. The Decorator class delegates to the LCD object.

7. Define a Decorator derived class for each optional embellishment.

8. Decorator derived classes implement their wrapper functionality - and - delegate to the Decorator base class.

9. The client configures the type and ordering of Core and Decorator objects.

Rules of thumb

• Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.

• Adapter changes an object’s interface, Decorator enhances an object’s responsibilities. Decorator is thus more transparent to the client. As a consequence, Decorator supports recursive composition, which isn’t possible with pure Adapters.

• Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.

• A Decorator can be viewed as a degenerate Composite with only one component. However, a Decorator adds additional responsibilities - it isn’t intended for object aggregation.

• Decorator is designed to let you add responsibilities to objects without subclassing. Composite’s focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.

Page 99: Design Patterns

Structural patterns 99 of 205

• Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition.

• Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.

• Decorator lets you change the skin of an object. Strategy lets you change the guts.

Example links:

C++ examples

http://sourcemaking.com/design_patterns/decorator/cpp/1

http://sourcemaking.com/design_patterns/decorator/cpp/2

http://sourcemaking.com/design_patterns/decorator/cpp/3

Java examples

http://sourcemaking.com/design_patterns/decorator/java/1

http://sourcemaking.com/design_patterns/decorator/java/2

http://sourcemaking.com/design_patterns/decorator/java/3

http://sourcemaking.com/design_patterns/decorator/java/4

Facade Design Pattern

Intent

• Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

• Wrap a complicated subsystem with a simpler interface.

Problem

A segment of the client community needs a simplified interface to the overall functionality of a complex subsystem.

Discussion

Facade discusses encapsulating a complex subsystem within a single interface object. This reduces the learning curve necessary to successfully leverage the subsystem. It also promotes decoupling the subsystem from its potentially many clients. On the other hand, if the Facade is the only access point for the subsystem, it will limit the features and flexibility that “power users” may need.

The Facade object should be a fairly simple advocate or facilitator. It should not become an all-knowing oracle or “god” object.

Structure

Page 100: Design Patterns

Structural patterns 100 of 205

Facade takes a “riddle wrapped in an enigma shrouded in mystery”, and interjects a wrapper that tames the amorphous and inscrutable mass of software.

SubsystemOne and SubsystemThree do not interact with the internal components of SubsystemTwo. They use the SubsystemTwoWrapper “facade” (i.e. the higher level abstraction).

Example

The Facade defines a unified, higher level interface to a subsystem that makes it easier to use. Consumers encounter a Facade when ordering from a catalog. The consumer calls one number and speaks with a customer service representative. The customer service representative acts as a Facade, providing an interface to the order fulfillment department, the billing department, and

Page 101: Design Patterns

Structural patterns 101 of 205

the shipping department.

Check list

1. Identify a simpler, unified interface for the subsystem or component.

2. Design a ‘wrapper’ class that encapsulates the subsystem.

3. The facade/wrapper captures the complexity and collaborations of the component, and delegates to the appropriate methods.

4. The client uses (is coupled to) the Facade only.

5. Consider whether additional Facades would add value.

Rules of thumb

• Facade defines a new interface, whereas Adapter uses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.

• Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.

• Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communications between colleague objects. It routinely “adds value”, and it is known/referenced by the colleague objects. In contrast, Facade defines a simpler interface to a subsystem, it doesn’t add new functionality, and it is not known by the subsystem classes.

• Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.

• Facade objects are often Singletons because only one Facade object is required.

• Adapter and Facade are both wrappers; but they are different kinds of wrappers. The intent of Facade is to produce a simpler interface, and the intent of Adapter is to design to an existing interface. While Facade routinely wraps multiple objects and Adapter wraps a single object; Facade could front-end a single complex object and Adapter could wrap several legacy objects.

Question: So the way to tell the difference between the Adapter pattern and the Facade pattern is that the Adapter wraps one class and the Facade may represent many classes?

Answer: No! Remember, the Adapter pattern changes the interface of one or more classes into one interface that a client is expecting. While most textbook examples show the adapter adapting

Page 102: Design Patterns

Structural patterns 102 of 205

one class, you may need to adapt many classes to provide the interface a client is coded to. Likewise, a Facade may provide a simplified interface to a single class with a very complex interface. The difference between the two is not in terms of how many classes they “wrap”, it is in their intent.

Facade in C++

Facade design pattern demo

Discussion. Structuring a system into subsystems helps reduce complexity. A common design goal is to minimize the communication and dependencies between subsystems.

One way to achieve this goal is to introduce a “facade” object that provides a single, simplified interface to the many, potentially complex, individual interfaces within the subsystem. In this example, the “subsystem” for responding to a networking service request has been modeled, and a facade (FacilitiesFacade) interposed. The facade “hides” the twisted and bizarre choreography necessary to satisfy even the most basic of requests. All the user of the facade object has to do is make one or two phone calls a week for 5 months, and a completed service request results.

#include <iostream.h>

class MisDepartment{  public:    void submitNetworkRequest()    {        _state = 0;    }    bool checkOnStatus()    {        _state++;        if (_state == Complete)          return 1;        return 0;    }  private:    enum States    {        Received, DenyAllKnowledge, ReferClientToFacilities,          FacilitiesHasNotSentPaperwork, ElectricianIsNotDone,          ElectricianDidItWrong, DispatchTechnician, SignedOff, DoesNotWork,          FixElectriciansWiring, Complete    };    int _state;};

class ElectricianUnion{  public:    void submitNetworkRequest()    {        _state = 0;    }    bool checkOnStatus()    {        _state++;

Page 103: Design Patterns

Structural patterns 103 of 205

        if (_state == Complete)          return 1;        return 0;    }  private:    enum States    {        Received, RejectTheForm, SizeTheJob, SmokeAndJokeBreak,          WaitForAuthorization, DoTheWrongJob, BlameTheEngineer, WaitToPunchOut,          DoHalfAJob, ComplainToEngineer, GetClarification, CompleteTheJob,          TurnInThePaperwork, Complete    };    int _state;};

class FacilitiesDepartment{  public:    void submitNetworkRequest()    {        _state = 0;    }    bool checkOnStatus()    {        _state++;        if (_state == Complete)          return 1;        return 0;    }  private:    enum States    {        Received, AssignToEngineer, EngineerResearches, RequestIsNotPossible,          EngineerLeavesCompany, AssignToNewEngineer, NewEngineerResearches,          ReassignEngineer, EngineerReturns, EngineerResearchesAgain,          EngineerFillsOutPaperWork, Complete    };    int _state;};

class FacilitiesFacade{  public:    FacilitiesFacade()    {        _count = 0;    }    void submitNetworkRequest()    {        _state = 0;    }    bool checkOnStatus()    {        _count++;        /* Job request has just been received */        if (_state == Received)

Page 104: Design Patterns

Structural patterns 104 of 205

        {            _state++;            /* Forward the job request to the engineer */            _engineer.submitNetworkRequest();            cout << "submitted to Facilities ­ " << _count <<               " phone calls so far" << endl;        }        else if (_state == SubmitToEngineer)        {            /* If engineer is complete, forward to electrician */            if (_engineer.checkOnStatus())            {                _state++;                _electrician.submitNetworkRequest();                cout << "submitted to Electrician ­ " << _count <<                   " phone calls so far" << endl;            }        }        else if (_state == SubmitToElectrician)        {            /* If electrician is complete, forward to technician */            if (_electrician.checkOnStatus())            {                _state++;                _technician.submitNetworkRequest();                cout << "submitted to MIS ­ " << _count <<                   " phone calls so far" << endl;            }        }        else if (_state == SubmitToTechnician)        {            /* If technician is complete, job is done */            if (_technician.checkOnStatus())              return 1;        }        /* The job is not entirely complete */        return 0;    }    int getNumberOfCalls()

    {        return _count;    }  private:    enum States    {        Received, SubmitToEngineer, SubmitToElectrician, SubmitToTechnician    };    int _state;    int _count;    FacilitiesDepartment _engineer;    ElectricianUnion _electrician;    MisDepartment _technician;};

int main()

Page 105: Design Patterns

Structural patterns 105 of 205

{  FacilitiesFacade facilities;

  facilities.submitNetworkRequest();  /* Keep checking until job is complete */  while (!facilities.checkOnStatus())    ;  cout << "job completed after only " << facilities.getNumberOfCalls() <<     " phone calls" << endl;}

output:

submitted to Facilities ­ 1 phone calls so far submitted to Electrician ­ 12 phone calls so far submitted to MIS ­ 25 phone calls so far job completed after only 35 phone calls 

Facade in Java

Facade design pattern

1. Identify the desired unified interface for a set of subsystems

2. Design a “wrapper” class that can encapsulate the use of the subsystems

3. The client uses (is coupled to) the Facade

4. The facade/wrapper “maps” to the APIs of the subsystems

// 1. Subsystemclass PointCarte {  private double x, y;  public PointCarte( double xx, double yy ) {    x = xx;    y = yy;  }  public void  move( int dx, int dy ) {    x += dx;    y += dy;  }  public String toString() {    return "(" + x + "," + y + ")";  }  public double getX() {    return x;  }  public double getY() {    return y;  } }

// 1. Subsystemclass PointPolar {  private double radius, angle;  public PointPolar( double r, double a ) {    radius = r;

Page 106: Design Patterns

Structural patterns 106 of 205

    angle = a;  }  public void  rotate( int ang ) {    angle += ang % 360;  }  public String toString() {    return "[" + radius + "@" + angle + "]";  }}

// 1. Desired interface: move(), rotate()class Point {  private PointCarte pc; // 2. Design a "wrapper" class    public Point( double xx, double yy ) {    pc = new PointCarte( xx,yy );  }  public String toString() {    return pc.toString();  }  // 4. Wrapper maps  public void move( int dx, int dy ) {    pc.move( dx,dy );  }  public void rotate( int angle, Point o ) {    double x = pc.getX() ­ o.pc.getX();    double y = pc.getY() ­ o.pc.getY();    PointPolar pp = new PointPolar( Math.sqrt(x*x+y*y),                          Math.atan2(y,x)*180/Math.PI );    // 4. Wrapper maps    pp.rotate( angle );    System.out.println( "  PointPolar is " + pp );    String str = pp.toString();  int i = str.indexOf( '@' );    double r = Double.parseDouble( str.substring(1,i) );    double a = Double.parseDouble( str.substring(i+1,str.length()­1) );    pc = new PointCarte(r*Math.cos(a*Math.PI/180) + o.pc.getX(),                  r*Math.sin(a*Math.PI/180) + o.pc.getY() );  }}

class Line {  private Point o, e;  public Line( Point ori, Point end ) {    o = ori;    e = end;  }  public void  move( int dx, int dy ) {    o.move( dx, dy );    e.move( dx, dy );  }  public void  rotate( int angle ) {    e.rotate( angle, o );  }  public String toString() {    return "origin is " + o + ", end is " + e;  }

Page 107: Design Patterns

Structural patterns 107 of 205

}

class FacadeDemo {  public static void main( String[] args ) {    // 3. Client uses the Facade    Line line1 = new Line( new Point(2,4), new Point(5,7) );    line1.move(­2,­4);    System.out.println( "after move:  " + line1 );    line1.rotate(45);    System.out.println( "after rotate: " + line1 );    Line line2 = new Line( new Point(2,1), new Point(2.866,1.5) );    line2.rotate(30);    System.out.println( "30 degrees to 60 degrees: " + line2 );  }}

output:

after move: origin is (0.0,0.0), end is (3.0,3.0) PointPolar is [[email protected]] after rotate: origin is (0.0,0.0), end is (0.000,4.242) PointPolar   is   [[email protected]]   30   degrees   to   60   degrees:   origin   is   (2.0,1.0),   end   is (2.499,1.866) 

Flyweight Design Pattern

Intent

Use sharing to support large numbers of fine-grained objects efficiently.

The Motif GUI strategy of replacing heavy-weight widgets with light-weight gadgets.

Problem

Designing objects down to the lowest levels of system “granularity” provides optimal flexibility, but can be unacceptably expensive in terms of performance and memory usage.

Discussion

The Flyweight pattern describes how to share objects to allow their use at fine granularities without prohibitive cost. Each “flyweight” object is divided into two pieces: the state-dependent (extrinsic) part, and the state-independent (intrinsic) part. Intrinsic state is stored (shared) in the Flyweight object. Extrinsic state is stored or computed by client objects, and passed to the Flyweight when its operations are invoked.

An illustration of this approach would be Motif widgets that have been re-engineered as light-weight gadgets. Whereas widgets are “intelligent” enough to stand on their own; gadgets exist in a dependent relationship with their parent layout manager widget. Each layout manager provides context-dependent event handling, real estate management, and resource services to its flyweight gadgets, and each gadget is only responsible for context-independent state and behavior.

Structure

Flyweights are stored in a Factory’s repository. The client restrains herself from creating

Page 108: Design Patterns

Structural patterns 108 of 205

Flyweights directly, and requests them from the Factory. Each Flyweight cannot stand on its own. Any attributes that would make sharing impossible must be supplied by the client whenever a request is made of the Flyweight. If the context lends itself to “economy of scale” (i.e. the client can easily compute or look-up the necessary attributes), then the Flyweight pattern offers appropriate leverage.

The Ant, Locust, and Cockroach classes can be “light-weight” because their instance-specific state has been de-encapsulated, or externalized, and must be supplied by the client.

Example

The Flyweight uses sharing to support large numbers of objects efficiently. The public switched telephone network is an example of a Flyweight. There are several resources such as dial tone generators, ringing generators, and digit receivers that must be shared between all subscribers. A subscriber is unaware of how many resources are in the pool when he or she lifts the handset to make a call. All that matters to subscribers is that a dial tone is provided, digits are received, and the call is completed.

Page 109: Design Patterns

Structural patterns 109 of 205

Check list

1. Ensure that object overhead is an issue needing attention, and, the client of the class is able and willing to absorb responsibility realignment.

2. Divide the target class’s state into: shareable (intrinsic) state, and non-shareable (extrinsic) state.

3. Remove the non-shareable state from the class attributes, and add it the calling argument list of affected methods.

4. Create a Factory that can cache and reuse existing class instances.

5. The client must use the Factory instead of the new operator to request objects.

6. The client (or a third party) must look-up or compute the non-shareable state, and supply that state to class methods.

Rules of thumb

• Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.

• Flyweight is often combined with Composite to implement shared leaf nodes.

• Terminal symbols within Interpreter’s abstract syntax tree can be shared with Flyweight.

• Flyweight explains when and how State objects can be shared.

Flyweight in C++: Before and after

Before

Trying to use objects at very low levels of granularity is nice, but the overhead may be prohibitive. Flyweight suggests removing the non-shareable state from the class, and having the client supply it when methods are called. This places more responsibility on the client, but, considerably fewer instances of the Flyweight class are now created. Sharing of these instances is facilitated by introducing a Factory class that maintains a “cache” of existing Flyweights.

In this example, the “X” state is considered shareable (within each row anyways), and the “Y” state has been externalized (it is supplied by the client when report() is called).

class Gazillion

Page 110: Design Patterns

Structural patterns 110 of 205

{  public:    Gazillion()    {        m_value_one = s_num / Y;        m_value_two = s_num % Y;        ++s_num;    }    void report()    {        cout << m_value_one << m_value_two << ' ';    }    static int X, Y;  private:    int m_value_one;    int m_value_two;    static int s_num;};

int Gazillion::X = 6, Gazillion::Y = 10, Gazillion::s_num = 0;

int main(){  Gazillion matrix[Gazillion::X][Gazillion::Y];  for (int i = 0; i < Gazillion::X; ++i)  {    for (int j = 0; j < Gazillion::Y; ++j)      matrix[i][j].report();    cout << '\n';  }}

output:

00 01 02 03 04 05 06 07 08 0910 11 12 13 14 15 16 17 18 1920 21 22 23 24 25 26 27 28 2930 31 32 33 34 35 36 37 38 3940 41 42 43 44 45 46 47 48 4950 51 52 53 54 55 56 57 58 59

After

class Gazillion{  public:    Gazillion(int value_one)    {        m_value_one = value_one;        cout << "ctor: " << m_value_one << '\n';    }    ~Gazillion()    {        cout << m_value_one << ' ';    }    void report(int value_two)    {

Page 111: Design Patterns

Structural patterns 111 of 205

        cout << m_value_one << value_two << ' ';    }  private:    int m_value_one;};

class Factory{  public:    static Gazillion *get_fly(int in)    {        if (!s_pool[in])          s_pool[in] = new Gazillion(in);        return s_pool[in];    }    static void clean_up()    {        cout << "dtors: ";        for (int i = 0; i < X; ++i)          if (s_pool[i])            delete s_pool[i];        cout << '\n';    }    static int X, Y;  private:    static Gazillion *s_pool[];};

int Factory::X = 6, Factory::Y = 10;Gazillion *Factory::s_pool[] = {  0, 0, 0, 0, 0, 0};

int main(){  for (int i = 0; i < Factory::X; ++i)  {    for (int j = 0; j < Factory::Y; ++j)      Factory::get_fly(i)­>report(j);    cout << '\n';  }  Factory::clean_up();}

output:

ctor: 000 01 02 03 04 05 06 07 08 09ctor: 110 11 12 13 14 15 16 17 18 19ctor: 220 21 22 23 24 25 26 27 28 29ctor: 330 31 32 33 34 35 36 37 38 39ctor: 440 41 42 43 44 45 46 47 48 49

Page 112: Design Patterns

Structural patterns 112 of 205

ctor: 550 51 52 53 54 55 56 57 58 59dtors: 0 1 2 3 4 5

Flyweight in C++

Flyweight design pattern demo

Discussion. Flyweight describes how to share objects, so that their use at fine granularities is not cost prohibitive. A key concept is the distinction between “intrinsic” and “extrinsic” state. Intrinsic state consists of information that is independent of the flyweight’s context - information that is sharable (i.e. each Icon’s name, width, and height).

It is stored in the flyweight (i.e. the Icon class). Extrinsic state cannot be shared, it depends on and varies with the lyweight’s context (i.e. the x,y position that each Icon instance’s upper left corner will be drawn at). Extrinsic state is stored or computed by the client and is passed to the flyweight when an operation is invoked. Clients should not instantiate Flyweights directly, they should obtain them exclusively from a FlyweightFactory object to ensure they are shared properly.

#include <iostream.h>#include <string.h>

class Icon{  public:    Icon(char *fileName)    {        strcpy(_name, fileName);        if (!strcmp(fileName, "go"))        {            _width = 20;            _height = 20;        }        if (!strcmp(fileName, "stop"))        {            _width = 40;            _height = 40;        }        if (!strcmp(fileName, "select"))        {            _width = 60;            _height = 60;        }        if (!strcmp(fileName, "undo"))        {            _width = 30;            _height = 30;        }    }    const char *getName()    {        return _name;    }

Page 113: Design Patterns

Structural patterns 113 of 205

    draw(int x, int y)    {        cout << "   drawing " << _name << ": upper left (" << x << "," << y <<           ") ­ lower right (" << x + _width << "," << y + _height << ")" <<          endl;    }  private:    char _name[20];    int _width;    int _height;};

class FlyweightFactory{  public:    static Icon *getIcon(char *name)    {        for (int i = 0; i < _numIcons; i++)          if (!strcmp(name, _icons[i]­>getName()))            return _icons[i];        _icons[_numIcons] = new Icon(name);        return _icons[_numIcons++];    }    static void reportTheIcons()    {        cout << "Active Flyweights: ";        for (int i = 0; i < _numIcons; i++)          cout << _icons[i]­>getName() << " ";        cout << endl;    }  private:    enum    {        MAX_ICONS = 5    };    static int _numIcons;    static Icon *_icons[MAX_ICONS];};

int FlyweightFactory::_numIcons = 0;Icon *FlyweightFactory::_icons[];

class DialogBox{  public:    DialogBox(int x, int y, int incr): _iconsOriginX(x), _iconsOriginY(y),      _iconsXIncrement(incr){}    virtual void draw() = 0;  protected:    Icon *_icons[3];    int _iconsOriginX;    int _iconsOriginY;    int _iconsXIncrement;};

class FileSelection: public DialogBox

Page 114: Design Patterns

Structural patterns 114 of 205

{  public:    FileSelection(Icon *first, Icon *second, Icon *third): DialogBox(100, 100,      100)    {        _icons[0] = first;        _icons[1] = second;        _icons[2] = third;    }    void draw()    {        cout << "drawing FileSelection:" << endl;        for (int i = 0; i < 3; i++)          _icons[i]­>draw(_iconsOriginX + (i *_iconsXIncrement), _iconsOriginY);    }};

class CommitTransaction: public DialogBox{  public:    CommitTransaction(Icon *first, Icon *second, Icon *third): DialogBox(150,      150, 150)    {        _icons[0] = first;        _icons[1] = second;        _icons[2] = third;    }    void draw()    {        cout << "drawing CommitTransaction:" << endl;        for (int i = 0; i < 3; i++)          _icons[i]­>draw(_iconsOriginX + (i *_iconsXIncrement), _iconsOriginY);    }};

int main(){  DialogBox *dialogs[2];  dialogs[0] = new FileSelection(FlyweightFactory::getIcon("go"),    FlyweightFactory::getIcon("stop"), FlyweightFactory::getIcon("select"));  dialogs[1] = new CommitTransaction(FlyweightFactory::getIcon("select"),    FlyweightFactory::getIcon("stop"), FlyweightFactory::getIcon("undo"));

  for (int i = 0; i < 2; i++)    dialogs[i]­>draw();

  FlyweightFactory::reportTheIcons();}

output:drawing FileSelection:   drawing go: upper left (100,100) ­ lower right (120,120)   drawing stop: upper left (200,100) ­ lower right (240,140)   drawing select: upper left (300,100) ­ lower right (360,160)drawing CommitTransaction:   drawing select: upper left (150,150) ­ lower right (210,210)   drawing stop: upper left (300,150) ­ lower right (340,190)

Page 115: Design Patterns

Structural patterns 115 of 205

   drawing undo: upper left (450,150) ­ lower right (480,180)Active Flyweights: go stop select undo 

Flyweight in Java

Flyweight design pattern

Discussion. Trying to use objects at very low levels of granularity is nice, but the overhead may be prohibitive. Flyweight suggests removing the non-shareable state from the class, and having the client supply it when methods are called. This places more responsibility on the client, but, considerably fewer instances of the Flyweight class are now created. Sharing of these instances is facilitated by introducing a Factory class that maintains a “cache” of existing Flyweights.

class Gazillion {   private static int num = 0;   private int        row, col;   public Gazillion( int maxPerRow ) {      row = num / maxPerRow;      col = num % maxPerRow;      num++;   }   void report() {      System.out.print( " " + row + col );}  }

public class FlyweightDemo {   public static final int ROWS = 6, COLS = 10;

   public static void main( String[] args ) {      Gazillion[][] matrix = new Gazillion[ROWS][COLS];      for (int i=0; i < ROWS; i++)         for (int j=0; j < COLS; j++)            matrix[i][j] = new Gazillion( COLS );      for (int i=0; i < ROWS; i++) {         for (int j=0; j < COLS; j++)            matrix[i][j].report();         System.out.println();}  }  }

output:00 01 02 03 04 05 06 07 08 0910 11 12 13 14 15 16 17 18 1920 21 22 23 24 25 26 27 28 2930 31 32 33 34 35 36 37 38 3940 41 42 43 44 45 46 47 48 4950 51 52 53 54 55 56 57 58 59

In this refactoring, the “row” state is considered shareable (within each row anyways), and the “col” state has been externalized (it is supplied by the client when report() is called).

class Gazillion {   private int row;   public Gazillion( int theRow ) {      row = theRow;      System.out.println( "ctor: " + row );   }

Page 116: Design Patterns

Structural patterns 116 of 205

   void report( int theCol ) {      System.out.print( " " + row + theCol );}  }

class Factory {   private Gazillion[] pool;   public Factory( int maxRows ) {      pool = new Gazillion[maxRows];   }   public Gazillion getFlyweight( int theRow ) {      if (pool[theRow] == null)         pool[theRow] = new Gazillion( theRow );      return pool[theRow];}  }

public class FlyweightDemo {   public static final int ROWS = 6, COLS = 10;

   public static void main( String[] args ) {      Factory theFactory = new Factory( ROWS );      for (int i=0; i < ROWS; i++) {         for (int j=0; j < COLS; j++)            theFactory.getFlyweight( i ).report( j );         System.out.println();}  }  }

output:ctor: 0 00 01 02 03 04 05 06 07 08 09ctor: 1 10 11 12 13 14 15 16 17 18 19ctor: 2 20 21 22 23 24 25 26 27 28 29ctor: 3 30 31 32 33 34 35 36 37 38 39ctor: 4 40 41 42 43 44 45 46 47 48 49ctor: 5 50 51 52 53 54 55 56 57 58 59

Flyweight in Java 2

8 shared HandlerThreads in a ThreadPool

The ColorBox class has now become a Flyweight: the color changing and painting capability remains “intrinsic”, and the threaded behavior has been made “extrinsic”.

The ThreadPool class plays the role of the Factory. As ColorBox objects are created, they register themselves with the ThreadPool object. The latter launches 8 “handler” threads. When each thread is swapped into the CPU, it selects a random Flyweight from the ThreadPool’s cache, and asks the object to changeColor().

import java.awt.*;import java.util.Vector;

class ColorBox2 extends Canvas {   private Color  curColor = getColor();

Page 117: Design Patterns

Structural patterns 117 of 205

   private static Color[]  colors = { Color.black, Color.blue, Color.cyan,      Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.red,      Color.magenta, Color.orange, Color.pink, Color.white, Color.yellow };

   public ColorBox2( ThreadPool2 tp ) {      tp.register( this );   }   private static Color getColor() {      return colors[ (int)(Math.random() * 1000) % colors.length ];   }   public void changeColor() {      curColor = getColor();      repaint();   }   public void paint( Graphics g ) {      g.setColor( curColor );      g.fillRect( 0, 0, getWidth(), getHeight() );}  }

class ThreadPool2 {   private final int NUM_THREADS = 8;   private Vector cboxes = new Vector();   private int    pause;

   class HandlerThread extends Thread {      public void run() {         while (true) {            ((ColorBox2) cboxes.elementAt(               (int)(Math.random()*1000) % cboxes.size() )).changeColor();            try { Thread.sleep( pause ); } catch( InterruptedException e ) { }   }  }  }

   public ThreadPool2( int p ) {      pause = p;   }   public void register( ColorBox2 r ) {      cboxes.addElement( r );   }   public void start() {      for (int i=0; i < NUM_THREADS; i++) new HandlerThread().start();}  }

public class ColorBoxes2 {   public static void main( String[] args ) {      int size = 8, pause = 10;      if (args.length > 0) size  = Integer.parseInt( args[0] );      if (args.length > 1) pause = Integer.parseInt( args[1] );

      ThreadPool2 tp = new ThreadPool2( pause );

      Frame f = new FrameClose( "ColorBoxes2 ­ 8 shared HandlerThreads" );      f.setLayout( new GridLayout( size, size ) );      for (int i=0; i < size*size; i++)          f.add( new ColorBox2( tp ) );      f.setSize( 500, 400 );      f.setVisible( true );

Page 118: Design Patterns

Structural patterns 118 of 205

      tp.start();}  }

output:D:> java ColorBoxes 18 50        produces 324 boxes, 8 threads, and 50 millisecond sleep()            performance is very much improved

More examples for flyweight design pattern:

http://sourcemaking.com/design_patterns/flyweight/java/2http://sourcemaking.com/design_patterns/flyweight/java/3

Proxy Design Pattern

Intent

1. Provide a surrogate or placeholder for another object to control access to it.

2. Use an extra level of indirection to support distributed, controlled, or intelligent access.

3. Add a wrapper and delegation to protect the real component from undue complexity.

Problem

You need to support resource-hungry objects, and you do not want to instantiate such objects unless and until they are actually requested by the client.

Discussion

Design a surrogate, or proxy, object that: instantiates the real object the first time the client makes a request of the proxy, remembers the identity of this real object, and forwards the instigating request to this real object. Then all subsequent requests are simply forwarded directly to the encapsulated real object.

There are four common situations in which the Proxy pattern is applicable.

1. A virtual proxy is a placeholder for “expensive to create” objects. The real object is only created when a client first requests/accesses the object.

2. A remote proxy provides a local representative for an object that resides in a different address space. This is what the “stub” code in RPC and CORBA provides.

3. A protective proxy controls access to a sensitive master object. The “surrogate” object checks that the caller has the access permissions required prior to forwarding the request.

4. A smart proxy interposes additional actions when an object is accessed. Typical uses include:

• Counting the number of references to the real object so that it can be freed automatically when there are no more references (aka smart pointer),

• Loading a persistent object into memory when it’s first referenced,

• Checking that the real object is locked before it is accessed to ensure that no other object can change it.

Page 119: Design Patterns

Structural patterns 119 of 205

Structure

By defining a Subject interface, the presence of the Proxy object standing in place of the RealSubject is transparent to the client.

Example

The Proxy provides a surrogate or place holder to provide access to an object. A check or bank draft is a proxy for funds in an account. A check can be used in place of cash for making purchases and ultimately controls access to cash in the issuer’s account.

Check list

1. Identify the leverage or “aspect” that is best implemented as a wrapper or surrogate.

2. Define an interface that will make the proxy and the original component interchangeable.

3. Consider defining a Factory that can encapsulate the decision of whether a proxy or original object is desirable.

4. The wrapper class holds a pointer to the real class and implements the interface.

5. The pointer may be initialized at construction, or on first use.

6. Each wrapper method contributes its leverage, and delegates to the wrappee object.

Rules of thumb

• Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.

Page 120: Design Patterns

Structural patterns 120 of 205

• Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.

Proxy in C++: Before and after

Before

Direct coupling, lots of start-up and shut-down overhead.

class Image{    int m_id;    static int s_next;  public:    Image()    {        m_id = s_next++;        cout << "   $$ ctor: " << m_id << '\n';    }    ~Image()    {        cout << "   dtor: " << m_id << '\n';    }    void draw()    {        cout << "   drawing image " << m_id << '\n';    }};int Image::s_next = 1;

int main(){  Image images[5];

  for (int i; true;)  {    cout << "Exit[0], Image[1­5]: ";    cin >> i;    if (i == 0)      break;    images[i ­ 1].draw();  }}

output:   $$ ctor: 1   $$ ctor: 2   $$ ctor: 3   $$ ctor: 4   $$ ctor: 5Exit[0], Image[1­5]: 2   drawing image 2Exit[0], Image[1­5]: 4   drawing image 4Exit[0], Image[1­5]: 2   drawing image 2

Page 121: Design Patterns

Structural patterns 121 of 205

Exit[0], Image[1­5]: 0   dtor: 5   dtor: 4   dtor: 3   dtor: 2   dtor: 1

After

Initialization on first use

1. Design an “extra level of indirection” wrapper class

2. The wrapper class holds a pointer to the real class

3. The pointer is initialized to null

4. When a request comes in, the real object is created “on first use” (aka lazy intialization)

5. The request is always delegated

class RealImage{    int m_id;  public:    RealImage(int i)    {        m_id = i;        cout << "   $$ ctor: " << m_id << '\n';    }    ~RealImage()    {        cout << "   dtor: " << m_id << '\n';    }    void draw()    {        cout << "   drawing image " << m_id << '\n';    }};

// 1. Design an "extra level of indirection" wrapper classclass Image{    // 2. The wrapper class holds a pointer to the real class    RealImage *m_the_real_thing;    int m_id;    static int s_next;  public:    Image()    {        m_id = s_next++;        // 3. Initialized to null        m_the_real_thing = 0;    }    ~Image()    {        delete m_the_real_thing;    }    void draw()

Page 122: Design Patterns

Structural patterns 122 of 205

    {        // 4. When a request comes in, the real object is        //    created "on first use"        if (!m_the_real_thing)          m_the_real_thing = new RealImage(m_id);        // 5. The request is always delegated        m_the_real_thing­>draw();    }};int Image::s_next = 1;

int main(){  Image images[5];

  for (int i; true;)  {    cout << "Exit[0], Image[1­5]: ";    cin >> i;    if (i == 0)      break;    images[i ­ 1].draw();  }}

output:Exit[0], Image[1­5]: 2   $$ ctor: 2   drawing image 2Exit[0], Image[1­5]: 4   $$ ctor: 4   drawing image 4Exit[0], Image[1­5]: 2   drawing image 2Exit[0], Image[1­5]: 0   dtor: 4   dtor: 2

Proxy in C++ 1

”->” and “.” operators give different results

class Subject{  public:    virtual void execute() = 0;};

class RealSubject: public Subject{    string str;  public:    RealSubject(string s)    {        str = s;    }

Page 123: Design Patterns

Structural patterns 123 of 205

     /*virtual*/void execute()    {        cout << str << '\n';    }};

class ProxySubject: public Subject{    string first, second, third;    RealSubject *ptr;  public:    ProxySubject(string s)    {        int num = s.find_first_of(' ');        first = s.substr(0, num);        s = s.substr(num + 1);        num = s.find_first_of(' ');        second = s.substr(0, num);        s = s.substr(num + 1);        num = s.find_first_of(' ');        third = s.substr(0, num);        s = s.substr(num + 1);        ptr = new RealSubject(s);    }    ~ProxySubject()    {        delete ptr;    }    RealSubject *operator­>()    {        cout << first << ' ' << second << ' ';        return ptr;    }     /*virtual*/void execute()    {        cout << first << ' ' << third << ' ';        ptr­>execute();    }};

int main(){  ProxySubject obj(string("the quick brown fox jumped over the dog"));  obj­>execute();  obj.execute();}

output:the quick fox jumped over the dogthe   brown   fox   jumped   over   the   dog

Proxy in C++ 2

“A protection proxy controls access to the original object”

Page 124: Design Patterns

Structural patterns 124 of 205

class Person{    string nameString;    static string list[];    static int next;  public:    Person()    {        nameString = list[next++];    }    string name()    {        return nameString;    }};string Person::list[] = {  "Tom", "Dick", "Harry", "Bubba"};int Person::next = 0;

class PettyCashProtected{    int balance;  public:    PettyCashProtected()    {        balance = 500;    }    bool withdraw(int amount)    {        if (amount > balance)          return false;        balance ­= amount;        return true;    }    int getBalance()    {        return balance;    }};

class PettyCash{    PettyCashProtected realThing;  public:    bool withdraw(Person &p, int amount)    {        if (p.name() == "Tom" || p.name() == "Harry" || p.name() == "Bubba")          return realThing.withdraw(amount);        else          return false;    }    int getBalance()    {

Page 125: Design Patterns

Structural patterns 125 of 205

        return realThing.getBalance();    }};

int main(){  PettyCash pc;  Person workers[4];  for (int i = 0, amount = 100; i < 4; i++, amount += 100)    if (!pc.withdraw(workers[i], amount))      cout << "No money for " << workers[i].name() << '\n';    else      cout << amount << " dollars for " << workers[i].name() << '\n';  cout << "Remaining balance is " << pc.getBalance() << '\n';}

output:100 dollars for TomNo money for Dick300 dollars for HarryNo money for BubbaRemaining balance is 100

Proxy in Java

Proxy design pattern

1. Create a “wrapper” for a remote, or expensive, or sensitive target

2. Encapsulate the complexity/overhead of the target in the wrapper

3. The client deals with the wrapper

4. The wrapper delegates to the target

5. To support plug-compatibility of wrapper and target, create an interface

import java.io.*;  import java.net.*;

//   5.   To   support   plug­compatibility between// the wrapper and the target, create an interfaceinterface SocketInterface {  String readLine();  void  writeLine( String str );  void  dispose();}

public class ProxyDemo {  public static void main( String[] args ) {

    // 3. The client deals with the wrapper    SocketInterface socket = new SocketProxy( "127.0.0.1", 8189,

Page 126: Design Patterns

Structural patterns 126 of 205

      args[0].equals("first") ? true : false );

    String  str = null;    boolean skip = true;    while (true) {      if (args[0].equals("second")  &&  skip) {        skip = ! skip;      }      else {        str = socket.readLine();        System.out.println( "Receive ­ " + str );  // java ProxyDemo first        if (str.equals("quit")) break;             // Receive ­ 123 456      }                                            // Send ­­­­ 234 567      System.out.print( "Send ­­­­ " );            // Receive ­ 345 678      str = Read.aString();                        //      socket.writeLine( str );                     // java ProxyDemo second      if (str.equals("quit")) break;               // Send ­­­­ 123 456    }                                              // Receive ­ 234 567    socket.dispose();                              // Send ­­­­ 345 678  }}

class SocketProxy implements SocketInterface {  // 1. Create a "wrapper" for a remote,  // or expensive, or sensitive target  private Socket      socket;  private BufferedReader in;  private PrintWriter   out;

  public SocketProxy( String host, int port, boolean wait ) {    try {      if (wait) {        // 2. Encapsulate the complexity/overhead of the target in the wrapper        ServerSocket server = new ServerSocket( port );        socket = server.accept();      } else        socket = new Socket( host, port );        in  = new BufferedReader( new InputStreamReader(                                        socket.getInputStream()));        out = new PrintWriter( socket.getOutputStream(), true );      } catch( IOException e ) {        e.printStackTrace();      }  }  public String readLine() {    String str = null;    try {      str = in.readLine();    } catch( IOException e ) {      e.printStackTrace();    }    return str;  }  public void writeLine( String str ) {    // 4. The wrapper delegates to the target    out.println( str );

Page 127: Design Patterns

Structural patterns 127 of 205

  }  public void dispose() {    try {      socket.close();    } catch( IOException e ) {      e.printStackTrace();    }  }}

Page 128: Design Patterns

Behavioral patterns 128 of 205

Behavioral patterns

IntroductionIn software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.

• Chain of responsibility

◦ A way of passing a request between a chain of objects

• Command

◦ Encapsulate a command request as an object

• Interpreter

◦ A way to include language elements in a program

• Iterator

◦ Sequentially access the elements of a collection

• Mediator

◦ Defines simplified communication between classes

• Memento

◦ Capture and restore an object’s internal state

• Null Object

◦ Designed to act as a default value of an object

• Observer

◦ A way of notifying change to a number of classes

• State

◦ Alter an object’s behavior when its state changes

• Strategy

◦ Encapsulates an algorithm inside a class

• Template method

◦ Defer the exact steps of an algorithm to a subclass

• Visitor

◦ Defines a new operation to a class without change

Rules of thumb

1. Behavioral patterns are concerned with the assignment of responsibilities between objects, or, encapsulating behavior in an object and delegating requests to it.

2. Chain of responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-

Page 129: Design Patterns

Behavioral patterns 129 of 205

receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.

3. Chain of responsibility can use Command to represent requests as objects.

4. Chain of responsibility is often applied in conjunction with Composite. There, a component’s parent can act as its successor.

5. Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Memento because its interface is so narrow that a memento can only be passed as a value.

6. Command can use Memento to maintain the state required for an undo operation.

7. MacroCommands can be implemented with Composite.

8. A Command that must be copied before being placed on a history list acts as a Prototype.

9. Interpreter can use State to define parsing contexts.

10. The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable).

11. Terminal symbols within Interpreter’s abstract syntax tree can be shared with Flyweight.

12. Iterator can traverse a Composite. Visitor can apply an operation over a Composite.

13. Polymorphic Iterators rely on Factory Methods to instantiate the appropriate Iterator subclass.

14. Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing “observer” and “subject” objects, whereas a Mediator object encapsulates the communication between other objects. We’ve found it easier to make reusable Observers and Subjects than to make reusable Mediators.

15. On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.

16. Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely “adds value”, and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it doesn’t add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa).

17. Memento is often used in conjunction with Iterator. An Iterator can use a Memento to capture the state of an iteration. The Iterator stores the Memento internally.

18. State is like Strategy except in its intent.

19. Flyweight explains when and how State objects can be shared.

20. State objects are often Singletons.

21. Strategy lets you change the guts of an object. Decorator lets you change the skin.

22. Strategy is to algorithm. as Builder is to creation.

23. Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).

24. Strategy objects often make good Flyweights.

Page 130: Design Patterns

Behavioral patterns 130 of 205

25. Strategy is like Template method except in its granularity.

26. Template method uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm.

27. The Visitor pattern is like a more powerful Command pattern because the visitor may initiate whatever is appropriate for the kind of object it encounters.

Chain of Responsibility

Intent

• 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 and pass the request along the chain until an object handles it.

• Launch-and-leave requests with a single processing pipeline that contains many possible handlers.

• An object-oriented linked list with recursive traversal.

Problem

There is a potentially variable number of “handler” or “processing element” or “node” objects, and a stream of requests that must be handled. Need to efficiently process the requests without hard-wiring handler relationships and precedence, or request-to-handler mappings.

Discussion

Encapsulate the processing elements inside a “pipeline” abstraction; and have clients “launch and leave” their requests at the entrance to the pipeline.

The pattern chains the receiving objects together, and then passes any request messages from object to object until it reaches an object capable of handling the message. The number and type of handler objects isn’t known a priori, they can be configured dynamically. The chaining mechanism uses recursive composition to allow an unlimited number of handlers to be linked.

Chain of Responsibility simplifies object interconnections. Instead of senders and receivers maintaining references to all candidate receivers, each sender keeps a single reference to the head of the chain, and each receiver keeps a single reference to its immediate successor in the chain.

Make sure there exists a “safety net” to “catch” any requests which go unhandled.

Do not use Chain of Responsibility when each request is only handled by one handler, or, when the client object knows which service object should handle the request.

Structure

The derived classes know how to satisfy Client requests. If the “current” object is not available or

Page 131: Design Patterns

Behavioral patterns 131 of 205

sufficient, then it delegates to the base class, which delegates to the “next” object, and the circle of life continues.

Multiple handlers could contribute to the handling of each request. The request can be passed down the entire length of the chain, with the last link being careful not to delegate to a “null next”.

Example

The Chain of Responsibility pattern avoids coupling the sender of a request to the receiver by giving more than one object a chance to handle the request. ATM use the Chain of Responsibility in money giving mechanism.

Check list

1. The base class maintains a “next” pointer.

2. Each derived class implements its contribution for handling the request.

3. If the request needs to be “passed on”, then the derived class “calls back” to the base class, which delegates to the “next” pointer.

4. The client (or some third party) creates and links the chain (which may include a link from the last node to the root node).

5. The client “launches and leaves” each request with the root of the chain.

6. Recursive delegation produces the illusion of magic.

Rules of thumb

• Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers.

• Chain of Responsibility can use Command to represent requests as objects.

• Chain of Responsibility is often applied in conjunction with Composite. There, a component’s parent can act as its successor.

Chain of Responsibility in C++

Chain of Responsibility design pattern

Page 132: Design Patterns

Behavioral patterns 132 of 205

1. Put a “next” pointer in the base class

2. The “chain” method in the base class always delegates to the next object

3. If the derived classes cannot handle, they delegate to the base class

#include <iostream>#include <vector>#include <ctime>using namespace std;

class Base{    Base *next; // 1. "next" pointer in the base class  public:    Base()    {        next = 0;    }    void setNext(Base *n)    {        next = n;    }    void add(Base *n)    {        if (next)          next­>add(n);        else          next = n;    }    // 2. The "chain" method in the base class always delegates to the next obj    virtual void handle(int i)    {        next­>handle(i);    }};

class Handler1: public Base{  public:     /*virtual*/void handle(int i)    {        if (rand() % 3)        {            // 3. Don't handle requests 3 times out of 4            cout << "H1 passsed " << i << "  ";            Base::handle(i); // 3. Delegate to the base class        }        else          cout << "H1 handled " << i << "  ";    }};

class Handler2: public Base{  public:     /*virtual*/void handle(int i)

Page 133: Design Patterns

Behavioral patterns 133 of 205

    {        if (rand() % 3)        {            cout << "H2 passsed " << i << "  ";            Base::handle(i);        }        else          cout << "H2 handled " << i << "  ";    }};

class Handler3: public Base{  public:     /*virtual*/void handle(int i)    {        if (rand() % 3)        {            cout << "H3 passsed " << i << "  ";            Base::handle(i);        }        else          cout << "H3 handled " << i << "  ";    }};

int main(){  srand(time(0));  Handler1 root;  Handler2 two;  Handler3 thr;  root.add(&two);  root.add(&thr);  thr.setNext(&root);  for (int i = 1; i < 10; i++)  {    root.handle(i);    cout << '\n';  }}

H1 passsed 1  H2 passsed 1  H3 passsed 1  H1 passsed 1  H2 handled 1H1 handled 2H1 handled 3H1 passsed 4  H2 passsed 4  H3 handled 4H1 passsed 5  H2 handled 5H1 passsed 6  H2 passsed 6  H3 passsed 6  H1 handled 6H1 passsed 7  H2 passsed 7  H3 passsed 7  H1 passsed 7  H2 handled 7H1 handled 8H1 passsed 9  H2 passsed 9  H3 handled 9

Chain of Responsibility in C++: Chain and Composite

1. Put a “next” pointer in the base class

Page 134: Design Patterns

Behavioral patterns 134 of 205

2. The “chain” method in the base class always delegates to the next object

3. If the derived classes cannot handle, they delegate to the base class

#include <iostream>#include <vector>#include <ctime>using namespace std;

class Component{    int value;    Component *next; // 1. "next" pointer in the base class  public:    Component(int v, Component *n)    {        value = v;        next = n;    }    void setNext(Component *n)    {        next = n;    }    virtual void traverse()    {        cout << value << ' ';    }    // 2. The "chain" method in the base class always delegates to the next obj    virtual void volunteer()    {        next­>volunteer();    }};

class Primitive: public Component{  public:    Primitive(int val, Component *n = 0): Component(val, n){}     /*virtual*/void volunteer()    {        Component::traverse();        // 3. Primitive objects don't handle volunteer requests 5 times out of 6        if (rand() *100 % 6 != 0)        // 3. Delegate to the base class          Component::volunteer();    }};

class Composite: public Component{    vector < Component * > children;  public:    Composite(int val, Component *n = 0): Component(val, n){}    void add(Component *c)    {        children.push_back(c);    }

Page 135: Design Patterns

Behavioral patterns 135 of 205

     /*virtual*/void traverse()    {        Component::traverse();        for (int i = 0; i < children.size(); i++)          children[i]­>traverse();    }    // 3. Composite objects never handle volunteer requests     /*virtual*/void volunteer()    {        Component::volunteer();    }};

int main(){  srand(time(0));                 // 1  Primitive seven(7);             // |  Primitive six(6, &seven);       // +­­ 2  Composite three(3, &six);       // |   |  three.add(&six);  three.add(&seven);              // |   +­­ 4 5  Primitive five(5, &three);      // |  Primitive four(4, &five);       // +­­ 3  Composite two(2, &four);        // |   |  two.add(&four);  two.add(&five);                 // |   +­­ 6 7  Composite one(1, &two);         // |  Primitive nine(9, &one);        // +­­ 8 9  Primitive eight(8, &nine);  one.add(&two);  one.add(&three);  one.add(&eight);  one.add(&nine);  seven.setNext(&eight);  cout << "traverse: ";  one.traverse();  cout << '\n';  for (int i = 0; i < 8; i++)  {    one.volunteer();    cout << '\n';  }}

traverse: 1 2 4 5 3 6 7 8 944 5 6 74 5 6 7 8 9 4 5 6 7 8 9 444 5 64 54 54 5 6 7 8 9 4 5 6 7 8 9 4 5 6

Chain of Responsibility in Java: Before and after

Page 136: Design Patterns

Behavioral patterns 136 of 205

Before

The client is responsible for stepping through the “list” of Handler objects, and determining when the request has been handled.

class Handler{    private static java.util.Random s_rn = new java.util.Random();    private static int s_next = 1;    private int m_id = s_next++;

    public boolean handle(int num)    {        if (s_rn.nextInt(4) != 0)        {            System.out.print(m_id + "­busy  ");            return false;        }        System.out.println(m_id + "­handled­" + num);        return true;    }}

public class ChainDemo{    public static void main(String[] args)    {        Handler[] nodes =         {            new Handler(), new Handler(), new Handler(), new Handler()        };        for (int i = 1, j; i < 10; i++)        {            j = 0;            while (!nodes[j].handle(i))              j = (j + 1) % nodes.length;        }    }}

1­busy  2­busy  3­busy  4­busy  1­busy  2­handled­11­busy  2­busy  3­handled­21­busy  2­busy  3­busy  4­handled­31­busy  2­busy  3­busy  4­busy  1­busy  2­busy    3­handled­41­busy  2­busy  3­handled­51­handled­61­busy  2­handled­71­busy  2­busy  3­busy  4­busy  1­busy  2­busy    3­busy  4­handled­81­busy  2­handled­9

After

The client submits each request to the “chain” abstraction and is decoupled from all subsequent processing.

Page 137: Design Patterns

Behavioral patterns 137 of 205

class Handler{    private static java.util.Random s_rn = new java.util.Random();    private static int s_next = 1;    private int m_id = s_next++;    private Handler m_next;

    public void add(Handler next)    {        if (m_next == null)          m_next = next;        else          m_next.add(next);    }    public void wrap_around(Handler root)    {        if (m_next == null)          m_next = root;        else          m_next.wrap_around(root);    }    public void handle(int num)    {        if (s_rn.nextInt(4) != 0)        {            System.out.print(m_id + "­busy  ");            m_next.handle(num);        }        else          System.out.println(m_id + "­handled­" + num);    }}

public class ChainDemo{    public static void main(String[] args)    {        Handler chain_root = new Handler();        chain_root.add(new Handler());        chain_root.add(new Handler());        chain_root.add(new Handler());        chain_root.wrap_around(chain);        for (int i = 1; i < 10; i++)          chain_root.handle(i);    }}

1­busy  2­busy  3­handled­11­busy  2­busy  3­busy  4­busy  1­handled­21­busy  2­busy  3­busy  4­busy  1­busy  2­busy    3­busy  4­busy  1­handled­31­busy  2­handled­41­busy  2­busy  3­busy  4­handled­51­busy  2­busy  3­busy  4­busy  1­busy  2­handled­61­busy  2­handled­71­handled­81­busy  2­busy  3­handled­9

Page 138: Design Patterns

Behavioral patterns 138 of 205

Chain of Responsibility in Java

Lots of client effort to manage a list of Processors

public class ChainBefore {    interface Image {        String process();    }

    static class IR implements Image {        public String process() {            return "IR";        }    }

    static class LS implements Image {        public String process() {            return "LS";        }    }

    static class Processor {        private static java.util.Random rn = new java.util.Random();        private static int nextId = 1;        private int id = nextId++;        public boolean handle( Image img ) {            if (rn.nextInt(2) != 0) {                System.out.println( "   Processor " + id + " is busy" );                return false;            }            System.out.println( "Processor " + id + " ­ " + img.process() );            return true;        }    }

    public static void main( String[] args ) {        Image[] input = { new IR(), new IR(), new LS(), new IR(), new LS(), new LS() };        Processor[] procs = { new Processor(), new Processor(), new Processor() };        for (int i=0, j; i < input.length; i++) {            j = 0;            while ( ! procs[j].handle( input[i] ))                j = (j+1) % procs.length;        }    }}Processor 1 ­ IR   Processor 1 is busy   Processor 2 is busy   Processor 3 is busy   Processor 1 is busy   Processor 2 is busyProcessor 3 ­ IR   Processor 1 is busyProcessor 2 ­ LSProcessor 1 ­ IR

Page 139: Design Patterns

Behavioral patterns 139 of 205

Processor 1 ­ LS   Processor 1 is busy   Processor 2 is busy   Processor 3 is busyProcessor 1 ­ LS

Command 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.

• Promote “invocation of a method on an object” to full object status

• An object-oriented callback

Problem

Need to issue requests to objects without knowing anything about the operation being requested or the receiver of the request.

Discussion

Command decouples the object that invokes the operation from the one that knows how to perform it. To achieve this separation, the designer creates an abstract base class that maps a receiver (an object) with an action (a pointer to a member function). The base class contains an execute() method that simply calls the action on the receiver.

All clients of Command objects treat each object as a “black box” by simply invoking the object’s virtual execute() method whenever the client requires the object’s “service”.

A Command class holds some subset of the following: an object, a method to be applied to the object, and the arguments to be passed when the method is applied. The Command’s “execute” method then causes the pieces to come together.

Sequences of Command objects can be assembled into composite (or macro) commands.

Structure

The client that creates a command is not the same client that executes it. This separation provides flexibility in the timing and sequencing of commands. Materializing commands as objects means they can be passed, staged, shared, loaded in a table, and otherwise instrumented or manipulated like any other object.

Page 140: Design Patterns

Behavioral patterns 140 of 205

Command objects can be thought of as “tokens” that are created by one client that knows what need to be done, and passed to another client that has the resources for doing it.

Example

The Command pattern allows requests to be encapsulated as objects, thereby allowing clients to be parameterized with different requests. The “check” at a diner is an example of a Command pattern. The waiter or waitress takes an order or command from a customer and encapsulates that order by writing it on the check. The order is then queued for a short order cook. Note that the pad of “checks” used by each waiter is not dependent on the menu, and therefore they can support commands to cook many different items.

Check list

1. Define a Command interface with a method signature like execute().

2. Create one or more derived classes that encapsulate some subset of the following: a “receiver” object, the method to invoke, the arguments to pass.

3. Instantiate a Command object for each deferred execution request.

4. Pass the Command object from the creator (aka sender) to the invoker (aka receiver).

Page 141: Design Patterns

Behavioral patterns 141 of 205

5. The invoker decides when to execute().

Rules of thumb

• Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Command normally specifies a sender-receiver connection with a subclass.

• Chain of Responsibility can use Command to represent requests as objects.

• Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Memento because its interface is so narrow that a memento can only be passed as a value.

• Command can use Memento to maintain the state required for an undo operation.

• MacroCommands can be implemented with Composite.

• A Command that must be copied before being placed on a history list acts as a Prototype.

• Two important aspects of the Command pattern: interface separation (the invoker is isolated from the receiver), time separation (stores a ready-to-go processing request that’s to be stated later).

Command in C++: Before and after

Before

the client has to query the “type” of each object, and manually invoke the desired method.

class Giant{  public:    enum Type    {        Fee, Phi, Pheaux    };    Giant()    {        m_id = s_next++;        m_type = (Type)(m_id % 3);    }    Type get_type()    {        return m_type;    }    void fee()    {        cout << m_id << "­fee  ";    }    void phi()    {        cout << m_id << "­phi  ";    }    void pheaux()    {        cout << m_id << "­pheaux  ";

Page 142: Design Patterns

Behavioral patterns 142 of 205

    }  private:    Type m_type;    int m_id;    static int s_next;};int Giant::s_next = 0;

template <typename T> class Queue{  public:    Queue()    {        m_add = m_remove = 0;    }    void enque(T *c)    {        m_array[m_add] = c;        m_add = (m_add + 1) % SIZE;    }    T *deque()    {        int temp = m_remove;        m_remove = (m_remove + 1) % SIZE;        return m_array[temp];    }  private:    enum    {        SIZE = 8    };    T *m_array[SIZE];    int m_add, m_remove;};

int main(){  Queue que;  Giant input[6],  *bad_guy;

  for (int i = 0; i < 6; i++)    que.enque(&input[i]);

  for (int i = 0; i < 6; i++)  {    bad_guy = que.deque();    if (bad_guy­>get_type() == Giant::Fee)      bad_guy­>fee();    else if (bad_guy­>get_type() == Giant::Phi)      bad_guy­>phi();    else if (bad_guy­>get_type() == Giant::Pheaux)      bad_guy­>pheaux();  }  cout << '\n';}

Page 143: Design Patterns

Behavioral patterns 143 of 205

0­fee  1­phi  2­pheaux  3­fee  4­phi  5­pheaux

After

the desired method is encapsulated in each Command object.

class Giant{  public:    Giant()    {        m_id = s_next++;    }    void fee()    {        cout << m_id << "­fee  ";    }    void phi()    {        cout << m_id << "­phi  ";    }    void pheaux()    {        cout << m_id << "­pheaux  ";    }  private:    int m_id;    static int s_next;};int Giant::s_next = 0;

class Command{  public:    typedef void(Giant:: *Action)();    Command(Giant *object, Action method)    {        m_object = object;        m_method = method;    }    void execute()    {        (m_object­> *m_method)();    }  private:    Giant *m_object;    Action m_method;};

template <typename T> class Queue{  public:    Queue()    {        m_add = m_remove = 0;

Page 144: Design Patterns

Behavioral patterns 144 of 205

    }    void enque(T *c)    {        m_array[m_add] = c;        m_add = (m_add + 1) % SIZE;    }    T *deque()    {        int temp = m_remove;        m_remove = (m_remove + 1) % SIZE;        return m_array[temp];    }  private:    enum    {        SIZE = 8    };    T *m_array[SIZE];    int m_add, m_remove;};

int main(){  Queue que;  Command *input[] =   {    new Command(new Giant, &Giant::fee), new Command(new Giant, &Giant::phi),      new Command(new Giant, &Giant::pheaux), new Command(new Giant, &Giant      ::fee), new Command(new Giant, &Giant::phi), new Command(new Giant,      &Giant::pheaux)  };

  for (int i = 0; i < 6; i++)    que.enque(input[i]);

  for (int i = 0; i < 6; i++)    que.deque()­>execute();  cout << '\n';}

0­fee  1­phi  2­pheaux  3­fee  4­phi  5­pheaux

Command in C++

Command design pattern

1. Create a class that encapsulates some number of the following:

• a “receiver” object

• the method to invoke

• the arguments to pass

2. Instantiate an object for each “callback”

3. Pass each object to its future “sender”

Page 145: Design Patterns

Behavioral patterns 145 of 205

4. When the sender is ready to callback to the receiver, it calls execute()

#include <iostream>  #include <string>  using namespace std;class Person;

class Command{    // 1. Create a class that encapsulates an object and a member function    // a pointer to a member function (the attribute's name is "method")    Person *object; //        void(Person:: *method)();  public:    Command(Person *obj = 0, void(Person:: *meth)() = 0)    {        object = obj; // the argument's name is "meth"        method = meth;    }    void execute()    {        (object­> *method)(); // invoke the method on the object    }};

class Person{    string name;

    // cmd is a "black box", it is a method invocation    // promoted to "full object status"    Command cmd;   public:    Person(string n, Command c): cmd(c)    {        name = n;    }    void talk()    {        // "this" is the sender, cmd has the receiver        cout << name << " is talking" << endl;        cmd.execute(); // ask the "black box" to callback the receiver    }    void passOn()    {        cout << name << " is passing on" << endl;                // 4. When the sender is ready to callback to the receiver,        // it calls execute()        cmd.execute();     }    void gossip()    {        cout << name << " is gossiping" << endl;        cmd.execute();    }    void listen()    {

Page 146: Design Patterns

Behavioral patterns 146 of 205

        cout << name << " is listening" << endl;    }};

int main(){  // Fred will "execute" Barney which will result in a call to passOn()  // Barney will "execute" Betty which will result in a call to gossip()  // Betty will "execute" Wilma which will result in a call to listen()  Person wilma("Wilma", Command());  // 2. Instantiate an object for each "callback"  // 3. Pass each object to its future "sender"  Person betty("Betty", Command(&wilma, &Person::listen));  Person barney("Barney", Command(&betty, &Person::gossip));  Person fred("Fred", Command(&barney, &Person::passOn));  fred.talk();}

Fred is talkingBarney is passing onBetty is gossipingWilma is listening

Command in C++: Simple and "macro" commands

Discussion. Encapsulate a request as an object. SimpleCommand maintains a binding between a receiver object and an action stored as a pointer to a member function. MacroCommand maintains a sequence of Commands. No explicit receiver is required because the subcommands already define their receiver. MacroCommand may contain MacroCommands.

#include <iostream>#include <vector>using namespace std;

class Number{  public:    void dubble(int &value)    {        value *= 2;    }};

class Command{  public:    virtual void execute(int &) = 0;};

class SimpleCommand: public Command{    typedef void(Number:: *Action)(int &);    Number *receiver;    Action action;  public:    SimpleCommand(Number *rec, Action act)

Page 147: Design Patterns

Behavioral patterns 147 of 205

    {        receiver = rec;        action = act;    }     /*virtual*/void execute(int &num)    {        (receiver­> *action)(num);    }};

class MacroCommand: public Command{    vector < Command * > list;  public:    void add(Command *cmd)    {        list.push_back(cmd);    }     /*virtual*/void execute(int &num)    {        for (int i = 0; i < list.size(); i++)          list[i]­>execute(num);    }};

int main(){  Number object;  Command *commands[3];  commands[0] = &SimpleCommand(&object, &Number::dubble);

  MacroCommand two;  two.add(commands[0]);  two.add(commands[0]);  commands[1] = &two;

  MacroCommand four;  four.add(&two);  four.add(&two);  commands[2] = &four;

  int num, index;  while (true)  {    cout << "Enter number selection (0=2x 1=4x 2=16x): ";    cin >> num >> index;    commands[index]­>execute(num);    cout << "   " << num << '\n';  }}

Enter number selection (0=2x 1=4x 2=16x): 3 0   6Enter number selection (0=2x 1=4x 2=16x): 3 1   12Enter number selection (0=2x 1=4x 2=16x): 3 2

Page 148: Design Patterns

Behavioral patterns 148 of 205

   48Enter number selection (0=2x 1=4x 2=16x): 4 0   8Enter number selection (0=2x 1=4x 2=16x): 4 1   16Enter number selection (0=2x 1=4x 2=16x): 4 2   64

Command in Java: Decoupling producer from consumer

import java.util.*;public class CommandQueue {

interface Command { void execute(); }

static class DomesticEngineer implements Command {   public void execute() {      System.out.println( "take out the trash" );}  }

static class Politician implements Command {   public void execute() {      System.out.println( "take money from the rich, take votes from the poor" );}  }

static class Programmer implements Command {   public void execute() {      System.out.println( "sell the bugs, charge extra for the fixes" );}  }

public static List produceRequests() {   List queue = new ArrayList();   queue.add( new DomesticEngineer() );   queue.add( new Politician() );   queue.add( new Programmer() );   return queue;}

public static void workOffRequests( List queue ) {   for (Iterator it = queue.iterator(); it.hasNext(); )      ((Command)it.next()).execute();}

public static void main( String[] args ) {   List queue = produceRequests();   workOffRequests( queue );}}

take out the trashtake money from the rich, take votes from the poorsell the bugs, charge extra for the fixed

Command in Java

Java reflection and the Command design pattern

Page 149: Design Patterns

Behavioral patterns 149 of 205

Motivation. “Sometimes it is necessary to issue requests to objects without knowing anything about the operation being requested or the receiver of the request.” The Command design pattern suggests encapsulating (“wrapping”) in an object all (or some) of the following: an object, a method name, and some arguments. Java does not support “pointers to methods”, but its reflection capability will do nicely. The “command” is a black box to the “client”. All the client does is call “execute()” on the opaque object.

import java.lang.reflect.*;

public class CommandReflect {   private int state;   public CommandReflect( int in ) {      state = in;   }   public int addOne( Integer one ) {      return state + one.intValue();   }   public int addTwo( Integer one, Integer two ) {      return state + one.intValue() + two.intValue();   }

   static public class Command {      private Object   receiver;               // the "encapsulated" object      private Method   action;                 // the "pre­registered" request      private Object[] args;                   // the "pre­registered" arg list      public Command( Object obj, String methodName, Object[] arguments ) {         receiver = obj;         args = arguments;         Class cls = obj.getClass();           // get the object's "Class"         Class[] argTypes = new Class[args.length];         for (int i=0; i < args.length; i++)   // get the "Class" for each            argTypes[i] = args[i].getClass();  //    supplied argument         // get the "Method" data structure with the correct name and signature         try {      action = cls.getMethod( methodName, argTypes );      }         catch( NoSuchMethodException e ) { System.out.println( e ); }      }      public Object execute() {         // in C++, you do something like ­­­ return receiver­>action( args );          try {     return action.invoke( receiver, args );     }         catch( IllegalAccessException e    ) { System.out.println( e ); }         catch( InvocationTargetException e ) { System.out.println( e ); }         return null;   }  }

   public static void main( String[] args ) {      CommandReflect[] objs = { new CommandReflect(1), new CommandReflect(2) };      System.out.print( "Normal call results: " );      System.out.print( objs[0].addOne( new Integer(3) ) + " " );      System.out.print( objs[1].addTwo( new Integer(4),                                        new Integer(5) ) + " " );      Command[] cmds = {         new Command( objs[0], "addOne", new Integer[] { new Integer(3) } ),         new Command( objs[1], "addTwo", new Integer[] { new Integer(4),                                                         new Integer(5) } ) };      System.out.print( "\nReflection results:  " );      for (int i=0; i < cmds.length; i++)

Page 150: Design Patterns

Behavioral patterns 150 of 205

          System.out.print( cmds[i].execute() + " " );      System.out.println();}  }

Normal call results: 4 11     // 1 + 3 = 4     // 2 + 4 + 5 = 11Reflection results:  4 11

Interpreter Design Pattern

Intent

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

Map a domain to a language, the language to a grammar, and the grammar to a hierarchical object-oriented design.

Problem

A class of problems occurs repeatedly in a well-defined and well-understood domain. If the domain were characterized with a “language”, then problems could be easily solved with an interpretation “engine”.

Discussion

The Interpreter pattern discusses: defining a domain language (i.e. problem characterization) as a simple language grammar, representing domain rules as language sentences, and interpreting these sentences to solve the problem. The pattern uses a class to represent each grammar rule. And since grammars are usually hierarchical in structure, an inheritance hierarchy of rule classes maps nicely.

An abstract base class specifies the method interpret(). Each concrete subclass implements interpret() by accepting (as an argument) the current state of the language stream, and adding its contribution to the problem solving process.

Structure

Interpreter suggests modeling the domain with a recursive grammar. Each rule in the grammar is either a ‘composite’ (a rule that references other rules) or a terminal (a leaf node in a tree structure). Interpreter relies on the recursive traversal of the Composite pattern to interpret the ‘sentences’ it is asked to process.

Page 151: Design Patterns

Behavioral patterns 151 of 205

Example

The Intepreter pattern defines a grammatical representation for a language and an interpreter to interpret the grammar. Musicians are examples of Interpreters. The pitch of a sound and its duration can be represented in musical notation on a staff. This notation provides the language of music. Musicians playing the music from the score are able to reproduce the original pitch and duration of each sound represented.

Check list

1. Decide if a “little language” offers a justifiable return on investment.

2. Define a grammar for the language.

3. Map each production in the grammar to a class.

4. Organize the suite of classes into the structure of the Composite pattern.

5. Define an interpret(Context) method in the Composite hierarchy.

6. The Context object encapsulates the current state of the input and output as the former is parsed and the latter is accumulated. It is manipulated by each grammar class as the “interpreting” process transforms the input into the output.

Rules of thumb

• Considered in its most general form (i.e. an operation distributed over a class hierarchy based on the Composite pattern), nearly every use of the Composite pattern will also contain the Interpreter pattern. But the Interpreter pattern should be reserved for those cases in which you want to think of this class hierarchy as defining a language.

• Interpreter can use State to define parsing contexts.

• The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable).

• Terminal symbols within Interpreter’s abstract syntax tree can be shared with Flyweight.

• The pattern doesn’t address parsing. When the grammar is very complex, other

Page 152: Design Patterns

Behavioral patterns 152 of 205

techniques (such as a parser) are more appropriate.

Interpreter in C++

Using Interpreter pattern with Template Method

Discussion. Uses a class hierarchy to represent the grammar given below. When a roman numeral is provided, the class hierarchy validates and interprets the string. RNInterpreter “has” 4 sub-interpreters. Each sub-interpreter receives the “context” (remaining unparsed string and cumulative parsed value) and contributes its share to the processing. Sub-interpreters simply define the Template Methods declared in the base class RNInterpreter.

romanNumeral ::= {thousands} {hundreds} {tens} {ones}thousands, hundreds, tens, ones ::= nine | four | {five} {one} {one} {one}nine ::= "CM" | "XC" | "IX"four ::= "CD" | "XL" | "IV"five ::= 'D' | 'L' | 'V'one ::= 'M' | 'C' | 'X' | 'I'

#include <iostream.h>#include <string.h>

class Thousand;class Hundred;class Ten;class One;

class RNInterpreter{  public:    RNInterpreter(); // ctor for client    RNInterpreter(int){}    // ctor for subclasses, avoids infinite loop    int interpret(char*); // interpret() for client    virtual void interpret(char *input, int &total)    {        // for internal use        int index;        index = 0;        if (!strncmp(input, nine(), 2))        {            total += 9 * multiplier();            index += 2;        }        else if (!strncmp(input, four(), 2))        {            total += 4 * multiplier();            index += 2;        }        else        {            if (input[0] == five())            {                total += 5 * multiplier();                index = 1;

Page 153: Design Patterns

Behavioral patterns 153 of 205

            }            else              index = 0;            for (int end = index + 3; index < end; index++)              if (input[index] == one())                total += 1 * multiplier();              else                break;        }        strcpy(input, &(input[index]));    } // remove leading chars processed  protected:    // cannot be pure virtual because client asks for instance    virtual char one(){}    virtual char *four(){}    virtual char five(){}    virtual char *nine(){}    virtual int multiplier(){}  private:    RNInterpreter *thousands;    RNInterpreter *hundreds;    RNInterpreter *tens;    RNInterpreter *ones;};

class Thousand: public RNInterpreter{  public:    // provide 1­arg ctor to avoid infinite loop in base class ctor    Thousand(int): RNInterpreter(1){}  protected:    char one()    {        return 'M';    }    char *four()    {        return "";    }    char five()    {        return '\0';    }    char *nine()    {        return "";    }    int multiplier()    {        return 1000;    }};

class Hundred: public RNInterpreter{  public:

Page 154: Design Patterns

Behavioral patterns 154 of 205

    Hundred(int): RNInterpreter(1){}  protected:    char one()    {        return 'C';    }    char *four()    {        return "CD";    }    char five()    {        return 'D';    }    char *nine()    {        return "CM";    }    int multiplier()    {        return 100;    }};

class Ten: public RNInterpreter{  public:    Ten(int): RNInterpreter(1){}  protected:    char one()    {        return 'X';    }    char *four()    {        return "XL";    }    char five()    {        return 'L';    }    char *nine()    {        return "XC";    }    int multiplier()    {        return 10;    }};

class One: public RNInterpreter{  public:    One(int): RNInterpreter(1){}  protected:

Page 155: Design Patterns

Behavioral patterns 155 of 205

    char one()    {        return 'I';    }    char *four()    {        return "IV";    }    char five()    {        return 'V';    }    char *nine()    {        return "IX";    }    int multiplier()    {        return 1;    }};

RNInterpreter::RNInterpreter(){  // use 1­arg ctor to avoid infinite loop  thousands = new Thousand(1);  hundreds = new Hundred(1);  tens = new Ten(1);  ones = new One(1);}

int RNInterpreter::interpret(char *input){  int total;  total = 0;  thousands­>interpret(input, total);  hundreds­>interpret(input, total);  tens­>interpret(input, total);  ones­>interpret(input, total);  if (strcmp(input, ""))  // if input was invalid, return 0    return 0;  return total;}

int main(){  RNInterpreter interpreter;  char input[20];  cout << "Enter Roman Numeral: ";  while (cin >> input)  {    cout << "   interpretation is " << interpreter.interpret(input) << endl;    cout << "Enter Roman Numeral: ";  }}

Page 156: Design Patterns

Behavioral patterns 156 of 205

Enter Roman Numeral: MCMXCVI   interpretation is 1996Enter Roman Numeral: MMMCMXCIX   interpretation is 3999Enter Roman Numeral: MMMM   interpretation is 0Enter Roman Numeral: MDCLXVIIII   interpretation is 0Enter Roman Numeral: CXCX   interpretation is 0Enter Roman Numeral: MDCLXVI   interpretation is 1666Enter Roman Numeral: DCCCLXXXVIII   interpretation is 888

Interpreter in Java: Before and after

Before

This is an adaptation of a design that appeared in a Pascal data structures book. The intent was to use stacks to convert normal “infix” syntax into “postfix” notation with operator precedence already handled.

public class InterpreterDemo{    public static boolean precedence(char a, char b)    {        String high = "*/", low = "+­";        if (a == '(')          return false;        if (a == ')' && b == '(')        {            System.out.println(")­(");            return false;        }        if (b == '(')          return false;        if (b == ')')          return true;        if (high.indexOf(a) >  ­ 1 && low.indexOf(b) >  ­ 1)          return true;        if (high.indexOf(a) >  ­ 1 && high.indexOf(b) >  ­ 1)          return true;        if (low.indexOf(a) >  ­ 1 && low.indexOf(b) >  ­ 1)          return true;        return false;    }    public static String convert_to_postfix(String expr)    {        Stack < Character > op_stack = new Stack < Character > ();        StringBuffer out = new StringBuffer();        String opers = "+­*/()";        char top_sym = '+';        boolean empty;        String[] tokens = expr.split(" ");

Page 157: Design Patterns

Behavioral patterns 157 of 205

        for (int i = 0; i < tokens.length; i++)        if (opers.indexOf(tokens[i].charAt(0)) ==  ­ 1)        {            out.append(tokens[i]);            out.append(' ');        }        else        {            while (!(empty = op_stack.isEmpty()) && precedence(top_sym =              op_stack.pop(), tokens[i].charAt(0)))            {                out.append(top_sym);                out.append(' ');            }            if (!empty)              op_stack.push(top_sym);            if (empty || tokens[i].charAt(0) != ')')              op_stack.push(tokens[i].charAt(0));            else              top_sym = op_stack.pop();        }        while (!op_stack.isEmpty())        {            out.append(op_stack.pop());            out.append(' ');        }        return out.toString();    }    public static double process_postfix(String postfix, HashMap < String,      Integer > map)    {        Stack < Double > stack = new Stack < Double > ();        String opers = "+­*/";        String[] tokens = postfix.split(" ");        for (int i = 0; i < tokens.length; i++)        // If token is a number or variable        if (opers.indexOf(tokens[i].charAt(0)) ==  ­ 1)        {            double term = 0.;            try            {                term = Double.parseDouble(tokens[i]);            }            catch (NumberFormatException ex)            {                term = map.get(tokens[i]);            }            stack.push(term);

            // If token is an operator        }        else        {            double b = stack.pop(), a = stack.pop();            if (tokens[i].charAt(0) == '+')              a = a + b;

Page 158: Design Patterns

Behavioral patterns 158 of 205

            else if (tokens[i].charAt(0) == '­')              a = a ­ b;            else if (tokens[i].charAt(0) == '*')              a = a * b;            else if (tokens[i].charAt(0) == '/')              a = a / b;            stack.push(a);        }        return stack.pop();    }

    public static void main(String[] args)    {        String infix = "C * 9 / 5 + 32";        String postfix = convert_to_postfix(infix);        System.out.println("Infix:   " + infix);        System.out.println("Postfix: " + postfix);        HashMap < String, Integer > map = new HashMap < String, Integer > ();        for (int i = 0; i <= 100; i += 10)        {            map.put("C", i);            System.out.println("C is " + i + ",  F is " + process_postfix              (postfix, map));        }    }}

Infix:   C * 9 / 5 + 32Postfix: C 9 * 5 / 32 +C is 0,  F is 32.0C is 10,  F is 50.0C is 20,  F is 68.0C is 30,  F is 86.0C is 40,  F is 104.0C is 50,  F is 122.0C is 60,  F is 140.0C is 70,  F is 158.0C is 80,  F is 176.0C is 90,  F is 194.0C is 100,  F is 212.0

After

This is a refactoring that follows the intent of the Interpreter design pattern. All classes in the Operand hierarchy: implement the evaluate(context), digest some piece of the context argument, and return their contribution to the recursive traversal. Applying the Interpreter pattern in this domain is probably inappropriate.

interface Operand{  double evaluate(HashMap < String, Integer > context);  void traverse(int level);}

class Expression implements Operand{    private char m_operator;

Page 159: Design Patterns

Behavioral patterns 159 of 205

    public Operand left, rite;    public Expression(char op)    {        m_operator = op;    }    public void traverse(int level)    {        left.traverse(level + 1);        System.out.print("" + level + m_operator + level + " ");        rite.traverse(level + 1);    }    public double evaluate(HashMap < String, Integer > context)    {        double result = 0.;        double a = left.evaluate(context);        double b = rite.evaluate(context);        if (m_operator == '+')          result = a + b;        else if (m_operator == '­')          result = a ­ b;        else if (m_operator == '*')          result = a * b;        else if (m_operator == '/')          result = a / b;        return result;    }}

class Variable implements Operand{    private String m_name;    public Variable(String name)    {        m_name = name;    }    public void traverse(int level)    {        System.out.print(m_name + " ");    }    public double evaluate(HashMap < String, Integer > context)    {        return context.get(m_name);    }}

class Number implements Operand{    private double m_value;    public Number(double value)    {        m_value = value;    }    public void traverse(int level)    {        System.out.print(m_value + " ");    }

Page 160: Design Patterns

Behavioral patterns 160 of 205

    public double evaluate(HashMap context)    {        return m_value;    }}

public class InterpreterDemo{    public static boolean precedence(char a, char b)    {        String high = "*/", low = "+­";        if (a == '(')          return false;        if (a == ')' && b == '(')        {            System.out.println(")­(");            return false;        }        if (b == '(')          return false;        if (b == ')')          return true;        if (high.indexOf(a) >  ­ 1 && low.indexOf(b) >  ­ 1)          return true;        if (high.indexOf(a) >  ­ 1 && high.indexOf(b) >  ­ 1)          return true;        if (low.indexOf(a) >  ­ 1 && low.indexOf(b) >  ­ 1)          return true;        return false;    }    public static String convert_to_postfix(String expr)    {        Stack < Character > op_stack = new Stack < Character > ();        StringBuffer out = new StringBuffer();        String opers = "+­*/()";        char top_sym = '+';        boolean empty;        String[] tokens = expr.split(" ");

        for (int i = 0; i < tokens.length; i++)        if (opers.indexOf(tokens[i].charAt(0)) ==  ­ 1)        {            out.append(tokens[i]);            out.append(' ');        }        else        {            while (!(empty = op_stack.isEmpty()) && precedence(top_sym =              op_stack.pop(), tokens[i].charAt(0)))            {                out.append(top_sym);                out.append(' ');            }            if (!empty)              op_stack.push(top_sym);            if (empty || tokens[i].charAt(0) != ')')

Page 161: Design Patterns

Behavioral patterns 161 of 205

              op_stack.push(tokens[i].charAt(0));            else              top_sym = op_stack.pop();        }        while (!op_stack.isEmpty())        {            out.append(op_stack.pop());            out.append(' ');        }        return out.toString();    }    public static Operand build_syntax_tree(String tree)    {        Stack < Operand > stack = new Stack < Operand > ();        String opers = "+­*/";        String[] tokens = tree.split(" ");        for (int i = 0; i < tokens.length; i++)        // If token is a number or variable        if (opers.indexOf(tokens[i].charAt(0)) ==  ­ 1)        {            Operand term = null;            try            {                term = new Number(Double.parseDouble(tokens[i]));            }            catch (NumberFormatException ex)            {                term = new Variable(tokens[i]);            }            stack.push(term);

            // If token is an operator        }        else        {            Expression expr = new Expression(tokens[i].charAt(0));            expr.rite = stack.pop();            expr.left = stack.pop();            stack.push(expr);        }        return stack.pop();    }    public static void main(String[] args)    {        System.out.println("celsi * 9 / 5 + thirty");        String postfix = convert_to_postfix("celsi * 9 / 5 + thirty");        System.out.println(postfix);        Operand expr = build_syntax_tree(postfix);        expr.traverse(1);        System.out.println();        HashMap < String, Integer > map = new HashMap < String, Integer > ();        map.put("thirty", 30);        for (int i = 0; i <= 100; i += 10)        {            map.put("celsi", i);            System.out.println("C is " + i + ",  F is " + expr.evaluate(map));

Page 162: Design Patterns

Behavioral patterns 162 of 205

        }    }}

celsi * 9 / 5 + thirtycelsi 9 * 5 / thirty +celsi 3*3 9.0 2/2 5.0 1+1 thirtyC is 0,  F is 30.0C is 10,  F is 48.0C is 20,  F is 66.0C is 30,  F is 84.0C is 40,  F is 102.0C is 50,  F is 120.0C is 60,  F is 138.0C is 70,  F is 156.0C is 80,  F is 174.0C is 90,  F is 192.0C is 100,  F is 210.0

Interpreter in Java

Interpreter aside

“The pattern doesn’t address parsing.”

“When the grammer is very complex, other techniques (such as a parser) are more appropriate.”

public class InterpreterDemo {   public static boolean precedence( char a, char b ) {      String high = "*/", low = "+­";      if (a == '(') return false;     // if (a == '(' && b == ')') return false;      if (a == ')'  &&  b == '(') { System.out.println( ")­(" ); return false; }      if (b == '(') return false;      if (b == ')') return true;      if (high.indexOf( a ) > ­1  &&  low.indexOf( b )  > ­1) return true;      if (high.indexOf( a ) > ­1  &&  high.indexOf( b ) > ­1) return true;      if (low.indexOf( a ) > ­1   &&  low.indexOf( b )  > ­1) return true;      return false;   }   public static String convertToPostfix( String in ) {      StkChar      opstk  = new StkChar();      StringBuffer out    = new StringBuffer();      String       opers  = "+­*/()";      char         topsym = '+';      boolean      empty;

      for (int i = 0; i < in.length(); i++)         if (opers.indexOf( in.charAt(i) ) == ­1)            out.append( in.charAt(i) );         else {            while ( ! (empty = opstk.isEmpty())                    &&  precedence( topsym = opstk.pop(), in.charAt(i) ))               out.append( topsym );            if ( ! empty)                     opstk.push( topsym );            if (empty || in.charAt(i) != ')') opstk.push( in.charAt(i) );            else                              topsym = opstk.pop();         }

Page 163: Design Patterns

Behavioral patterns 163 of 205

      while ( ! opstk.isEmpty()) out.append( opstk.pop() );      return out.toString();   }   public static int evaluate( String in ) {      StkInt stack = new StkInt();      String opers = "+­*/";      for (int a, b, i=0; i < in.length(); i++)         if (opers.indexOf( in.charAt(i) ) == ­1)            stack.push( in.charAt(i)­48 );         else {            b = stack.pop();  a = stack.pop();            if      (in.charAt(i) == '+') a = a + b;            else if (in.charAt(i) == '­') a = a ­ b;            else if (in.charAt(i) == '*') a = a * b;            else if (in.charAt(i) == '/') a = a / b;            stack.push( a );         }      return stack.pop();   }   public static void main( String[] args ) {      System.out.print( args[0] );      String postfix = convertToPostfix( args[0] );      System.out.print( " ­­ " + postfix );      System.out.println( " ­­ " + evaluate( postfix ) );} 

class StkChar {   private char[] arr = new char[9];   private int    sp  = ­1;   void    push( char ch ) { if ( ! isFull()) arr[++sp] = ch; }   char    pop()           { if (isEmpty()) return '\0';  return arr[sp­­]; }   boolean isFull()        { return sp == arr.length­1; }   boolean isEmpty()       { return sp == ­1; }}

class StkInt {   private int[] arr = new int[9];   private int   sp  = ­1;   void    push( int ch ) { if ( ! isFull()) arr[++sp] = ch; }   int     pop()          { if (isEmpty()) return 0;  return arr[sp­­]; }   boolean isFull()       { return sp == arr.length­1; }   boolean isEmpty()      { return sp == ­1; }}}

2+3*4­5+6 ­­ 234*+5­6+ ­­ 15(2+3)*4­5+6 ­­ 23+4*5­6+ ­­ 212+3*(4­5)+6 ­­ 2345­*+6+ ­­ 52+3*((4­5)+6) ­­ 2345­6+*+ ­­ 17(3­(4*(5+6))/(7­8))*9/4 ­­ 3456+*78­/­9*4/ ­­ 105

Iterator Design Pattern

Intent

• Provide a way to access the elements of an aggregate object sequentially without exposing

Page 164: Design Patterns

Behavioral patterns 164 of 205

its underlying representation.

• The C++ and Java standard library abstraction that makes it possible to decouple collection classes and algorithms.

• Promote to “full object status” the traversal of a collection.

• Polymorphic traversal

Problem

Need to “abstract” the traversal of wildly different data structures so that algorithms can be defined that are capable of interfacing with each transparently.

Discussion

“An aggregate object such as a list should give you a way to access its elements without exposing its internal structure. Moreover, you might want to traverse the list in different ways, depending on what you need to accomplish. But you probably don’t want to bloat the List interface with operations for different traversals, even if you could anticipate the ones you’ll require. You might also need to have more than one traversal pending on the same list.” And, providing a uniform interface for traversing many types of aggregate objects (i.e. polymorphic iteration) might be valuable.

The Iterator pattern lets you do all this. The key idea is to take the responsibility for access and traversal out of the aggregate object and put it into an Iterator object that defines a standard traversal protocol.

The Iterator abstraction is fundamental to an emerging technology called “generic programming”. This strategy seeks to explicitly separate the notion of “algorithm” from that of “data structure”. The motivation is to: promote component-based development, boost productivity, and reduce configuration management.

As an example, if you wanted to support four data structures (array, binary tree, linked list, and hash table) and three algorithms (sort, find, and merge), a traditional approach would require four times three permutations to develop and maintain. Whereas, a generic programming approach would only require four plus three configuration items.

Structure

The Client uses the Collection class’ public interface directly. But access to the Collection’s elements is encapsulated behind the additional level of abstraction called Iterator. Each Collection derived class knows which Iterator derived class to create and return. After that, the Client relies on the interface defined in the Iterator base class.

Page 165: Design Patterns

Behavioral patterns 165 of 205

Example

The Iterator provides ways to access elements of an aggregate object sequentially without exposing the underlying structure of the object. Files are aggregate objects. In office settings where access to files is made through administrative or secretarial staff, the Iterator pattern is demonstrated with the secretary acting as the Iterator. Several television comedy skits have been developed around the premise of an executive trying to understand the secretary’s filing system. To the executive, the filing system is confusing and illogical, but the secretary is able to access files quickly and efficiently.

On early television sets, a dial was used to change channels. When channel surfing, the viewer was required to move the dial through each channel position, regardless of whether or not that channel had reception. On modern television sets, a next and previous button are used. When the viewer selects the “next” button, the next tuned channel will be displayed. Consider watching television in a hotel room in a strange city. When surfing through channels, the channel number is not important, but the programming is. If the programming on one channel is not of interest, the viewer can request the next channel, without knowing its number.

Check list

1. Add a create_iterator() method to the “collection” class, and grant the “iterator” class privileged access.

2. Design an “iterator” class that can encapsulate traversal of the “collection” class.

3. Clients ask the collection object to create an iterator object.

4. Clients use the first(), is_done(), next(), and current_item() protocol to access the elements of the collection class.

Rules of thumb

• The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable).

• Iterator can traverse a Composite. Visitor can apply an operation over a Composite.

• Polymorphic Iterators rely on Factory Methods to instantiate the appropriate Iterator subclass.

• Memento is often used in conjunction with Iterator. An Iterator can use a Memento to

Page 166: Design Patterns

Behavioral patterns 166 of 205

capture the state of an iteration. The Iterator stores the Memento internally.

Iterator in C++

Iterator design pattern

Take traversal-of-a-collection functionality out of the collection and promote it to “full object status”. This simplifies the collection, allows many traversals to be active simultaneously, and decouples collection algo- rithms from collection data structures.

“Every ‘container-like’ class must have an iterator.” It may seem like a violation of encapsulation for a Stack class to allow its users to access its contents directly, but John Lakos’ argument is that the designer of a class inevitably leaves something out. Later, when users need addi- tional functionality, if an iterator was originally provided, they can add functionality with “open for extension, closed for modification”. Without an iterator, their only recourse is to invasively customize production code. Below, the orginal Stack class did not include an equality operator, but it did include an iterator. As a result, the equality operator could be readily retrofitted.

1. Design an “iterator” class for the “container” class

2. Add a createIterator() member to the container class

3. Clients ask the container object to create an iterator object

4. Clients use the first(), isDone(), next(), and currentItem() protocol

#include <iostream>using namespace std;

class Stack{    int items[10];    int sp;  public:    friend class StackIter;    Stack()    {        sp =  ­ 1;    }    void push(int in)    {        items[++sp] = in;    }    int pop()    {        return items[sp­­];    }    bool isEmpty()    {        return (sp ==  ­ 1);    }    StackIter *createIterator()const; // 2. Add a createIterator() member};

class StackIter{    // 1. Design an "iterator" class    const Stack *stk;

Page 167: Design Patterns

Behavioral patterns 167 of 205

    int index;  public:    StackIter(const Stack *s)    {        stk = s;    }    void first()    {        index = 0;    }    void next()    {        index++;    }    bool isDone()    {        return index == stk­>sp + 1;    }    int currentItem()    {        return stk­>items[index];    }};

StackIter *Stack::createIterator()const{  return new StackIter(this);}

bool operator == (const Stack &l, const Stack &r){  // 3. Clients ask the container object to create an iterator object  StackIter *itl = l.createIterator();  StackIter *itr = r.createIterator();  // 4. Clients use the first(), isDone(), next(), and currentItem() protocol  for (itl­>first(), itr­>first(); !itl­>isDone(); itl­>next(), itr­>next())    if (itl­>currentItem() != itr­>currentItem())      break;  bool ans = itl­>isDone() && itr­>isDone();  delete itl;  delete itr;  return ans;}

int main(){  Stack s1;  for (int i = 1; i < 5; i++)    s1.push(i);  Stack s2(s1), s3(s1), s4(s1), s5(s1);  s3.pop();  s5.pop();  s4.push(2);  s5.push(9);  cout << "1 == 2 is " << (s1 == s2) << endl;  cout << "1 == 3 is " << (s1 == s3) << endl;

Page 168: Design Patterns

Behavioral patterns 168 of 205

  cout << "1 == 4 is " << (s1 == s4) << endl;  cout << "1 == 5 is " << (s1 == s5) << endl;}

1 == 2 is 11 == 3 is 01 == 4 is 01 == 5 is 0

Iterator in C++: Using operators instead of methods

Discussion. John Lakos suggests the GOF and STL iterator interfaces are: error-prone (possibility of misspelling method names), clumsy, and require too much typing. This design uses nothing but “intuitive” operators. Notice also that no createIterator() was specified. The user creates these iterators as local variables, and no clean-up is necessary.

#include <iostream>using namespace std;

class Stack{    int items[10];    int sp;  public:    friend class StackIter;    Stack()    {        sp =  ­ 1;    }    void push(int in)    {        items[++sp] = in;    }    int pop()    {        return items[sp­­];    }    bool isEmpty()    {        return (sp ==  ­ 1);    }};

class StackIter{    const Stack &stk;    int index;  public:    StackIter(const Stack &s): stk(s)    {        index = 0;    }    void operator++()    {        index++;    }

Page 169: Design Patterns

Behavioral patterns 169 of 205

    bool operator()()    {        return index != stk.sp + 1;    }    int operator *()    {        return stk.items[index];    }};

bool operator == (const Stack &l, const Stack &r){  StackIter itl(l), itr(r);  for (; itl(); ++itl, ++itr)    if (*itl !=  *itr)      break;  return !itl() && !itr();}

int main(){  Stack s1;  int i;  for (i = 1; i < 5; i++)    s1.push(i);  Stack s2(s1), s3(s1), s4(s1), s5(s1);  s3.pop();  s5.pop();  s4.push(2);  s5.push(9);  cout << "1 == 2 is " << (s1 == s2) << endl;  cout << "1 == 3 is " << (s1 == s3) << endl;  cout << "1 == 4 is " << (s1 == s4) << endl;  cout << "1 == 5 is " << (s1 == s5) << endl;}

1 == 2 is 11 == 3 is 01 == 4 is 01 == 5 is 0

Iterator in Java: Before and after

The class SomeClassWithData provides access to its internal data structure. Clients can accidently or maliciously trash that data structure.

class SomeClassWithData{    private TreeSet < Integer > m_data = new TreeSet < Integer > ();

    public void add(int in)    {        m_data.add(in);    }    public Collection get_data()    {

Page 170: Design Patterns

Behavioral patterns 170 of 205

        return m_data;    }}

class IteratorDemo{    public static void main(String[] args)    {        SomeClassWithData some_object = new SomeClassWithData();        for (int i = 9; i > 0; ­­i)          some_object.add(i);        Collection data = some_object.get_data();        for (java.util.Iterator it = data.iterator(); it.hasNext();)          System.out.print(it.next() + "  ");        System.out.println();

        // Do we really want a client to be able to        // trash encapsulated state?        data.clear();        data = some_object.get_data();        System.out.println("size of data is " + data.size());    }}1  2  3  4  5  6  7  8  9size of data is 0

After

Take traversal-of-a-collection functionality out of the collection and promote it to “full object status”. This simplifies the collection, allows many traversals to be active simultaneously, and decouples collection algorithms from collection data structures.

class SomeClassWithData{    private TreeSet < Integer > m_data = new TreeSet < Integer > ();

    public class Iterator    {        private SomeClassWithData m_collection;        private java.util.Iterator m_it;        private int m_current;        public Iterator(SomeClassWithData in)        {            m_collection = in;        }        public void first()        {            m_it = m_collection.m_data.iterator();            next();        }        public void next()        {            try            {                m_current = m_it.next();            }

Page 171: Design Patterns

Behavioral patterns 171 of 205

            catch (NoSuchElementException ex)            {                m_current =  ­ 999;            }        }        public boolean is_done()        {            return m_current ==  ­ 999;        }        public int current_item()        {            return m_current;        }    }

    public void add(int in)    {        m_data.add(in);    }    public Iterator create_iterator()    {        return new Iterator(this);    }}

class IteratorDemo{    public static void main(String[] args)    {        SomeClassWithData some_object = new SomeClassWithData();        for (int i = 9; i > 0; ­­i)          some_object.add(i);

        // get_data() has been removed.        // Client has to use Iterator.        SomeClassWithData.Iterator it1 = some_object.create_iterator();        SomeClassWithData.Iterator it2 = some_object.create_iterator();

        for (it1.first(); !it1.is_done(); it1.next())          System.out.print(it1.current_item() + "  ");        System.out.println();

        // Two simultaneous iterations        for (it1.first(), it2.first(); !it1.is_done(); it1.next(), it2.next())          System.out.print(it1.current_item() + " " + it2.current_item() + "  ")            ;        System.out.println();    }}

1  2  3  4  5  6  7  8  91 1  2 2  3 3  4 4  5 5  6 6  7 7  8 8  9 9

Page 172: Design Patterns

Behavioral patterns 172 of 205

Iterator in Java

Iterator design pattern

Take traversal-of-a-collection functionality out of the collection and promote it to “full object status”. This simplifies the collection, allows many traversals to be active simultaneously, and decouples collection algo- rithms from collection data structures.

1. Design an internal “iterator” class for the “collection” class

2. Add a createIterator() member to the collection class

3. Clients ask the collection object to create an iterator object

4. Clients use the first(), isDone(), next(), and currentItem() protocol

import java.util.*;

class IntSet {   private Hashtable ht = new Hashtable();

   // 1. Design an internal "iterator" class for the "collection" class   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; }   // 2. Add a createIterator() member to the collection class   public Iterator  createIterator()  { return new Iterator( this ); }}

class IteratorDemo {   public static void main( String[] args ) {      IntSet set = new IntSet();      for (int i=2; i < 10; i += 2) set.add( i );      for (int i=1; i < 9; i++)         System.out.print( i + "­" + set.isMember( i ) + "  " );

      // 3. Clients ask the collection object to create many iterator objects      IntSet.Iterator it1 = set.createIterator();      IntSet.Iterator it2 = set.createIterator();

      // 4. 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() + "  " );

Page 173: Design Patterns

Behavioral patterns 173 of 205

      // Java uses a different collection traversal "idiom" called Enumeration      System.out.print( "\nEnumeration: " );      for (Enumeration e = set.getHashtable().keys(); e.hasMoreElements(); )         System.out.print( e.nextElement() + "  " );      System.out.println();}  }

1­false  2­true  3­false  4­true  5­false  6­true  7­false  8­trueIterator:    8 8  6 6  4 4  2 2Enumeration: 8  6  4  2

Mediator Design Pattern

Intent

• 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 it lets you vary their interaction independently.

• Design an intermediary to decouple many peers.

• Promote the many-to-many relationships between interacting peers to “full object status”.

Problem

We want to design reusable components, but dependencies between the potentially reusable pieces demonstrates the “spaghetti code” phenomenon (trying to scoop a single serving results in an “all or nothing clump”).

Discussion

In Unix, permission to access system resources is managed at three levels of granularity: world, group, and owner. A group is a collection of users intended to model some functional affiliation. Each user on the system can be a member of one or more groups, and each group can have zero or more users assigned to it. Next figure shows three users that are assigned to all three groups.

Page 174: Design Patterns

Behavioral patterns 174 of 205

If we were to model this in software, we could decide to have User objects coupled to Group objects, and Group objects coupled to User objects. Then when changes occur, both classes and all their instances would be affected.

An alternate approach would be to introduce “an additional level of indirection” - take the mapping of users to groups and groups to users, and make it an abstraction unto itself. This offers several advantages: Users and Groups are decoupled from one another, many mappings can easily be maintained and manipulated simultaneously, and the mapping abstraction can be extended in the future by defining derived classes.

Partitioning a system into many objects generally enhances reusability, but proliferating interconnections between those objects tend to reduce it again. The mediator object: encapsulates all interconnections, acts as the hub of communication, is responsible for controlling and coordinating the interactions of its clients, and promotes loose coupling by keeping objects from referring to each other explicitly.

The Mediator pattern promotes a “many-to-many relationship network” to “full object status”. Modelling the inter-relationships with an object enhances encapsulation, and allows the behavior of those inter-relationships to be modified or extended through subclassing.

An example where Mediator is useful is the design of a user and group capability in an operating system. A group can have zero or more users, and, a user can be a member of zero or more groups. The Mediator pattern provides a flexible and non-invasive way to associate and manage users and groups.

Structure

Colleagues (or peers) are not coupled to one another. Each talks to the Mediator, which in turn knows and conducts the orchestration of the others. The “many to many” mapping between colleagues that would otherwise exist, has been “promoted to full object status”. This new

Page 175: Design Patterns

Behavioral patterns 175 of 205

abstraction provides a locus of indirection where additional leverage can be hosted.

Example

The Mediator defines an object that controls how a set of objects interact. Loose coupling between colleague objects is achieved by having colleagues communicate with the Mediator, rather than with each other. The control tower at a controlled airport demonstrates this pattern very well. The pilots of the planes approaching or departing the terminal area communicate with the tower rather than explicitly communicating with one another. The constraints on who can take off or land are enforced by the tower. It is important to note that the tower does not control the whole flight. It exists only to enforce constraints in the terminal area.

Check list

1. Identify a collection of interacting objects that would benefit from mutual decoupling.

2. Encapsulate those interactions in the abstraction of a new class.

3. Create an instance of that new class and rework all “peer” objects to interact with the Mediator only.

4. Balance the principle of decoupling with the principle of distributing responsibility evenly.

5. Be careful not to create a “controller” or “god” object.

Rules of thumb

Page 176: Design Patterns

Behavioral patterns 176 of 205

• Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.

• Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing “observer” and “subject” objects, whereas a Mediator object encapsulates the communication between other objects. We’ve found it easier to make reusable Observers and Subjects than to make reusable Mediators.

• On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.

• Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely “adds value”, and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it doesn’t add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa).

Mediator in C++: Before and after

Before

Node objects interact directly with each other, recursion is required, removing a Node is hard, and it is not possible to remove the first node.

class Node{  public:    Node(int v)    {        m_val = v;        m_next = 0;    }    void add_node(Node *n)    {        if (m_next)          m_next­>add_node(n);        else          m_next = n;    }    void traverse()    {        cout << m_val << "  ";        if (m_next)          m_next­>traverse();        else          cout << '\n';    }    void remove_node(int v)    {

Page 177: Design Patterns

Behavioral patterns 177 of 205

        if (m_next)          if (m_next­>m_val == v)            m_next = m_next­>m_next;          else            m_next­>remove_node(v);    }  private:    int m_val;    Node *m_next;};

int main(){  Node lst(11);  Node two(22), thr(33), fou(44);  lst.add_node(&two);  lst.add_node(&thr);  lst.add_node(&fou);  lst.traverse();  lst.remove_node(44);  lst.traverse();  lst.remove_node(22);  lst.traverse();  lst.remove_node(11);  lst.traverse();}

11  22  33  4411  22  3311  3311  33

After

A “mediating” List class focuses and simplifies all the administrative responsibilities, and the recursion (which does not scale up well) has been eliminated.

class Node{  public:    Node(int v)    {        m_val = v;    }    int get_val()    {        return m_val;    }  private:    int m_val;};

class List{  public:    void add_node(Node *n)

Page 178: Design Patterns

Behavioral patterns 178 of 205

    {        m_arr.push_back(n);    }    void traverse()    {        for (int i = 0; i < m_arr.size(); ++i)          cout << m_arr[i]­>get_val() << "  ";        cout << '\n';    }    void remove_node(int v)    {        for (vector::iterator it = m_arr.begin(); it != m_arr.end(); ++it)        if ((*it)­>get_val() == v)        {            m_arr.erase(it);            break;        }    }  private:    vector m_arr;};

int main(){  List lst;  Node one(11), two(22);  Node thr(33), fou(44);  lst.add_node(&one);  lst.add_node(&two);  lst.add_node(&thr);  lst.add_node(&fou);  lst.traverse();  lst.remove_node(44);  lst.traverse();  lst.remove_node(22);  lst.traverse();  lst.remove_node(11);  lst.traverse();}

11  22  33  4411  22  3311  3333

Mediator in C++

Mediator design pattern demo

Discussion. Though partitioning a system into many objects generally enhances reusability, proliferating interconnections tend to reduce it again. You can avoid this problem by capsulating the interconnections (i.e. the collective behavior) in a separate “mediator” object. A mediator is responsible for controlling and coordinating the interactions of a group of objects.

In this example, the dialog box object is functioning as the mediator. Child widgets of the dialog box do not know, or care, who their siblings are. Whenever a simulated user interaction occurs in

Page 179: Design Patterns

Behavioral patterns 179 of 205

a child widget Widget::changed(), the widget does nothing except “delegate” that event to its parent dialog box mediator->widgetChanged(this).

FileSelectionDialog::widgetChanged() encapsulates all collective behavior for the dialog box (it serves as the hub of communication). The user may choose to “interact” with a simulated: filter edit field, directories list, files list, or selection edit field.

#include <iostream.h>

class FileSelectionDialog;

class Widget{  public:    Widget(FileSelectionDialog *mediator, char *name)    {        _mediator = mediator;        strcpy(_name, name);    }    virtual void changed();    virtual void updateWidget() = 0;    virtual void queryWidget() = 0;  protected:    char _name[20];  private:    FileSelectionDialog *_mediator;};

class List: public Widget{  public:    List(FileSelectionDialog *dir, char *name): Widget(dir, name){}    void queryWidget()    {        cout << "   " << _name << " list queried" << endl;    }    void updateWidget()    {        cout << "   " << _name << " list updated" << endl;    }};

class Edit: public Widget{  public:    Edit(FileSelectionDialog *dir, char *name): Widget(dir, name){}    void queryWidget()    {        cout << "   " << _name << " edit queried" << endl;    }    void updateWidget()    {        cout << "   " << _name << " edit updated" << endl;    }};

class FileSelectionDialog

Page 180: Design Patterns

Behavioral patterns 180 of 205

{  public:    enum Widgets    {        FilterEdit, DirList, FileList, SelectionEdit    };    FileSelectionDialog()    {        _components[FilterEdit] = new Edit(this, "filter");        _components[DirList] = new List(this, "dir");        _components[FileList] = new List(this, "file");        _components[SelectionEdit] = new Edit(this, "selection");    }    virtual ~FileSelectionDialog();    void handleEvent(int which)    {        _components[which]­>changed();    }    virtual void widgetChanged(Widget *theChangedWidget)    {        if (theChangedWidget == _components[FilterEdit])        {            _components[FilterEdit]­>queryWidget();            _components[DirList]­>updateWidget();            _components[FileList]­>updateWidget();            _components[SelectionEdit]­>updateWidget();        }        else if (theChangedWidget == _components[DirList])        {            _components[DirList]­>queryWidget();            _components[FileList]­>updateWidget();            _components[FilterEdit]­>updateWidget();            _components[SelectionEdit]­>updateWidget();        }        else if (theChangedWidget == _components[FileList])        {            _components[FileList]­>queryWidget();            _components[SelectionEdit]­>updateWidget();        }        else if (theChangedWidget == _components[SelectionEdit])        {            _components[SelectionEdit]­>queryWidget();            cout << "   file opened" << endl;        }    }  private:    Widget *_components[4];};

FileSelectionDialog::~FileSelectionDialog(){  for (int i = 0; i < 3; i++)    delete _components[i];}

void Widget::changed()

Page 181: Design Patterns

Behavioral patterns 181 of 205

{  _mediator­>widgetChanged(this);}

int main(){  FileSelectionDialog fileDialog;  int i;

  cout << "Exit[0], Filter[1], Dir[2], File[3], Selection[4]: ";  cin >> i;

  while (i)  {    fileDialog.handleEvent(i ­ 1);    cout << "Exit[0], Filter[1], Dir[2], File[3], Selection[4]: ";    cin >> i;  }}

Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 1

   filter edit queried

   dir list updated

   file list updated

   selection edit updated

Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 2

   dir list queried

   file list updated

   filter edit updated

   selection edit updated

Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 3

   file list queried

   selection edit updated

Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 4

   selection edit queried

   file opened

Exit[0], Filter[1], Dir[2], File[3], Selection[4]: 3

   file list queried

   selection edit updated

Mediator in Java

Mediator design pattern

1. Create an “intermediary” that decouples “senders” from “receivers”

2. Producers are coupled only to the Mediator

3. Consumers are coupled only to the Mediator

Page 182: Design Patterns

Behavioral patterns 182 of 205

4. The Mediator arbitrates the storing and retrieving of messages

// 1. The "intermediary"class Mediator {  // 4. The Mediator arbitrates  private boolean slotFull = false;  private int number;  public synchronized void storeMessage( int num ) {    // no room for another message    while (slotFull == true) {      try {        wait();      }      catch (InterruptedException e ) { }    }    slotFull = true;    number = num;    notifyAll();  }  public synchronized int retrieveMessage() {    // no message to retrieve    while (slotFull == false)      try {        wait();      }      catch (InterruptedException e ) { }    slotFull = false;    notifyAll();    return number;  }}

class Producer extends Thread {  // 2. Producers are coupled only to the Mediator  private Mediator med;  private int    id;  private static int num = 1;  public Producer( Mediator m ) {    med = m;    id = num++;  }  public void run() {    int num;    while (true) {      med.storeMessage( num = (int)(Math.random()*100) );      System.out.print( "p" + id + "­" + num + "  " );    }  }}

class Consumer extends Thread {  // 3. Consumers are coupled only to the Mediator  private Mediator med;  private int    id;  private static int num = 1;  public Consumer( Mediator m ) {

Page 183: Design Patterns

Behavioral patterns 183 of 205

    med = m;    id = num++;  }  public void run() {    while (true) {      System.out.print("c" + id + "­" + med.retrieveMessage() + "  ");    }  }}

class MediatorDemo {  public static void main( String[] args ) {    Mediator mb = new Mediator();    new Producer( mb ).start();    new Producer( mb ).start();    new Consumer( mb ).start();    new Consumer( mb ).start();    new Consumer( mb ).start();    new Consumer( mb ).start();  }}

p1­87   c1­87   p2­37   c3­37   p1­28   c2­28   p2­58   c1­58   p1­18   c4­18p2­42   c3­42   p1­3   c2­3   p2­11   c3­11   p1­72   c2­72   p2­75   c3­75p1­93   c4­93   p2­52   c1­52   p1­21   c3­21   p2­80   c4­80   p1­96   c2­96

Memento Design Pattern

Intent

• Without violating encapsulation, capture and externalize an object’s internal state so that the object can be returned to this state later.

• A magic cookie that encapsulates a “check point” capability.

• Promote undo or rollback to full object status.

Problem

Need to restore an object back to its previous state (e.g. “undo” or “rollback” operations).

Discussion

The client requests a Memento from the source object when it needs to checkpoint the source object’s state. The source object initializes the Memento with a characterization of its state. The client is the “care-taker” of the Memento, but only the source object can store and retrieve information from the Memento (the Memento is “opaque” to the client and all other objects). If the client subsequently needs to “rollback” the source object’s state, it hands the Memento back to the source object for reinstatement.

An unlimited “undo” and “redo” capability can be readily implemented with a stack of Command objects and a stack of Memento objects.

The Memento design pattern defines three distinct roles:

1. Originator - the object that knows how to save itself.

Page 184: Design Patterns

Behavioral patterns 184 of 205

2. Caretaker - the object that knows why and when the Originator needs to save and restore itself.

3. Memento - the lock box that is written and read by the Originator, and shepherded by the Caretaker.

Structure

Example

The Memento captures and externalizes an object’s internal state so that the object can later be restored to that state. This pattern is common among do-it-yourself mechanics repairing drum brakes on their cars. The drums are removed from both sides, exposing both the right and left brakes. Only one side is disassembled and the other serves as a Memento of how the brake parts fit together. Only after the job has been completed on one side is the other side disassembled. When the second side is disassembled, the first side acts as the Memento.

Check list

1. Identify the roles of “caretaker” and “originator”.

2. Create a Memento class and declare the originator a friend.

Page 185: Design Patterns

Behavioral patterns 185 of 205

3. Caretaker knows when to “check point” the originator.

4. Originator creates a Memento and copies its state to that Memento.

5. Caretaker holds on to (but cannot peek into) the Memento.

6. Caretaker knows when to “roll back” the originator.

7. Originator reinstates itself using the saved state in the Memento.

Rules of thumb

• Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Memento because its interface is so narrow that a memento can only be passed as a value.

• Command can use Memento to maintain the state required for an undo operation.

• Memento is often used in conjunction with Iterator. An Iterator can use a Memento to capture the state of an iteration. The Iterator stores the Memento internally.

Memento in C++

Memento design pattern

Discussion. A memento is an object that stores a snapshot of the internal state of another object. It can be leveraged to support multi-level undo of the Command pattern. In this example, before a command is run against the Number object, Number’s current state is saved in Command’s static memento history list, and the command itself is saved in the static command history list. Undo() simply “pops” the memento history list and reinstates Number’s state from the memento. Redo() “pops” the command history list. Note that Number’s encapsulation is preserved, and Memento is wide open to Number.

#include <iostream.h>class Number;

class Memento{  public:    Memento(int val)    {        _state = val;    }  private:    friend class Number; // not essential, but p287 suggests this    int _state;};

class Number{  public:    Number(int value)    {        _value = value;

Page 186: Design Patterns

Behavioral patterns 186 of 205

    }    void dubble()    {        _value = 2 * _value;    }    void half()    {        _value = _value / 2;    }    int getValue()    {        return _value;    }    Memento *createMemento()    {        return new Memento(_value);    }    void reinstateMemento(Memento *mem)    {        _value = mem­>_state;    }  private:    int _value;};

class Command{  public:    typedef void(Number:: *Action)();    Command(Number *receiver, Action action)    {        _receiver = receiver;        _action = action;    }    virtual void execute()    {        _mementoList[_numCommands] = _receiver­>createMemento();        _commandList[_numCommands] = this;        if (_numCommands > _highWater)          _highWater = _numCommands;        _numCommands++;        (_receiver­> *_action)();    }    static void undo()    {        if (_numCommands == 0)        {            cout << "*** Attempt to run off the end!! ***" << endl;            return ;        }        _commandList[_numCommands ­ 1]­>_receiver­>reinstateMemento          (_mementoList[_numCommands ­ 1]);        _numCommands­­;    }    void static redo()    {

Page 187: Design Patterns

Behavioral patterns 187 of 205

        if (_numCommands > _highWater)        {            cout << "*** Attempt to run off the end!! ***" << endl;            return ;        }        (_commandList[_numCommands]­>_receiver­>*(_commandList[_numCommands]          ­>_action))();        _numCommands++;    }  protected:    Number *_receiver;    Action _action;    static Command *_commandList[20];    static Memento *_mementoList[20];    static int _numCommands;    static int _highWater;};

Command *Command::_commandList[];Memento *Command::_mementoList[];int Command::_numCommands = 0;int Command::_highWater = 0;

int main(){  int i;  cout << "Integer: ";  cin >> i;  Number *object = new Number(i);

  Command *commands[3];  commands[1] = new Command(object, &Number::dubble);  commands[2] = new Command(object, &Number::half);

  cout << "Exit[0], Double[1], Half[2], Undo[3], Redo[4]: ";  cin >> i;

  while (i)  {    if (i == 3)      Command::undo();    else if (i == 4)      Command::redo();    else      commands[i]­>execute();    cout << "   " << object­>getValue() << endl;    cout << "Exit[0], Double[1], Half[2], Undo[3], Redo[4]: ";    cin >> i;  }}

Integer: 11Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 2   5Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 1   10

Page 188: Design Patterns

Behavioral patterns 188 of 205

Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 2   5Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 3   10Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 3   5Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 3   11Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 3*** Attempt to run off the end!! ***   11Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 4   5Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 4   10Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 4   5Exit[0], Double[1], Half[2], Undo[3], Redo[4]: 4*** Attempt to run off the end!! ***   5

Memento in Java

import java.util.*;

class Memento {   private String state;

   public Memento(String stateToSave) { state = stateToSave; }   public String getSavedState() { return state; }}

class Originator {   private String state;   /* lots of memory consumptive private data that is not necessary to define the     * state and should thus not be saved. Hence the small memento object. */

   public void set(String state) {        System.out.println("Originator: Setting state to "+state);       this.state = state;    }

   public Memento saveToMemento() {        System.out.println("Originator: Saving to Memento.");       return new Memento(state);    }   public void restoreFromMemento(Memento m) {       state = m.getSavedState();        System.out.println("Originator: State after restoring from Memento: "+state);   }}   

class Caretaker {   private ArrayList<Memento> savedStates = new ArrayList<Memento>();

   public void addMemento(Memento m) { savedStates.add(m); }   public Memento getMemento(int index) { return savedStates.get(index); }

Page 189: Design Patterns

Behavioral patterns 189 of 205

}   

class MementoExample {   public static void main(String[] args) {       Caretaker caretaker = new Caretaker();

       Originator originator = new Originator();       originator.set("State1");       originator.set("State2");       caretaker.addMemento( originator.saveToMemento() );       originator.set("State3");       caretaker.addMemento( originator.saveToMemento() );       originator.set("State4");

       originator.restoreFromMemento( caretaker.getMemento(1) );   }}

Page 190: Design Patterns

Behavioral patterns 190 of 205

Null Object Design Pattern

Intent

The intent of a Null Object is to encapsulate the absence of an object by providing a substitutable alternative that offers suitable default do nothing behavior. In short, a design where “nothing will come of nothing”

Use the Null Object pattern when

• an object requires a collaborator. The Null Object pattern does not introduce this collaboration—it makes use of a collaboration that already exists

• some collaborator instances should do nothing

• you want to abstract the handling of null away from the client

Problem

Given that an object reference may be optionally null, and that the result of a null check is to do nothing or use some default value, how can the absence of an object — the presence of a null reference — be treated transparently?

Discussion

Sometimes a class that requires a collaborator does not need the collaborator to do anything. However, the class wishes to treat a collaborator that does nothing the same way it treats one that actually provides behavior.

Consider for example a simple screen saver which displays balls that move about the screen and have special color effects. This is easily achieved by creating a Ball class to represent the balls and using a Strategy pattern to control the ball’s motion and another Strategy pattern to control the ball’s color.

It would then be trivial to write strategies for many different types of motion and color effects and create balls with any combination of those. However, to start with you want to create the simplest strategies possible to make sure everything is working. And these strategies could also be useful later since you want as strategies as possible strategies.

Page 191: Design Patterns

Behavioral patterns 191 of 205

Now, the simplest strategy would be no strategy. That is do nothing, don’t move and don’t change color. However, the Strategy pattern requires the ball to have objects which implement the strategy interfaces. This is where the Null Object pattern becomes useful.

Simply implement a NullMovementStrategy which doesn’t move the ball and a NullColorStrategy which doesn’t change the ball’s color. Both of these can probably be implemented with essentially no code. All the methods in these classes do “nothing”. They are perfect examples of the Null Object Pattern.

The key to the Null Object pattern is an abstract class that defines the interface for all objects of this type. The Null Object is implemented as a subclass of this abstract class. Because it conforms to the abstract class’ interface, it can be used any place this type of object is needed. As compared to using a special “null” value which doesn’t actually implement the abstract interface and which must constantly be checked for with special code in any object which uses the abstract interface.

It is sometimes thought that Null Objects are over simple and “stupid” but in truth a Null Object always knows exactly what needs to be done without interacting with any other objects. So in truth it is very “smart.”

Structure

• Client -

◦ requires a collaborator.

• AbstractObject -

◦ declares the interface for Client’s collaborator

◦ implements default behavior for the interface common to all classes, as appropriate

• <strong>RealObject</strong> -

◦ defines a concrete subclass of AbstractObject whose instances provide useful behavior that Client expects

• <strong>NullObject</strong> -

◦ provides an interface identical to AbstractObject’s so that a null object can be substituted for a real object

◦ implements its interface to do nothing. What exactly it means to do nothing depends on what sort of behavior Client is expecting

◦ when there is more than one way to do nothing, more than one NullObject class may be required

Page 192: Design Patterns

Behavioral patterns 192 of 205

Rules of thumb

• The Null Object class is often implemented as a Singleton. Since a null object usually does not have any state, its state can’t change, so multiple instances are identical. Rather than use multiple identical instances, the system can just use a single instance repeatedly.

• If some clients expect the null object to do nothing one way and some another, multiple NullObject classes will be required. If the do nothing behavior must be customized at run time, the NullObject class will require pluggable variables so that the client can specify how the null object should do nothing (see the discussion of pluggable adaptors in the Adapter pattern). This may generally be a symptom of the AbstractObject not having a well defined (semantic) interface.

• A Null Object does not transform to become a Real Object. If the object may decide to stop providing do nothing behavior and start providing real behavior, it is not a null object. It may be a real object with a do nothing mode, such as a controller which can switch in and out of read-only mode. If it is a single object which must mutate from a do nothing object to a real one, it should be implemented with the State pattern or perhaps the Proxy pattern. In this case a Null State may be used or the proxy may hold a Null Object.

• The use of a null object can be similar to that of a Proxy, but the two patterns have different purposes. A proxy provides a level of indirection when accessing a real subject, thus controlling access to the subject. A null collaborator does not hide a real object and control access to it, it replaces the real object. A proxy may eventually mutate to start acting like a real subject. A null object will not mutate to start providing real behavior, it will always provide do nothing behavior.

• A Null Object can be a special case of the Strategy pattern. Strategy specifies several ConcreteStrategy classes as different approaches for accomplishing a task. If one of those approaches is to consistently do nothing, that ConcreteStrategy is a NullObject. For example, a Controller is a View’s Strategy for handling input, and NoController is the Strategy that ignores all input.

• A Null Object can be a special case of the State pattern. Normally, each ConcreteState has some do nothing methods because they’re not appropriate for that state. In fact, a given method is often implemented to do something useful in most states but to do nothing in at least one state. If a particular ConcreteState implements most of its methods to do nothing or at least give null results, it becomes a do nothing state and as such is a null state.

• A Null Object can be used to allow a Visitor to safely visit a hierarchy and handle the null situation.

• Null Object is a concrete collaborator class that acts as the collaborator for a client which needs one. The null behavior is not designed to be mixed into an object that needs some do nothing behavior. It is designed for a class which delegates to a collaborator all of the behavior that may or may not be do nothing behavior.

Observer Design Pattern

Intent

• Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

• Encapsulate the core (or common or engine) components in a Subject abstraction, and the

Page 193: Design Patterns

Behavioral patterns 193 of 205

variable (or optional or user interface) components in an Observer hierarchy.

• The “View” part of Model-View-Controller.

Problem

A large monolithic design does not scale well as new graphing or monitoring requirements are levied.

Discussion

Define an object that is the “keeper” of the data model and/or business logic (the Subject). Delegate all “view” functionality to decoupled and distinct Observer objects. Observers register themselves with the Subject as they are created. Whenever the Subject changes, it broadcasts to all registered Observers that it has changed, and each Observer queries the Subject for that subset of the Subject’s state that it is responsible for monitoring.

This allows the number and “type” of “view” objects to be configured dynamically, instead of being statically specified at compile-time.

The protocol described above specifies a “pull” interaction model. Instead of the Subject “pushing” what has changed to all Observers, each Observer is responsible for “pulling” its particular “window of interest” from the Subject. The “push” model compromises reuse, while the “pull” model is less efficient.

Issues that are discussed, but left to the discretion of the designer, include: implementing event compression (only sending a single change broadcast after a series of consecutive changes has occurred), having a single Observer monitoring multiple Subjects, and ensuring that a Subject notify its Observers when it is about to go away.

The Observer pattern captures the lion’s share of the Model-View-Controller architecture that has been a part of the Smalltalk community for years.

Structure

Subject represents the core (or independent or common or engine) abstraction. Observer represents the variable (or dependent or optional or user interface) abstraction. The Subject prompts the Observer objects to do their thing. Each Observer can call back to the Subject as needed.

Example

The Observer defines a one-to-many relationship so that when one object changes state, the others are notified and updated automatically. Some auctions demonstrate this pattern. Each bidder possesses a numbered paddle that is used to indicate a bid. The auctioneer starts the bidding, and “observes” when a paddle is raised to accept the bid. The acceptance of the bid

Page 194: Design Patterns

Behavioral patterns 194 of 205

changes the bid price which is broadcast to all of the bidders in the form of a new bid.

Check list

1. Differentiate between the core (or independent) functionality and the optional (or dependent) functionality.

2. Model the independent functionality with a “subject” abstraction.

3. Model the dependent functionality with an “observer” hierarchy.

4. The Subject is coupled only to the Observer base class.

5. The client configures the number and type of Observers.

6. Observers register themselves with the Subject.

7. The Subject broadcasts events to all registered Observers.

8. The Subject may “push” information at the Observers, or, the Observers may “pull” the information they need from the Subject.

Rules of thumb

• Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.

• Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing “observer” and “subject” objects, whereas a Mediator object encapsulates the communication between other objects. We’ve found it easier to make reusable Observers and Subjects than to make reusable Mediators.

• On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.

Page 195: Design Patterns

Behavioral patterns 195 of 205

State Design Pattern

Intent

• Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

• An object-oriented state machine

• wrapper + polymorphic wrappee + collaboration

Problem

A monolithic object’s behavior is a function of its state, and it must change its behavior at run-time depending on that state. Or, an application is characterixed by large and numerous case statements that vector flow of control based on the state of the application.

Discussion

The State pattern is a solution to the problem of how to make behavior depend on state.

• Define a “context” class to present a single interface to the outside world.

• Define a State abstract base class.

• Represent the different “states” of the state machine as derived classes of the State base class.

• Define state-specific behavior in the appropriate State derived classes.

• Maintain a pointer to the current “state” in the “context” class.

• To change the state of the state machine, change the current “state” pointer.

The State pattern does not specify where the state transitions will be defined. The choices are two: the “context” object, or each individual State derived class. The advantage of the latter option is ease of adding new State derived classes. The disadvantage is each State derived class has knowledge of (coupling to) its siblings, which introduces dependencies between subclasses.

A table-driven approach to designing finite state machines does a good job of specifying state transitions, but it is difficult to add actions to accompany the state transitions. The pattern-based approach uses code (instead of data structures) to specify state transitions, but it does a good job of accomodating state transition actions.

Structure

The state machine’s interface is encapsulated in the “wrapper” class. The wrappee hierarchy’s interface mirrors the wrapper’s interface with the exception of one additional parameter. The extra parameter allows wrappee derived classes to call back to the wrapper class as necessary. Complexity that would otherwise drag down the wrapper class is neatly compartmented and encapsulated in a polymorphic hierarchy to which the wrapper object delegates.

Page 196: Design Patterns

Behavioral patterns 196 of 205

Example

The State pattern allows an object to change its behavior when its internal state changes. This pattern can be observed in a vending machine. Vending machines have states based on the inventory, amount of currency deposited, the ability to make change, the item selected, etc. When currency is deposited and a selection is made, a vending machine will either deliver a product and no change, deliver a product and change, deliver no product due to insufficient currency on deposit, or deliver no product due to inventory depletion.

Check list

1. Identify an existing class, or create a new class, that will serve as the “state machine” from the client’s perspective. That class is the “wrapper” class.

2. Create a State base class that replicates the methods of the state machine interface. Each method takes one additional parameter: an instance of the wrapper class. The State base class specifies any useful “default” behavior.

3. Create a State derived class for each domain state. These derived classes only override the methods they need to override.

4. The wrapper class maintains a “current” State object.

5. All client requests to the wrapper class are simply delegated to the current State object, and the wrapper object’s this pointer is passed.

6. The State methods change the “current” state in the wrapper object as appropriate.

Rules of thumb

• State objects are often Singletons.

• Flyweight explains when and how State objects can be shared.

• Interpreter can use State to define parsing contexts.

Page 197: Design Patterns

Behavioral patterns 197 of 205

• Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).

• The structure of State and Bridge are identical (except that Bridge admits hierarchies of envelope classes, whereas State allows only one). The two patterns use the same structure to solve different problems: State allows an object’s behavior to change along with its state, while Bridge’s intent is to decouple an abstraction from its implementation so that the two can vary independently.

• The implementation of the State pattern builds on the Strategy pattern. The difference between State and Strategy is in the intent. With Strategy, the choice of algorithm is fairly stable. With State, a change in the state of the “context” object causes it to select from its “palette” of Strategy objects.

Strategy Design Pattern

Intent

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.

Capture the abstraction in an interface, bury implementation details in derived classes.

Problem

One of the dominant strategies of object-oriented design is the “open-closed principle”.

Figure demonstrates how this is routinely achieved - encapsulate interface details in a base class, and bury implementation details in derived classes. Clients can then couple themselves to an interface, and not have to experience the upheaval associated with change: no impact when the number of derived classes changes, and no impact when the implementation of a derived class changes.

A generic value of the software community for years has been, “maximize cohesion and minimize coupling”. The object-oriented design approach shown in figure is all about minimizing coupling. Since the client is coupled only to an abstraction (i.e. a useful fiction), and not a particular realization of that abstraction, the client could be said to be practicing “abstract coupling” . an object-oriented variant of the more generic exhortation “minimize coupling”.

A more popular characterization of this “abstract coupling” principle is “Program to an interface,

Page 198: Design Patterns

Behavioral patterns 198 of 205

not an implementation”.

Clients should prefer the “additional level of indirection” that an interface (or an abstract base class) affords. The interface captures the abstraction (i.e. the “useful fiction”) the client wants to exercise, and the implementations of that interface are effectively hidden.

Structure

The Interface entity could represent either an abstract base class, or the method signature expectations by the client. In the former case, the inheritance hierarchy represents dynamic polymorphism. In the latter case, the Interface entity represents template code in the client and the inheritance hierarchy represents static polymorphism.

Example

A Strategy defines a set of algorithms that can be used interchangeably. Modes of transportation to an airport is an example of a Strategy. Several options exist such as driving one’s own car, taking a taxi, an airport shuttle, a city bus, or a limousine service. For some airports, subways and helicopters are also available as a mode of transportation to the airport. Any of these modes of transportation will get a traveler to the airport, and they can be used interchangeably. The traveler must chose the Strategy based on tradeoffs between cost, convenience, and time.

Check list

1. Identify an algorithm (i.e. a behavior) that the client would prefer to access through a “flex point”.

2. Specify the signature for that algorithm in an interface.

Page 199: Design Patterns

Behavioral patterns 199 of 205

3. Bury the alternative implementation details in derived classes.

4. Clients of the algorithm couple themselves to the interface.

Rules of thumb

• Strategy is like Template Method except in its granularity.

• State is like Strategy except in its intent.

• Strategy lets you change the guts of an object. Decorator lets you change the skin.

• State, Strategy, Bridge (and to some degree Adapter) have similar solution structures. They all share elements of the ‘handle/body’ idiom. They differ in intent - that is, they solve different problems.

• Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).

• Strategy objects often make good Flyweights.

Template Method Design Pattern

Intent

Define the skeleton of an algorithm in an operation, deferring some steps to client subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

Base class declares algorithm ‘placeholders’, and derived classes implement the placeholders.

Problem

Two different components have significant similarities, but demonstrate no reuse of common interface or implementation. If a change common to both components becomes necessary, duplicate effort must be expended.

Discussion

The component designer decides which steps of an algorithm are invariant (or standard), and which are variant (or customizable). The invariant steps are implemented in an abstract base class, while the variant steps are either given a default implementation, or no implementation at all. The variant steps represent “hooks”, or “placeholders”, that can, or must, be supplied by the component’s client in a concrete derived class.

The component designer mandates the required steps of an algorithm, and the ordering of the steps, but allows the component client to extend or replace some number of these steps.

Template Method is used prominently in frameworks. Each framework implements the invariant pieces of a domain’s architecture, and defines “placeholders” for all necessary or interesting client customization options. In so doing, the framework becomes the “center of the universe”, and the client customizations are simply “the third rock from the sun”. This inverted control structure has been affectionately labelled “the Hollywood principle” - “don’t call us, we’ll call you”.

Structure

Page 200: Design Patterns

Behavioral patterns 200 of 205

The implementation of template_method() is: call step_one(), call step_two(), and call step_three(). step_two() is a “hook” method – a placeholder. It is declared in the base class, and then defined in derived classes. Frameworks (large scale reuse infrastructures) use Template Method a lot. All reusable code is defined in the framework’s base classes, and then clients of the framework are free to define customizations by creating derived classes as needed.

Example

The Template Method defines a skeleton of an algorithm in an operation, and defers some steps to subclasses. Home builders use the Template Method when developing a new subdivision. A typical subdivision consists of a limited number of floor plans with different variations available for each. Within a floor plan, the foundation, framing, plumbing, and wiring will be identical for each house. Variation is introduced in the later stages of construction to produce a wider variety of models.

Page 201: Design Patterns

Behavioral patterns 201 of 205

Check list

1. Examine the algorithm, and decide which steps are standard and which steps are peculiar to each of the current classes.

2. Define a new abstract base class to host the “don’t call us, we’ll call you” framework.

3. Move the shell of the algorithm (now called the “template method”) and the definition of all standard steps to the new base class.

4. Define a placeholder or “hook” method in the base class for each step that requires many different implementations. This method can host a default implementation – or – it can be defined as abstract (Java) or pure virtual (C++).

5. Invoke the hook method(s) from the template method.

6. Each of the existing classes declares an “is-a” relationship to the new abstract base class.

7. Remove from the existing classes all the implementation details that have been moved to the base class.

8. The only details that will remain in the existing classes will be the implementation details peculiar to each derived class.

Rules of thumb

• Strategy is like Template Method except in its granularity.

• Template Method uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm.

• Strategy modifies the logic of individual objects. Template Method modifies the logic of an entire class.

• Factory Method is a specialization of Template Method.

Visitor Design Pattern

Intent

• 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.

• The classic technique for recovering lost type information.

• Do the right thing based on the type of two objects.

• Double dispatch

Page 202: Design Patterns

Behavioral patterns 202 of 205

Problem

Many distinct and unrelated operations need to be performed on node objects in a heterogeneous aggregate structure. You want to avoid “polluting” the node classes with these operations. And, you don’t want to have to query the type of each node and cast the pointer to the correct type before performing the desired operation.

Discussion

Visitor’s primary purpose is to abstract functionality that can be applied to an aggregate hierarchy of “element” objects. The approach encourages designing lightweight Element classes - because processing functionality is removed from their list of responsibilities. New functionality can easily be added to the original inheritance hierarchy by creating a new Visitor subclass.

Visitor implements “double dispatch”. OO messages routinely manifest “single dispatch” - the operation that is executed depends on: the name of the request, and the type of the receiver. In “double dispatch”, the operation executed depends on: the name of the request, and the type of TWO receivers (the type of the Visitor and the type of the element it visits).

The implementation proceeds as follows. Create a Visitor class hierarchy that defines a pure virtual visit() method in the abstract base class for each concrete derived class in the aggregate node hierarchy. Each visit() method accepts a single argument - a pointer or reference to an original Element derived class.

Each operation to be supported is modelled with a concrete derived class of the Visitor hierarchy. The visit() methods declared in the Visitor base class are now defined in each derived subclass by allocating the “type query and cast” code in the original implementation to the appropriate overloaded visit() method.

Add a single pure virtual accept() method to the base class of the Element hierarchy. accept() is defined to receive a single argument - a pointer or reference to the abstract base class of the Visitor hierarchy.

Each concrete derived class of the Element hierarchy implements the accept() method by simply calling the visit() method on the concrete derived instance of the Visitor hierarchy that it was passed, passing its “this” pointer as the sole argument.

Everything for “elements” and “visitors” is now set-up. When the client needs an operation to be performed, (s)he creates an instance of the Vistor object, calls the accept() method on each Element object, and passes the Visitor object.

The accept() method causes flow of control to find the correct Element subclass. Then when the visit() method is invoked, flow of control is vectored to the correct Visitor subclass. accept() dispatch plus visit() dispatch equals double dispatch.

The Visitor pattern makes adding new operations (or utilities) easy - simply add a new Visitor derived class. But, if the subclasses in the aggregate node hierarchy are not stable, keeping the Visitor subclasses in sync requires a prohibitive amount of effort.

An acknowledged objection to the Visitor pattern is that is represents a regression to functional decomposition - separate the algorithms from the data structures. While this is a legitimate interpretation, perhaps a better perspective/rationale is the goal of promoting non-traditional behavior to full object status.

Structure

The Element hierarchy is instrumented with a “universal method adapter”. The implementation of accept() in each Element derived class is always the same. But – it cannot be moved to the Element base class and inherited by all derived classes because a reference to this in the Element class always maps to the base type Element.

Page 203: Design Patterns

Behavioral patterns 203 of 205

When the polymorphic firstDispatch() method is called on an abstract First object, the concrete type of that object is “recovered”. When the polymorphic secondDispatch() method is called on an abstract Second object, its concrete type is “recovered”. The application functionality appropriate for this pair of types can now be exercised.

Example

The Visitor pattern represents an operation to be performed on the elements of an object structure without changing the classes on which it operates. This pattern can be observed in the

Page 204: Design Patterns

Behavioral patterns 204 of 205

operation of a taxi company. When a person calls a taxi company (accepting a visitor), the company dispatches a cab to the customer. Upon entering the taxi the customer, or Visitor, is no longer in control of his or her own transportation, the taxi (driver) is.

Check list

1. Confirm that the current hierarchy (known as the Element hierarchy) will be fairly stable and that the public interface of these classes is sufficient for the access the Visitor classes will require. If these conditions are not met, then the Visitor pattern is not a good match.

2. Create a Visitor base class with a visit(ElementXxx) method for each Element derived type.

3. Add an accept(Visitor) method to the Element hierarchy. The implementation in each Element derived class is always the same – accept( Visitor v ) { v.visit( this ); }. Because of cyclic dependencies, the declaration of the Element and Visitor classes will need to be interleaved.

4. The Element hierarchy is coupled only to the Visitor base class, but the Visitor hierarchy is coupled to each Element derived class. If the stability of the Element hierarchy is low, and the stability of the Visitor hierarchy is high; consider swapping the ‘roles’ of the two hierarchies.

5. Create a Visitor derived class for each “operation” to be performed on Element objects. visit() implementations will rely on the Element’s public interface.

6. The client creates Visitor objects and passes each to Element objects by calling accept().

Rules of thumb

• The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable).

• Iterator can traverse a Composite. Visitor can apply an operation over a Composite.

• The Visitor pattern is like a more powerful Command pattern because the visitor may

Page 205: Design Patterns

Behavioral patterns 205 of 205

initiate whatever is appropriate for the kind of object it encounters.

• The Visitor pattern is the classic technique for recovering lost type information without resorting to dynamic casts.

Notes

The November 2000 issue of JavaPro has an article by James Cooper (author of a Java companion to the GoF) on the Visitor design pattern. He suggests it “turns the tables on our object-oriented model and creates an external class to act on data in other classes … while this may seem unclean … there are good reasons for doing it.”

His primary example. Suppose you have a hierarchy of Employee-Engineer-Boss. They all enjoy a normal vacation day accrual policy, but, Bosses also participate in a “bonus” vacation day program. As a result, the interface of class Boss is different than that of class Engineer. We cannot polymorphically traverse a Composite-like organization and compute a total of the organization’s remaining vacation days. “The Visitor becomes more useful when there are several classes with different interfaces and we want to encapsulate how we get data from these classes.”

His benefits for Visitor include:

• Add functions to class libraries for which you either do not have the source or cannot change the source

• Obtain data from a disparate collection of unrelated classes and use it to present the results of a global calculation to the user program

• Gather related operations into a single class rather than force you to change or derive classes to add these operations

• Collaborate with the Composite pattern

Visitor is not good for the situation where “visited” classes are not stable. Every time a new Composite hierarchy derived class is added, every Visitor derived class must be amended.