Docstoc

Multiple Inheritance

Document Sample
Multiple Inheritance Powered By Docstoc
					         Forward and Backwards
              Compatibility
• What do they mean?
• Suppose you are writing a web browser. Should the
  browser be able to handle future versions of HTML?
   – How do we ensure this?
• Suppose we are writing a new web browser. Should it be
  able to read in old versions of HTML?
   – How to ensure?
• Forward compatibility: The ability of an application to
  accept future versions of input.
• Backward compatibility: The ability of an application to
  accept previous versions of input.
 ABI (Application Binary Interface)
              vs. API
• Suppose you are designing and implementing
  module that fits within an application.
  – You design the interfaces carefully.
  – In version 2, you change the implementation, but the
    interfaces do not change.
     • Does the rest of the application need to be modified? Does it
       need to be recompiled?
     • Can you make your changes such that the application does
       not even need to be recompiled? Why does this matter? Isn’t
       recompiling simple?
     • Can you make your changes such that the application does
       not even need to be relinked?
• Is Node v2 backwards binary compatible with
  v1?
  – struct Node_v1 {
       double x;
       int i;
       int p1, p2, p3; // For extensibility.
    };
    struct Node_v2 {
       double x;
       int i;
       double p1;
       int p3; // For extensibility.
    };
• How to achieve binary compatibility in C/C++/Fortran,
  etc.?
   – // A.hpp
     class Aimpl;
     class A {
        public:
          void method1();
        private:
          Aimpl *impl;
     };
   – // A.cpp
     void A::method1() { impl->method1(); }
   – // Aimpl.hpp
     class Aimpl { … };
   – // What does a client need to include?
     #include “A.hpp”
     #include “Aimpl.hpp” // Needed?
   – When you modify the implementation by changing A.cpp is a
     recompile needed? What about Aimpl.hpp, is a recompile
     needed?
• Binary compatibility is important in these
  situations:
  – Large app. Want to ship bug fixes to
    customers.
     • With no binary compatibility, what happens? With
       binary compatibility?
  – Designing an OS. When you upgrade the OS,
    what happens to apps?
  – Libs and dlls. What happens if there is a bug
    in the C library on Windows or Linux?
Design Patterns
                       Introduction
• Designing reusable object-oriented software is hard.
   –   Find the right objects/classes.
   –   Find the right factorization.
   –   Define the interfaces.
   –   Define the inheritance hierarchies.
• Solves the problem at hand
   – But also general enough to address future problems and
     requirements.
• Very hard to get right the first time.
   – An iterative process.
• Design it, try reuse, redesign/refactor, try reuse again.
• Do not solve every problem starting from first
  principles.
  – When building a house, each house does not have to
    be designed starting from each nail or screw.
  – There are well-known “templates” or “patterns” for
    building a house that can then be customized, like
    kitchen plans, etc.
  – “Each pattern describes a problem which occurs over
    and over again in our environment, and then
    describes the core of the solution to that problem, in
    such a way that you can use this solution a million
    times over, without ever doing it the same way twice.”
     What is a Design Pattern
• Description of communicating objects and
  classes that are then customized to solve
  a general design problem in a particular
  context.
  – Pattern name
     • Are names important?
  – Problem: when to apply the pattern
  – Solution: the elements that make up the
    design
  – Consequences: results and trade-offs
   Organizing Design Patterns
• Purpose:
  – Creational
     • Dealing with object creation: Factory Method
  – Structural
     • Dealing with composition: Adapter
  – Behavioral
     • Dealing with behavior: Visitor
• Scope:
  – Class
     • Applies primarily to classes
  – Object
     • Applies primarily to objects
           Interface vs. Class
• In common OOP usage:
  – Interface: What the methods are named, the
    parameters they take, return types, and the
    semantics.
  – Class: The implementation of the interface, the actual
    data members, method implementation code, etc.
• In C++, there is greater ability to mix and match
  the features of interfaces and classes, so
  interface is somewhat implicit.
  – Virtual functions and abstract base classes can be
    used to make them more explicit.
  – A class with just pure virtual functions and no data
    members is essentially an interface.
• What is the interface of this class?
  – struct A {
        void f(int);
    };

• Do these two classes have the same
  interface?
  – struct A   {
        void   f(int);
    };
    struct B   {
        void   f(int);
    };
• Do Impl1 and Impl2 have the same interface?
  – struct Interface {
        virtual void f1()   = 0;
    ;
    struct Impl1 : public   Interface {
        virtual void f1()   { … }
    };
    struct Impl2 : public   Interface {
        virtual void f1()   { … }
    };

• When we use the word interface, we usually
  include semantics. But the programming
  language only enforces syntactic.
• Program to the interface, not to the
  implementation.
                 Reuse
• Suppose in the first version of your
  application, you have a Engine class,
  with methods stop() and start().
• Now you also want a Car class. If you just
  inherit from from Engine, you can just
  automatically get stop() and start().
• Should you? Or should you use
  composition?
• Example:
  – class Engine {
        public:
            void stop();
            void start();
    };
    // Automatically get stop() and start().
    class Car1 : public Engine {
    };
    // This way requires more coding.
    class Car2 {
        public:
            void stop() { engine.start(); }
            void start() { engine.stop(); }
        private:
            Engine engine;
            // Engine *engine;
    };
• Generally, prefer composition to
  inheritance.
              Delegation
• One aspect of composition is delegation.
• For example, in a GUI, a Window might be
  based on a Rectangle class. If we use
  composition, then an invocation of the
  area() method of a Window object can
  be forwarded to the Rectangle object.
  – int Window::area() {
        return rect->area();
    }
         Fragile Base Class
• Often, seemingly safe changes to a base
  class cause things to break in the derived
  classes.
• Example:
• Someone writes a bag class.
  – class Bag {
        public:
            void add(int);
    };
• Some wants to keep track of how many
  numbers are in the bag.
  – class Bag {
        public:
            void add(int);
    };
    class CountingBag : public Bag {
        public:
            void add(int i) {
                count++;
                Bag::add(i);
            }
    };
• Someone wants to add a convenience function
  to add a range of numbers at once.
  – class Bag {
        public:
            void add(int);
            // addAll() calls add().
            void addAll(int i, int j) {
              … add(i); … }
    };
    class CountingBag : public Bag {
        public:
            void add(int i) {
                count++;
                Bag::add(i);
            }
    };
    Run-Time Type Identification
             (RTTI)
• Sometimes you need to know the actual
  type of an object, when you have just a
  pointer to the base class.
• How do you do inheritance in C?
• Inheritance in C:
  – struct A {
        int a_member; };
    struct B {
        struct A A_sub;
        int b_member; };
    struct C1 {
        struct B B_sub;
        int c1_member; };
    struct C2 {
        struct B B_sub;
        int c2_member; };
• Upcasting and downcasting:
  – struct C1 c1;
    C1_ctor(&c1);
    A *a = (A *) &c; // Upcast
    B *b = a; // Downcast
    A *ap = …; // Pointer to A obtained somehow.
    C2 *c2 = (C2 *) ap; // Safe?
• Inheritance in C:
  – struct A {
        int a_member; };
    struct B1 {
        struct A A_sub;
        int b1_member; };
     struct B2 {
        struct A A_sub;
        int b2_member; };
• How do we be safe? Try to make sure of type.
  – A *ap = …; // Pointer to A obtained somehow.
    if (/* ap is really a B1 */) {
        B1 *b1 = (B1 *) ap;
       // Do something with b1 that is B1 specific.
    } else if (/* ap is really a B2 */) {
        B2 *b2 = (B2 *) ap;
       // Do something with b2 that is B2 specific.
    }
• Use type ID of some kind.
  – struct A {
      enum { T_B1, T_B2 } id;
      int a_member; };
    struct B1 {
      struct A A_sub;
      int b1_member; };
    struct B2 {
      struct A A_sub;
      int b2_member; };
• Check ID before downcast.
  – A *a = …; // Pointer to A   obtained somehow.
    if (a->id == T_B1) {
      B1 *b1 = (B1 *) a;
      // Do something with b1   that is B1 specific.
    } else if (a->id == T_B2)   {
      B2 *b2 = (B2 *) a;
      // Do something with b2   that is B2 specific.
    }
• Error prone: where is the ID set?
  – struct A {
        enum { B1_T, B2_T } id;
        …
    };
    struct B1 {
        struct A A_sub; };
    struct B2 {
        struct A A_sub;
    };
    B1 b1; // No constructor
    b1.A_sub.id = B1_T;
• If using C++, can do it in the constructor.
  – struct A {
        enum { B1_T, B2_T } id;
        A(enum Id i) : id(i) {}
        …
    };
    struct B1 {
        B1() : A_sub(B1_T) {}
        struct A A_sub; };
    struct B2 {
        B2() : A_sub(B2_T) {}
        struct A A_sub;
    };
    B1 b1;
• What are more idiomatic C++ solutions?
• What does this do?
  – struct A { virtual ~A() {} };
    struct B1 : public A { … };
    struct B2 : public A { … };
    B1 b;
    A *a = &b;
    B2 *bp = dynamic_cast<B2 *>(a);
    bp == ??; // What is the value of bp?

• Can use dynamic casting.
• Can also use RTTI:
  – #include <typeinfo>
    struct A { virtual ~A() {} };
    struct B1 : public A { … };
    struct B2 : public A { … };
    B1 b;
    A *a = &b;
    if (typeid(*a) == typeid(B1)) {
        …
    } else if (typeid(*a) == typeid(B2)) {
        …
    } else if (typeid(*a) == typeid(B3)) {
        …
    }
• The typeid operator returns a reference
  to an object of class type_info.
• The type_info object has a string name
  that can sometimes be helpful for
  debugging.
  – struct A { virtual ~A() {} };
    struct B1 : public A { … };
    struct B2 : public A { … };
    B1 b;
    A *a = &b;
    cout << typeid(*a).name() << endl;
• Is this efficient?
  – A *a = …; // Obtained somehow.
    if (typeid(*a) == typeid(B1)) {
        …
    } else if (typeid(*a) == typeid(B2)) {
        …
    } else if (typeid(*a) == typeid(B3)) {
        …
    } … {
    } else if (typeid(*a) == typeid(B100)) {
        …
    }

• Solution?
• You could push the code into the object:
  – // Original version.
    if (typeid(*a) == typeid(B1)) {
        // Some code to do XYZ.
    } else if (typeid(*a) == typeid(B2)) {
        // Some code to do ABC.
    }
  – // Code moved into a virtual function in the
    // object.
    virtual void B1::doit() {
        // Code to do XYZ.
    }
    virtual void B2::doit() {
        // Code to do ABC.
    }
    …
    a->doit(); // Outside of the object.
• Disadvantage?
  – Intrusive, however.
• The problem is to efficiently map from the
  type to the code that should be executed
  for that type.
  – struct Code {
        virtual void operator()(A *) const = 0;
    };
    struct Code_B1 : public Code {
        virtual void operator()(A *) const;
    };
    map<type_info *, Code, Cmp> type_map;
    Code &code = type_map.lookup(&typeid(*a));
    code(a);
• In order to efficiently store type_info in
  a map, what operation do we need?
  – The type_info object has before() method.
          Class Diagrams
• Diagram the relationships between
  classes.
  Abstract class or
interace (Italicized)




     Class name




       Methods



  Member variables
  (Only if concrete)
         Client                  Client

        Participant           Non-participant




• Clients that aren’t active participants in the
  pattern are shown in gray.
   Aggregation      Multiplicity
                                        Interface
                 Name




                                       Inheritance




        Instantiation              Acquaintance


• Class relationships
• Pseudo-code annotation
          Object Diagrams

• Describe relationships between actual
  objects.
Reference
  name
                           Reference




             Object name
            (aSomeclass)
         Interaction Diagrams
• Describe how objects interact.
  – How do you do this?
     • Function F invokes function G, in two different call
       sites.
     • In the second invocation, G invokes F.
         Object name




                                        Not yet
                       Instantiation
                                        created



                  Request name
                                       Object
                                       lifetime



Object
active
                 Example

• class A {
      public:
          A() : paren(0), a1(new A(this)),
                         a2(new A(this)) {}
          void start() {
              a1->foo();
              a2->foo();
          }
      private:
          A(A *p)
                 : paren(p), a1(0), a2(0) {}
          void foo() { paren->goo(); }
          void goo();
      private:
          A *a1, *a2, *paren;
  };
Most Common Patterns
              Abstract Factory
             (Object Creational)
• Intent
  – Provide an interface for creating families of related
    objects without specifying concrete factories.
• Motivation
  – Consider an application with a GUI that needs to run
    on both Windows and Linux. You might need to
    create a Window with a containing Scrollbar. You
    want the Windows version to create Windows
    interface objects, and the Linux version to create
    Linux interface objects.
• Interface has create methods.
  – Concrete derived class creates various concrete
    classes.
• Example:
  – struct MazeFactory {
        virtual Maze *MakeMaze() const = 0;
        virtual Wall *MakeWall() const = 0;
    };
    struct MagicMazeFactory : public MazeFactory {
        virtual Maze *MakeMaze() const {
            return new MagicMaze; }
        virtual Wall *MakeWall() const {
            return new MagicWall; }
    };
    struct BombedMazeFactory
                        : public MazeFactory { … };
    Maze *BuildMaze(MazeFactory *) { … }
    // Make a magic maze.
    MazeFactory *mmf = new MagicMazeFactory;
    Maze *m = BuildMaze(mmf);
    // Make a bombed maze.
    MazeFactory *bmf = new BombedMazeFactory;
    Maze *m = BuildMaze(bmf);
             Factory Method
            (Class Creational)
• Intent
  – Define an interface for creating an object, but
    let subclasses decide which class to
    instantiate.
• Motivation
  – At the point at which an object is created, it is
    unknown which actual implementation to use.
• Factory method subclasses the thing creating the
  objects.
• Can have a factory method without an abstract factory.
• Suppose you have different kinds of String
  implementations, optimized for different
  cases:
  – Short strings
  – Strings that don’t change
  – UTF-8 strings
  – Etc.
• You want to completely isolate these
  optimizations. The rest of the application
  should not know that there are different
  kinds of string types.
• So, can you put this in application code?
  – // Dealing with Unicode, so create
    Unicode optimized string.
    String *str = new UnicodeString;
• Use a virtual constructor approach.
  – class String {
        public:
            enum LengthType { FIXED, DYNAMIC };
            enum Encoding { UTF-8, ASCII };
            static String *MakeString(int len,
    LengthType,
                                          Encoding);
    };
    class UTFString : public String {… };

    String *String::MakeString(…) {
        // Decide which version to make…
        if (…) {
            return new UTFString(…);
        } else if (…) {
            return new ASCIIString(…);
        } …
    }
• Optimized implementations can now be
  added completely independently, without
  affecting the rest of the application at all.
• Application just says:
  – String *s = String::MakeString(…);
               Adapter
       (Class/Object Structural)
• Intent
  – Convert interface of a class into one that is
    expected.
• Commonly called a wrapper.
• Can use inheritance or composition.
• Within a single class.
• As two separate objects (probably
  preferred).
• Example: Adapt a TextView object to a Shape interface.
   – struct Shape {
       virtual void BoundingBox(Point &bottom_left,
                            Point &top_right) const;
     };
   – class TextView {
       void GetOrigin(Coord &x, Coord &y) const;
       void GetExtent(Coord &width,
                                Coord&height) const;
     }
• Using inheritance
   – class TextShape
                  : public Shape, private TextView {
         BoundingBox(Point &bl, Point &tr) const {
             GetOrigin(…);
             GetExtent(…);
             …
         }
     }
• Example: Adapt a TextView object to a Shape interface.
   – struct Shape {
       virtual void BoundingBox(Point &bottom_left,
                            Point &top_right) const;
     };
   – class TextView {
       void GetOrigin(Coord &x, Coord &y) const;
       void GetExtent(Coord &width,
                               Coord &height) const;
     }
• Using composition
   – class TextShape : public Shape {
       public:
         BoundingBox(Point &bl, Point &tr) const {
           tv.GetOrigin(…);
           tv.GetExtent(…);
           …
         }
       private: TextView tv;
     }
                Composite
             (Object Structural)
• Applicability
  – Part-whole hierarchies
  – Compositions of objects and individual objects
    treated the same.
• Example
  – An expression is:
     • A number by itself
     • A variable by itself
     • An operator
• A composite of things has the same interface as
  the contained things.
• Example:
  – class Expression { … };
    class Operator : public Expression {
        …
        private:
            Expression *left, *right;
    };
    class Leaf : public Expression {
        …
    };
                Decorator
            (Object Structural)
• Intent
  – Adding additional responsibilities/functionality
    to an object dynamically.
  – Alternative to subclassing.
  – Differs from Adapter in that Adapter changes
    the interface, while Decorator only modifies
    the features, not the interface.
• Example:
  – class VisualComponent {
        public:
            virtual void Draw() const;
    };
    class Decorator : public VisualComponent {
        public:
            Decorator(VisualComponent *);
            virtual void Draw() const;
        private:
            VisualComponent *comp;
    };
    void Decorator::Draw() {
        comp->Draw();
    }
    class Border : public Decorator { … };
    void Border::Draw() {
        Decorator::Draw();
        // Do stuff to draw border.
    }
• Discussion
  – Can be dynamic, unlike subclassing.
  – Avoids creating all possible combinations of
    subclasses. For example, if there are two
    possible decorations, D1, and D2, and two
    possible elements, E1, and E2, you would
    have to have ? different subclasses.
                        Observer
• Intent
   – Define a dependency (subscription) relationship between
     objects, so that when the observed object changes state, all
     observers are notified and updated automatically.
   – It is the View, in the MVC pattern.
• Motivation
   – Suppose you have a set of objects which needs to be notified
     when object A changes.
• Applicability
   – When a change to one object requires changing others, and you
     don’t know how many others need to be changed.
   – When an object should be able to notify other objects, and you
     don’t know the other objects ahead of time.
• Notify() is called by the subject itself when setstate() is called.
•   Example:
     –   class Observer {
           public:
             virtual void Update();
         };
         class Subject {
           public:
             void Notify() {
               for (it = list.begin();
                               it != list.end(); ++it) {
                 it->Update();
             }
         };
         class MyObserver : public Observer {
           void Update() {
             subject->getState();
             …
           }
         };
         class MySubject : public Subject {
           void SetState(…) {
             …
             Notify();
           }
         }
•   Who should call Notify(), the subject itself, or the object changing the state?
•   Suppose an observer itself need to set the state in Update.
•   Suppose a derived class operation is composed of several base class
    operations.
                     Strategy
                (Object Behavioral)
• Intent: Define a family of algorithms, encapsulate each
  one, make them interchangeable.
• Motivation: Many algorithms exist for breaking a stream
  of text into lines.
   – Do not want to put the code in the clients that need linebreaking.
   – Want to support multiple algorithms.
   – Want to support easily adding them.
• Applicability:
   –   You need variants of an algorithm.
   –   Many related classes differ only in their behavior.
   –   An algorithm uses data that clients shouldn’t know about.
   –   A class defines many different behaviors, and these show up as
       multiple conditionals in the ops. Move branches into strategy
       class.
• Strategy and context collaborate to
  provide the behavior.
• Consequences:
  – Alternative to subclassing.
      • You could subclass the Context object.
  – Eliminate conditional statements.
      • void Composition::Repair() {
          switch (line_breaking_strategy) {
            case SIMPLE:
              BreakWithSimple();
              break;
            case TEX:
              BreakWithTex();
              break;
              …
        }
      • void Composition::Repair() {
          compositor->BreakLines():
          …
        }
  – A choice of implementations. Makes it easy to compare two
    different ones.
• Implementation Issues:
  – How do the Strategy and Context
    communicate? What is passed?
  – Use a template. What are the benefits?
• Example:
  – class LineBreaker {
    public:
        virtual vector<string>
        break(const vector<string> &) const;
    };
    class Paragraph {
    public:
        Paragraph(const LineBreaker *);
        void addLine(const string &);
    private:
        const LineBreaker *const breaker;
    };
    void Paragraph::addLine(const string &l) {
        // Do stuff to add the line.
        lines = line_break->break(lines);
    }
               Template Method
              (Class Behavioral)
• Intent
  – Define the overall steps of an operation in a super-
    class method, but deferring the exact implementation
    of the steps to methods in derived classes.
• Motivation
  – You have some code that is similar, but not identical
    in multiple classes.
     • Factor out the similarity into a template method.
     • Use derived class methods (or function pointers) to handle
       the similar parts.
• Suppose you have an application
  framework with App and Doc objects.
  Specific applications, such as a drawing
  application or a spreadsheet application
  will subclass these.
  – One thing in common is the need to open a
    document. The overall sequence of steps is
    identical for all apps, but the specific details of
    how each step is carried out varies.
  – So, put the overall sequence in the base
    class, and let derived classes define exactly
    what to do.
•   class App {
       void OpenDoc(const char *name);
    };
    class MyApp {
       void CanOpenDoc(const char *name);
       Doc *DoCreateDoc(const char *name);
       void AboutToOpenDoc(Doc *);
    };
    void App::OpenDoc(const char *name) {
      if (!CanOpenDoc(name)) { return; }
      Doc *d = DoCreateDoc(name);
      if (d) {
        AboutToOpenDoc(d);
        d->Open();
        d->DoRead();
      }
    }
    void MyApp::CanOpenDoc(const char *name) {
      // Do stuff here specific to this app, such as maybe
      // check the format of the file to make sure it is of
      // the right type.
      // …
    }
    void MyApp::DoCreateDoc(const char *name) { … }
    void MyApp::AboutToOpenDoc(Doc *) { … }
• Applicability:
  – Implement the invariant parts of an algorithm
    once.
     • Sort, pick some good candidates using a metric,
       run a computation with those candidates, then do
       an update based on those results, but also
       dependent on the metric.
  – When common behavior should be factored
    and localized to a superclass.
  – Control and define subclass extensions.
• Example: A class called View that supports
  drawing on the screen.
  – Before drawing can begin, the focus must first be set.
    Base class does that, then calls derived class.
  – void View::Display() {
        SetFocus();
        DoDisplay();
        ResetFocus();
    }
    void MyView::DoDisplay() {
        // App-defined stuff.
    }
  – So user derives from base class.
• Tip: Use a naming convention to make clear
  what should be implemented by derived class.
• Basic idea here is that you want to put common
  code in the base class.
• Is there another way to do the same thing?
  – class Base {
       void op();
    };
    class Derived: public Base {
       virtual void op() {
         …
         Base::op();
       }
    };
  – Advantages, disadvantages?
Patterns Catalog
     Related Factory Patterns
• Abstract Factory
  – An object with factory methods.
• Factory Method
  – A method within an object that is subclassed.
• Builder
  – An object to which you feed a sequence of things to it,
    then get the result in the end.
• Prototype
  – Another way of creating objects via a clone() method.
       Builder (Object Creational)
• Intent: Separate the construction of a complex object
  from its representation so that the same construction
  process can create different representations.
• Motivation: Suppose you have an object to read RTF.
  You want it to be able to convert to multiple different
  representation types, such as ASCII, or HTML.
  Solutions?
   – // In reader
     while (t = get the next token) {
       switch (t.type) {
         case CHAR: builder->ConvertChar(t.char);
         case FONT: builder->ConvertFont(t.font);
         case PARA: builder->ConvertPara(t.para);
• Applicability:
  – Algorithm for creating a complex object
    should be independent of the parts that make
    up the object.
  – The construction process must allow for
    different representations.
• Builder similar to AF.
   – Builder focuses on creating a complex object step-by-step.
   – AF focus is on families of product objects.
   – Builder often returns product as final step. AF often returns
     immediately.
   – Where is the product stored?
                    Prototype
                (Object Creational)
• Intent
   – Specify the kinds of objects to create using a prototypical
     instance, and create new objects by copying this protoype.
• Motivation
   – Suppose you have a GUI element called a GraphicTool that
     will let you create and place a graphic in a music editor. You
     want to create and place a number of different ones, like
     WholeNote and HalfNote.
   – The GraphicTool needs to instantiate the graphic, such as
     WholeNote or HalfNote. You could create one GraphicTool
     for each graphic.
   – Better is to initialize each GraphicTool with an instance of a
     Graphic abstract class, that it then clones.
   – Other solutions?
       • Could use a factory of some kind.
• class Client {
     void Op() {
       p = prototype->Clone();
     }
  }
  class MyProto1 : public Proto {
     virtual MyProto1 *Clone() { … }
  };
  class MyProto2 : public Proto {
     virtual MyProto2 *Clone() { … }
  };
• Do we need to use a separate class for whole
  notes and half notes?
• Applicability:
  – When class to instantiate are specified at run-
    time.
  – To avoid building a hierarchy of factories that
    parallel the products.
  – When instances of a class can have only a
    few combinations of state.
     • Easier than instantiating manually, especially if
       many parameters, but few combinations.
• Example
  – class MazePrototypeFactory {
    public:
        MazePrototypeFactory(Maze*, Wall*, Room *);
        virtual Maze *MakeMaze() const;
        virtual Room *MakeRoom() const;
        virtual Wall *MakeWall() const;
    private:
        Maze *protoMaze;
        Room *protoRoom;
        Wall *protoWall;
    };
    Wall *MazePrototypeFactory::MakeWall() const {
        return protoWall->clone();
    }
    MazePrototypeFactory bombedMF(new Maze, new
    BombedWall, new BombedRoom);
• Consequences
  – Requires implementing clone(), so is intrusive.
  – Does not require a whole set of parallel classes, as
    using factories might.
      • A factory for each type, like bombed wall, etc.
      • The concept is like merging the factory with the object that
        it creates.
  – Supports user-templates. For example, say you
    have a graphic that you want to put into a palette.
  – Can be very dynamic, and have prototypes with
    different values (but same class). (Factories can do
    this to, but not quite as elegant.)
      • // Five bombs per wall.
        MazeProtoFactory mf5(new BombedWall(5));
        // Ten bombs per wall.
        MazeProtoFactory mf10(new BombedWall(10));
• Implentation:
  – If lots of prototypes, and there is a need to
    search for them based on attributes, use a
    prototype manager/registry.
 Discussion of Factory Patterns
• Two ways of parameterizing a system by the classes of
  objects it creates:
   – Subclass the class that creates the objects. (FactoryMethod)
   – Define an object that is responsible for knowing what to create
     (AbstractFactory, Builder, Prototype)
• Consider the GraphicTool.
   – FactoryMethod would say subclass it, one to create HalfNote,
     the other to create WholeNote.
   – AbstractFactory would say pass in a factory object to create
     HalfNotes or WholeNotes.
   – Prototype would say pass in a prototype object that is cloned.
   – Note that the line between these is somewhat blurry sometimes.
         Traversing Containers
• Iterator
   – Essentially an object that functions as a pointer,or
     cursor. It has a current element that it points to, and
     methods to advance to the next element.
• Visitor
   – For data structures that are heterogeneous. Factor
     out the traversal code, and as you traverse the
     structure, make callbacks to a visitor object that is
     carried along the traversal.
      Iterator (Object Behavioral)
• Intent
  – Provide a way to access the elements of an
    aggregate object sequentially without exposing the
    underlying implementation.
• Motivation
  – How do you traverse a linked list? How did you learn
    how to do it?
  – A container like a linked list should have a way of
    traversing the elements without exposing its structure.
     • Suppose you have a variety of containers, such as a list and
       binary tree. You want to do something to every thing in the
       container using the same code.
     • Or suppose you want to traverse it in different ways, like
       forwards and backwards, or using different orderings.
– void foo(List *li) {
      ListNode *ptr = li->head;
      while (ptr != NULL) {
         // Do something with it.
         ptr = ptr->next;
      }
  }
– Suppose it was changed to an array? Or a balanced binary tree?
– Suppose this is traverse monsters. You decide that you want to
  filter out invisible ones.
– void foo(Container *li) {
      Iterator *it = il->getIterator(no_invisible);
      while (it->more()) {
         // Do something with it.
         it->next();
      }
  }
– Key Idea: Take the responsibility for traversal and
  access out of the container itself, and put it into an
  iterator object. The iterator object functions as a
  pointer, or cursor, or placeholder, that you can then
  advance, etc.
   • Using a single interface, different classes of iterator objects
     can traverse in different directions, or different ways. For
     example, you could have an OddIterator to skip all even
     elements.
       – class Iterator {
            void next();
            int get();
         };
         class OddIterator : public Iterator {…};
         IntList l;
         OddIterator it(l);
         it.get();
         it.next();
         it.get();
– How does the iterator know how to advance
  to the next element? Does it require
  implementation knowledge about the
  container.
  • Yes, so should use a pattern.
     – What class should be created? Should it be public?
     – class SomeList;
       Iterator it = sl.createIterator(); // What
       is this pattern?
     – SomeListIterator it(sl);
– How can this code be rewritten to make it
  more flexible/maintainable/adaptable?
  • void foo(List *) {
      ListIterator lit(l);
      for (; !lit.end(); lit.next()) {
        // Do something with lit.get().
      }
    }
  • void foo(Iterator *) {
      for (; !lit.end(); lit.next()) {
        // Do something with lit.get().
      }
    }
  • Known as polymorphic iteration.
• Applicability: when to use?
  – To access a container’s contents without
    exposing the internal representation.
  – Support different ways of traversing the same
    container. For example, in-order or pre-order
    traversal of a tree. Or backwards or forwards.
    Or filtering out certain elements.
  – Provide a uniform interface for traversing
    different kinds of containers (polymorphic
    iteration).
• Implementation issues:
    – External iterators vs. internal iterators.
        • Where is the code for traversal defined? It could be in the container, or it
          could be in the iterator.

class ListNode {                      // Internal tree iterator.
   private:                           void TreeNode::traverse(Handler *h)
     ListNode *next;                  {
     Object *obj;                       right->traverse(h);
};                                      h->handle(elem);
class ListIterator {                    left->traverse(h);
   public:                            }
     void next() {                    // External tree iterator.
       cur = cur->next;               class TreeIterator {
     }                                  public:
     Object *get() {                      void next() {
       return obj;                          if (cur->left != 0) {
     }                                        stack.push(cur);
};                                            cur = cur->left;
                                              while (cur->right != 0) {
// Tree                                         stack.push(cur);
class TreeNode {                                cur = cur->right;
   public:                                    }
   private:                                 }
     Node *right, *left;                  }
     Element *elem;
};
– How robust is the iterator?
    • // Using a list iterator to delete an element.
      List l; ListIterator lit = lit.begin();
      while (!lit.end()) {
        if (lit.get() == 1234) {
          lit.delete(); break;
        }
        lit.next();
      }
    • // Suppose you have this.
      List l; ListIterator lit = lit.begin();
      while (!lit.end()) {
        if (lit.get() == 1234) {
          foo();
        }
        lit.next();
      }
      void foo(ListIterator lit) {
        // …
        lit.delete();
      }
– Additional operations?
  • Iterator::skip2();
– How to implement in C++? Pointers?
  • Iterator *container::begin() { … }
    Iterator container::begin() { … }
                      Visitor
                (Object Behavioral)
• Intent
   – Represent an operation to be performed on the elements of an
     object structure.
• Motivation
   – Suppose you have some operation, like Print, that you that want
     to do on some tree data structure consisting of a number of
     objects of different types.
   – You could add a Print operation to each class. But suppose you
     also want to do something like convert to HTML. That also
     requires a tree traversal.
   – Better to have a Print visitor, and a separate HTML visitor, then
     use the Visitor pattern to factor out the traversal code.
       • This separates the structure of the container from the operations
         that you want to perform.
• Applicability: Use when:
  – Object structure contains many different types of
    objects that need to be handled differently.
  – Many distinct and unrelated ops need to be
    performed on the elements of a structure. You could
    put the ops in the structure as methods in the
    structure, but this pollutes, and limits extensibility:
     • class TreeNode {
         public:
            void convertToHtml(…);
            void print(…);
            void convertToASN1(…);
            …
       };
     • Suppose you want to add a new operation. What happens to
       users of the above class? What if it is library used throughout
       your company? Can you achieve binary compatibility?
Visitor
• Example
  – class Node {
        virtual void accept(Visitor *) const;
        void visitChildrenHelper(Visitor *) const;
    };
    class RedNode : public Node {
        virtual void accept(Visitor) const; };
    class BlackNode : public Node {…};
    void RedNode::accept(Visitor *v) const {
        v->visitRedNode(this);
        visitChildrenHelper(v);
    }
    void BlackNode::accept(Visitor *v) const {
        v->visitBlackNode(this);
        visitChildrenHelper(v);
    }
    class Visitor {
        virtual void visitRedNode(const RedNode *)
                                               = 0;
        virtual void
             visitBlackNode(const BlackNode *) = 0;
    };
• Consequences: Benefits and liabilities are:
  – Makes adding new operations easy. Just
    define a new Visitor.
  – What about adding new concrete element
    types? What if we added a new Node type to
    XML?
     • May require changing a lot of visitors.
  – Can visit objects that don’t have same base
    class, etc.
• Visitor and Iterator are related.
  – To see the difference, consider a Visitor with
    one visit method: visitItem().
     • Essentially same as internal iterator.
  – Or, think about how to use the iterator to visit
    objects of different types.
     • Iterator *it;
       for (Iterator it = list.begin(); !it.end(); it++) {
         if ((*it).type() == … ) { … }
       }
 Related “Handle-Body” (Wrapper)
            Patterns
• Adapter
   – Adapts interface
• Bridge
   – Allow two abstractions to vary independently by layering one on
     top of the other.
• Decorator (same interface)
   – A wrapper that adds functionality, but keeps the interface.
• Proxy (same interface)
   – A wrapper that “stands-in” for the real thing.
• State
   – A wrapper around state-specific implementations. Could be
     same interface or not.
       Bridge (Object Structural)
• Intent
  – Decouple an abstraction from its implementation so
    that the two can vary independently.
• Motivation
  – Usually, when an abstraction can have one of several
    implementations, the solution is inheritance.
     • But that means the implementation is bound to the
       abstraction. You can’t use the same implementation for a
       different abstraction. (Because you can’t dynamically change
       the base class. MI does allow you to statically support
       multiple abstractions.)
  – Sometimes, it is useful to have greater decoupling
    between abstraction and implementation.
  – Suppose I have a Shape base class, plus Triangle
    and Square derived classes. Now I want to have
    them drawn using different graphics libraries.
     • Suppose I have three different graphics libraries. How many
       subclasses do I need? Solution?
                       Bridge




• Create a simple API to use between two abstractions.
• Most useful when the concrete implementation of a
  higher level abstraction can be specified via a lower-level
  abstraction.
• Example:
  – class Shape {
        virtual void show(…);
        …};
    class Square : public Shape {
        virtual show(…) {
            impl->drawLine(…);
            impl->drawLine(…);
            impl->drawLine(…);
            impl->drawLine(…); };
    class Triangle : public Shape {
        virtual show(…) {
            impl->drawLine(…);
            impl->drawLine(…);
            impl->drawLine(…); };
    class GfxImpl { virtual void drawLine(…); …};
    class X11GfxImpl : GfxImpl {…};
    class GDIGfxImpl : GfxImpl {…};
• Applicability:
  – You want to avoid a permanent binding
    between abstraction and its implementation.
  – Both abstraction and implementations should
    be extensible by subclassing.
     • Decouples even more interface and
       implementation.
     • Avoids N*M different classes.
                       Proxy
                 (Object Structural)
• Intent
   – Provide a surrogate or placeholder for another object to control
     access to it.
• Motivation
   – Suppose you are writing a web browser. Getting images is slow.
     You don’t want to all images are downloaded before starting to
     render the page.
       • Solution?
       • Use a proxy for the image, that can participate in the rendering.
         Once the image has downloaded, then fill in.
   – Suppose you want to access objects remotely from a client app,
     as if they were local:
       • MyObject *o = …;
         o->method1(); // Actual object should be remote.
• Applicability:
  – Remote proxy
  – Virtual proxy: defer creation of expensive
    objects.
  – Protection proxy: control access to an object.
  – Smart reference: Do something like copy-on-
    write, or reference counting (smart pointers).
     • You want to share an implementation among
       multiple objects (maybe using reference counting
       plus COW).
  – You want to hide the implementation from
    your users. (C++)
• For example, a remote proxy might represent a
  local object on a remote machine.
• Examples
  – Suppose you want to be able to invoke remote objects. (Show)
  – Suppose you have objects that are usually copied many times
    (strings).
  – (Show copy on write example.)
  – Suppose you have a million Person objects, but you can’t store
    all the data about a person in the objects, because it would use
    too much space.
      • Person::getAge() {
          if (impl == 0) {
            impl = new PersonImpl(odbc_conn);
          }
          return impl->getAge();
        }
        Person::store() { // Called when system decides not needed.
          impl->persist();
          delete impl;
          impl = 0;
        }
      State (Object Behavioral)
• Intent: Allow an object to alter its behavior
  when its internal state changes. The object
  will appear to change its class.
  – We can do this without using the state pattern,
    right?
– Suppose we have a TCPConnection object. It has three
  methods: Open(), Close(), Ack(). It also has three states:
  Established, Listening, Closed. It behaves differently in response
  to the methods depending on what state it is in.
    • How do you solve this?
        – TCPConnection::Open() {
            switch (state) {
              case Established: … break;
              case Listening: … break;
              case Closed: … break;
          }
        – TCPConnection::Close() {
            switch (state) {
              case Established: … break;
              case Listening: … break;
              case Closed: … break;
          }
        – TCPConnection::Ack() {
            switch (state) {
              case Established: … break;
              case Listening: … break;
              case Closed: … break;
          }
• Motivation
  – Based on Handle/Body.
  – A way of allowing an object to change
    implementation dynamically. Essentially
    changing classes.
  – Normally, once an object is created, the
    implementation can’t change.
     • Connection *conn = new My1Conn;
       // Cannot at a later time change to My2Conn.
  – How can we make this happen?
     • Use a wrapper around an implementation object
       that changes as the state changes. Forward all
       methods to wrapper.
• Applicability: Use when:
  – An object’s behavior depends on its state, and
    it must change behavior at run-time
    depending on that state.
  – Operations have large, multipart conditional
    statements to handle the state.
• Rather than have a state variable, and the
  implementation check that, just use a completely
  different implementation object.
• Example:
  – class Connection {
        void open() {
            conn_state = conn_state->open();
        }
    };
    class UnopenedState : public ConnState {
        virtual ConnState *open() {
            return new OpenedState(…);
        };
    };
     class OpenedState : public ConnState {
        virtual ConnState *open() {
            return this;
            // Or return error.
        };
    };
  – Connection con; // State starts as
                                    UnopenedState.
    con.open(); // Changes state internally.
    con.open();
• What’s the alternative, if we don’t use the State
  pattern?
   – class Connection {
         virtual void open() {
             if (state == OPEN) {
                 return;
             } else if (state == CLOSED) {
                 // Do stuff to open.
                 return;
             } else {
                 abort();
             }
         }
     };
• Consequences:
  – Localizes state-specific behavior into a class.
  – Makes state transitions very explicit.
  – Could essentially change the objects class at
    run-time, if the language allowed it.
  – The meta-point is that some patterns are to
    workaround limitations in static-typed
    languages.
Related “Aggregation” Patterns
• Composite
• Facade
• Mediator
        Facade (Object Structural)
• Suppose:
   – class A {
        public:
          void method1();
        private:
          int i;
          B b; // Need B.hpp header file?
     };
   – // client1.cpp
     // …
     A a;
     a.method1();
   – // client2.cpp
      // …
     A a;
     a.method1();
   – ... // Hundreds of users of A.
   – Suppose B is modified. How many files need to be recompiled?
• Some of the apps at Bloomberg take hours to compile.
• Solution?
• Intent
  – Provide a unified interface to a set of
    interfaces in a subsystem.
  – Defines a high level interface that makes the
    subsystem easier to use.
• Motivation
  – Sometimes you have a set of objects that
    make up a subsystem of some kind.
  – Now you need to expose the functionality of
    that subsystem. How?
• Suppose you are developing an IDE that includes a
  compiler:
   – Scanner, Parser, ProgramNode, BytecodeStream
       • Some clients might need access to these classes directly, but most
         do not want this complexity. Most just want to compile.
   – Create a single object to represent the subsystem, and hide the
     details behind that.
• Applicability
  – Provide simple interface to complex system.
    Applying patterns can create more classes.
  – Too many dependencies between clients and
    implementation classes. Gather into one
    place with the facade.
  – Layer subsystems. Define a facade for each
    layer.
  – Hide and decouple subsystem from clients.
• Structure
• Example:
  – class A {
      void detailed_func1();
    };
    class B {
      void detailed_func2();
    };
    class Facade {
      void simple_func1() {
        …; a->detailedfunc2(); …; }
      void simple_func2() {
        …; b->detailedfunc4(); …; }
      void simple_func3() {
        …; c->detailedfunc1(); …; }
    };
• Consequences/benefits
  – Shields clients from subsystem components, making
    the system easier to use.
  – Funnels all interaction from one set of classes to
    another set of classes through a single interface,
    making it easier to understand the relationship, and
    easier to make changes.
     • Can also use policy of allowing some direct use if needed.
  – Promotes weak coupling between clients and
    subsystem, making it easier to change the classes in
    the subsystem with affecting the clients.
     • Reduces compilation dependencies.
     Mediator (Object Behavioral)
• Intent: Define an object that encapsulates how a
  set of objects interact. Mediators promote loose
  coupling by keeping objects from referring to
  each other explicitly, and it lets you vary their
  interaction independently of the objects.
• Motivation
  – In structured programming, the behavior is “primary”.
    You have code that does stuff to data structures. You
    break up the behavior into prodedures.
  – Object oriented design encourages the distribution of
    behavior to the object methods. You divide the
    behavior up into methods. Each object has some
    methods. The behavior gets distributed.
  – Is this good or bad?
– Monster and human fighting. Where does this code
  go?
   • if (monster_swings) {
       if (monster_is_invisible) {
         …
       } else {
         if (human_limping) {
         …
     }
– Often you have a set of objects that interact, but you
  don’t really want the encode the interaction patterns
  into the objects.
   • It can be hard to see what is actually going on, because the
     code is scattered around.
– Solution is to use an mediator. You can also think of it
  as a coordinator, or manager also.
• Factor out coordination between a set of
  objects into a coordinator object.
• Example: Dialog boxes have a lot of
  dependencies. For example, if one radio
  button is selected, a list box is grayed out.
  How do we encapsulate all these
  dependencies?
  – We could subclass and add to various
    methods.
• Example
  – Consider an application to handle book purchases.
     •   Check inventory.
     •   Check shipping method.
     •   Authorize credit card.
     •   Send to shipper.
     •   Charge credit card.
     •   Update order information page.
  – If you spread out all this logic in the objects, it is hard
    to:
     •   Easily see the steps.
     •   Easily debug the steps.
     •   Easily change the steps.
     •   Easily reuse the objects.
• Contrast with Observer pattern.
  – If a particular text box should be grayed when
    a radio button is selected, you could make the
    text box an Observer of the radio button.
  – Compare and contrast.
              Chain Based
• Observer
  – Notify set of observers when state changes.
• Chain of Responsibility
  – Decouple sender of requests from which
    object actually handles it.
• Command
  – Decouple the code that is responsible for
    organizing and firing off commands from the
    actual implementation of the command.
           Chain Of Responsibility
            (Object Behavioral)
• 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.
• Motivation
   – Consider a context-sensitive help facility. You have buttons
     nested inside dialogs, inside applications. The help may be
     handled at any level.
   – The help that is delivered depends on the part of the interface,
     like a button, and the context. For example, an OK button in a
     dialog box might have different help from a button in the main
     window.
 – It’s natural to organize the help information from most specific to
   most general. Where it is handled depends on what is available.
      • We would like to be able to change the behavior just by changing a
        configuration file.
 – The problem is that the object that initiates the help doesn’t know
   which object is finally going to handle the help.
 – Idea is to decouple senders and receivers by giving multiple
   objects a chance to handle a request. The request is passed
   along a chain.


                            aSaveDialog
                            handler                        anApplication
aPrintButton
                                                           handler
handler                      aPrintDialog
                             handler
anOKButton
 handler
                           aSaveDialog
                            handler                     anApplication
 aPrintButton
                                                         handler
  handler                   aPrintDialog
                            handler
  anOKButton
  handler



   – First object either handles it or passes it on. The request has an
     implicit receiver.
   – What is the sequence diagram if the user clicks on aPrintButton?
• Applicability: Use when
   – More than one object may handle a request, and the handler is
     not known a priori.
   – You want to issue a request to one of several objects without
     specifying the receiver explicitly.
   – the set of objects that can handle a request should be specified
     dynamically.
• Consequences: Benefits and liabilities.
  – Reduced coupling.
  – Added flexibility in assigning responsibilities. Easy to
    do at run-time.
  – Receipt is not guaranteed. Could fall of the end.
• Implementation issues:
  – Should the chain be done using new links just for this
    chain of responsibility, or existing links?
     • If there already is a tree, for example, could use just that.
       What is the consequence of using an existing set of links?
– Connecting successors:
  • Can use a base class that derived classes can
    override:
     – class HelpHandler {
         public:
           HelpHandler(HelpHandler *n) : next(n)
                                            {}
           virtual void HandleHelp() {
             if (next != 0) {
               next->HandleHelp();
             }
           }
         private:
           HelpHandler *next;
       };
– Representing requests
  • Could use the method name.
  • Could use a single handler function that took a
    code.
  • Could use a request object.
     – void Handler::HandleRequest(Request *req) {
         if (typeid(*req) == typeid(PrintRequest)) {
           PrintRequest *pr
                  = dynamic_cast<PrintRequest *>(req);
           assert(req != 0);
           // …
         }
       }
                   Command
               (Object Behavioral)
• Intent
   – Encapsulate a request as an object, thereby letting you
     parameterize clients with different requests, queue or log
     requests, and support undoable operations.
   – Also bind the action to the receiver. In other words, the object
     contains both the action and the recipient of the action.
   – An example of how to use a functor.
• Motivation
   – Suppose you have a GUI, with menu items. Each menu item has
     a different action. But your menu code should be independent of
     the actual action.
   – Encapsulate the action as a command, which is passed to the
     MenuItem when it is created.
      – Encapsulate the action as a command.
                               class PrintAction : public
                               Action {
                                 Print(Doc *d) : doc(d) {}
class Menu {
                                 virtual void execute() {
   void addMenuItem(MenuItem *);
                                   doc->print();
};
                                 }
class MenuItem {
                                 private:
   MenuItem(Action *a)
                                   Doc *doc;
      : action(a) {}
                               }
   void clicked() {
     action->execute();
                               void NewDoc() {
   }
                                 Menu *menu = new Menu;
};
                                 PrintAction *act
class Action {
                                        = new PrintAction(doc);
   virtual void execute();
                                 MenuItem *mi
};
                                         = new MenuItem(act);
                                 menu->addItem(mi);
                               }
• Applicability: Use when you want to
  – Parameterize objects (such as the MenuItem)
    by the action to perform. Similar to a callback
    function, except we are using an object.
– Specify, queue, and execute requests at
  different times. Can decouple when the
  request was created from when to execute it.
  • Suppose your character has been poisoned.
     – BadPotion::quaffed() {
         PotionEffect *eff
            = new BadPotionEffect(severity, delay);
         character->queueEffect(eff);
       }
       Player::TimeStep() {
         nextEffect = effects->removeNextEffect();
         nextEffect->execute();
       }
– Supporting undo. Each command can now
  also have an undo() method. You can then
  maintain a list of the past N commands.
– Support logging easily. Each command can
  write to a log.
• Consequences
  – Actions are now first class objects. Can be
    subclassed, use multiple-inheritance, etc.
  – Commands can be assembled into a
    composite command.
  – Easy to add new commands. You can do it
    without changing your menu system at all, for
    example.
• Implementation issues:
  – How intelligent/complex should the action be?
    • It could actually just do it, or it could call a method
      on the receiver.
       – PrintAction::execute() {
           Printer *p = … ;
           PCL *pcl = genPCL(doc);
           p->send(pcl);
         }
       – PrintAction::execute() {
           doc->print();
         }
• Example
  – class Command {
    public:
        virtual ~Command();
        virtual void Execute() = 0;
    protected:
        Command();
    };
    class Paste : public Command {
    public:
        PasteCommand(Doc *);
        virtual void Execute();
    private:
        Doc *doc;
    };
    void Paste::Execute() { doc->Paste(); }
               Miscellaneous
• Flyweight
  – Factor out some state into context that is always used
    when methods are invoked.
• Memento
  – Object persistence
• Singleton
• Strategy
  – The “way” to do something is hidden in a strategy
    object. For example, how to break up lines.
• Template Method
  – The overall “template” of an operation is in the base
    class. Some steps are implementation specific, and
    handled in derived classes via virtual functions.
                  Flyweight
              (Object Structural)
• Intent
  – Use sharing to support large numbers of fine-grained
    objects efficiently.
• Motivation
  – Suppose you are writing a text editor. It is very
    convenient if you can treat every character in the file
    as an object.
     • Every character has a column, a row, a font, a color, a font
       size, a font style.
     • How much memory?
  – A way of factoring state, as opposed to functionality.
     • Separate into extrinsic and intrinsic.
     • Operations then need a context.
• Example
  – How to avoid storing a lot of properties with
    each character.
  – class Char {
        …
        void draw(const Context &);
        char c;
    };
    class Context {
        void setFont(…);
        void setColor(…);
        …
    };
    Char c(‘a’);
    Context ctx;
    ctx.setFont(…);
    c.draw(ctx);
• Variation 1
  – Suppose you are writing a game. The game
    grid is very fine-grained. Each world has 100
    million cells.
  – At each cell, there are many properties, like
    terrain, weather, etc. Takes 100 bytes each
    cell.
  – But the terrain is grouped into regions, so two
    neighboring cells very likely have the same
    terrain.
• A solution
  – class Cell {
        public:
            Terrain *getTerrain() {
                 return
                       world->lookupTerrain(x, y); }
        private:
            int x, y;
    };
    Terrain *World::lookupTerrain(int x, int y) {
        if (x > 50) {
            return mountain;
        } else {
            return plains;
        }
    }
  – So it appears that Terrain is stored with every cell.
                Memento
           (Object Behavioral)
• Intent
  – Snapshot the state of an object into another
    object, such that it can be restored easily.
• Example
  – class MyClass {
         Memento *snapshot();
    };
    class Memento {
         MyClass *restore();
         // Or, restore(MyClass *);
    };
                Singleton
            (Object Creational)
• Intent
  – Ensure that a class only has one instance, and
    provide a global point of access to it.
• Motivation
  – Often you will have classes for which there should
    only be one instance. For example, if you have a
    single node manager in a system, there should only
    be one instance of NodeManager.
  – A global variable can be used, but doesn’t prevent
    you from accidentally creating more than one.
• How to implement this?
  – class Singleton {
        public:
           static Singleton *instance();
        protected:
           Singleton();
        private:
           static Singleton *_instance;
    };
    Singleton *Singleton::instance() {
        if (_instance == 0) {
           _instance = new Singleton;
        }
        return _instance;
    }
  – Is this thread safe?
• Implementation:
  – May be useful to have a registry of singletons.
  – May be useful to allow more than one, but
    some limited number.
  – How can this be implemented with templates?
                Interpreter
            (Class Behavioral)
• Intent: Given a language, define a
  representation for its grammar along with
  an interpreter that uses the representation
  to interpret sentences in the language.
• Motivation
  – Suppose you have a 3D, fantasy role-playing
    game, and you have different magical spells.
     • For each spell, you have a different on-screen
       animation.
     • How would you code this?
• class LightningSpell : public Spell {
    virtual void animate() {
      extractWand();
      raiseArms(/* Height */ 10);
      waveArms(/* Speed, Height */ 1, 5);
      …
    }
    virtual void cast() {
      monster = find_hit(direction);
      monster->damager();
  };
• How convenient is this? How dynamic? How are
  bug fixes delivered?
• Options?
– Instead, encode the spell as data to your
  program. Then have your program process
  the data as commands. This is essentially an
  interpeter.
   • # In a data file.
     spell:
       name = lightning
       animation = {
         extractWand
         raiseArms 10
         waveArms 1 5 }
   • void Action::executeSpell(char *data) {
       …
     }
– Other uses for an interpreter?
Summary
• Factory related
  – Abstract Factory
     • An object with factory methods.
  – Factory Method
     • A method within an object that is subclassed.
  – Builder
     • An object to which you feed a sequence of things
       to it, then get the result in the end.
  – Prototype
     • Another way of creating objects via a clone()
       method.
  – Singleton
• Traversing structures
  – Iterator
     • Essentially an object that functions as a pointer,or
       cursor. It has a current element that it points to,
       and methods to advance to the next element.
  – Visitor
     • For data structures that are heterogeneous. Factor
       out the traversal code, and as you traverse the
       structure, make callbacks to a visitor object that is
       carried along the traversal.
• Wrapper-related
  – Adapter
     • What if two objects are similar in functionality, but have
       different interfaces?
  – Bridge
     • How do you divide functionality into two layers, so that you
       can vary each independently.
  – Decorator (same interface)
     • A wrapper that adds functionality, but keeps the interface.
  – Proxy (same interface)
     • A wrapper that “stands-in” for the real thing.
  – State
     • A wrapper around state-specific implementations. Could be
       same interface or not.
• Chain-related
  – Observer
    • Notify set of observers when state changes.
  – Chain of Responsibility
    • Decouple sender of requests from which object
      actually handles it.
  – Command
    • Decouple the code that is responsible for
      organizing and firing off commands from the actual
      implementation of the command.
• Miscellaneous
  – Flyweight
     • Factor out some state into context that is always used when
       methods are invoked.
  – Memento
     • Object persistence
  – Strategy
     • The “way” to do something is hidden in a strategy object. For
       example, how to break up lines.
  – Template Method
     • The overall “template” of an operation is in the base class.
       Some steps are implementation specific, and handled in
       derived classes via virtual functions.
  – Interpreter
     • Make code no longer hard-coded, but rather move to data,
       then execute the data.

				
DOCUMENT INFO