C++ Programming/Code/Design Patterns/Behavioral Patterns

From Wikibooks, the open-content textbooks collection

Jump to: navigation, search

Contents

[edit] Behavioral Patterns

[edit] Chain of Responsibility

Chain of Responsibility pattern has the intent to avoid coupling the sender of a request to its receiver by giving more then one object a chance to handle the request. Chains the receiving objects and passes the requests along the chain until an object handles it.

[edit] Command

Command pattern is an Object behavioral pattern that decouples sender and receiver by encapsulating a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. It can also be thought as an object oriented equivalent of call back method.

Call Back: It is a function that is registered to be called at later point of time based on user actions.

[edit] Interpreter

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

[edit] Iterator

The 'iterator' design pattern is used liberally within the STL for traversal of various containers. The full understanding of this will liberate a developer to create highly reusable and easily understandable data containers.

The basic idea of the iterator is that it permits the traversal of a container (like a pointer moving across an array). However, to get to the next element of a container, you need not know anything about how the container is constructed. This is the iterators job. By simply using the member functions provided by the iterator, you can move, in the intended order of the container, from the first element to the last element.

Let's start by considering a traditional single dimensional array with a pointer moving from the start to the end. This example assumes knowledge of pointer arithmetic. Note that the use of "it" or "itr," henceforth, is a short version of "iterator."

 const int ARRAY_LEN = 42;
 int *myArray = new int[ARRAY_LEN];
 // Set the iterator to point to the first memory location of the array
 int *arrayItr = myArray;
 // Move through each element of the array, setting it equal to its position in the array
 for(int i = 0; i < ARRAY_LEN; ++i)
 {
    // set the value of the current location in the array
    *arrayItr = i;
    // by incrementing the pointer, we move it to the next position in the array.
    // This is easy for a contiguous memory container, since pointer arithmetic 
    // handles the traversal.
    ++arrayItr;
 }
 // Don't be messy, clean up after yourself
 delete[] myArray;

This code works very quickly for arrays, but how would we traverse a linked list, when the memory is not contiguous? Consider the implementation of a rudimentary linked list as follows:

TODO

TODO
test compiling this, check for syntax errors.

 class IteratorCannotMoveToNext{}; // Error class
 class MyIntLList
 {
 public:
     // The Node class represents a single element in the linked list. 
     // The node has a next node and a previous node, so that the user 
     // may move from one position to the next, or step back a single 
     // position. Notice that the traversal of a linked list is O(N), 
     // as is searching, since the list is not ordered.
     class Node
     {
     public:
         Node():mNextNode(0),mPrevNode(0),mValue(0){}
         Node *mNextNode;
         Node *mPrevNode;
         int mValue;
     };
     MyIntLList():mSize(0) 
     {}
     ~MyIntLList()
     {
         while(!Empty())
             pop_front();
     } // See expansion for further implementation;
     int Size() const {return mSize;}
     // Add this value to the end of the list
     void push_back(int value)
     {
         Node *newNode = new Node;
         newNode->mValue = value;
         newNode->mPrevNode = mTail;
         mTail->mNextNode = newNode;
         mTail = newNode;
         ++mSize;
     }
     // Remove the value from the beginning of the list
     void pop_front()
     {
         if(Empty())
             return;
         Node *tmpnode = mHead;
         mHead = mHead->mNextNode
         delete tmpnode;
         --mSize;
     }
     bool Empty()
     {return mSize == 0;}
 
     // This is where the iterator definition will go, 
     // but lets finish the definition of the list, first
 
 private:
     Node *mHead;
     Node *mTail;
     int mSize;
 };

This linked list has non-contiguous memory, and is therefore not a candidate for pointer arithmetic. And we dont want to expose the internals of the list to other developers, forcing them to learn them, and keeping us from changing it.

This is where the iterator comes in. The common interface makes learning the usage of the container easier, and hides the traversal logic from other developers.

Let's examine the code for the iterator, itself.

     /*
      *  The iterator class knows the internals of the linked list, so that it 
      *  may move from one element to the next. In this implementation, I have 
      *  chosen the classic traversal method of overloading the increment 
      *  operators. More thorough implementations of a bi-directional linked 
      *  list would include decrement operators so that the iterator may move 
      *  in the opposite direction.
      */
     class Iterator
     {
     public:
         Iterator(Node *position):mCurrNode(position){}
         // Prefix increment
         const Iterator &operator++()
         {
             if(mCurrNode == 0 || mCurrNode->mNextNode == 0)
                 throw IteratorCannotMoveToNext();e
             mCurrNode = mCurrNode->mNextNode;
             return *this;
         }
         // Postfix increment
         Iterator operator++(int)
         {
             Iterator tempItr = *this;
             ++(*this);
             return tempItr;
         }
         // Dereferencing operator returns the current node, which should then 
         // be dereferenced for the int. TODO: Check syntax for overloading 
         // dereferencing operator
         Node * operator*()
         {return mCurrNode;}
         // TODO: implement arrow operator and clean up example usage following
     private:
         Node *mCurrNode;
     };
     // The following two functions make it possible to create 
     // iterators for an instance of this class.
     // First position for iterators should be the first element in the container.
     Iterator Begin(){return Iterator(mHead);}
     // Final position for iterators should be one past the last element in the container.
     Iterator End(){return Iterator(0);}

With this implementation, it is now possible, without knowledge of the size of the container or how its data is organized, to move through each element in order, manipulating or simply accessing the data. This is done through the accessors in the MyIntLList class, Begin() and End().

 // Create a list
 MyIntLList mylist;
 // Add some items to the list
 for(int i = 0; i < 10; ++i)
     myList.push_back(i);
 // Move through the list, adding 42 to each item.
 for(MyIntLList::Iterator it = myList.Begin(); it != myList.End(); ++it)
     (*it)->mValue += 42;
TODO

TODO

  • Discussion of iterators in the STL, and the usefulness of iterators within the algorithms library.
  • Iterators best practices
  • Warnings on creation of and usage of

[edit] Mediator

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

[edit] Memento

Without violating encapsulation the memento Pattern will capture and externalize an object’s internal state so that the object can be restored to this state later. Though the Gang of Four uses friend as a way to implement this pattern it is not the best design. It can also be implemented using PIMPL. Best Use case is 'Undo-Redo' in an editor.

[edit] Observer

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Problem 
In one place or many places in the application we need to be aware about a system event or an application state change. We'd like to have a standard way of subscribing to listening for system events and a standard way of notifying the interested parties. The notification should be automated after an interested party subscribed to the system event or application state change. There also should be a way to unsubscribed.
Forces 
Observers and observables probably should be represented by objects. The observer objects will be notified by the observable objects.
Solution 
After subscribing the listening objects will be notified by a way of method call.

[edit] State

The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear as having changed its class.

[edit] Strategy

Defines a family of algorithms, encapsulates each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients who use it.

[edit] Template Method

By defining a skeleton of an algorithm in an operation, deferring some steps to subclasses, the Template Method lets subclasses redefine certain steps of that algorithm without changing the algorithms structure.

[edit] Visitor

The Visitor Pattern will represent an operation to be performed on the elements of an object structure by letting you define a new operation without changing the classes of the elements on which it operates.

[edit] Model-View-Controller (MVC)

pattern often used by applications that need the ability to maintain multiple views of the same data.