sse658.1


 * Course:** SSE658
 * Project:** 1
 * Subject:** Design Patterns
 * Student:** Dmitriy Slipak
 * E-mail:** dslipak@gmail.com

=Table Of Content=

Preface Introduction Documenting Design Patterns Design Problems and Design Patterns Design Patterns Criticism Design Patterns Known Issues Observer Pattern Singleton Pattern Factory Method Pattern Decorator Pattern Command Pattern Strategy Pattern Conclusion

 =Preface=

This report is my overview of some well-known design patterns in object-oriented software. I selected following patterns to be reviewed: Factory Method, Strategy, Singleton, Decorator, Observer, and Command. My decision for this selection based on my personal interest. Those patterns in my opinion are most used in software development. In my previous experience I used Singleton and Adapter patterns. This is the reason why I am not considering Adapter pattern for this report. But I will do overview of the Singleton pattern even though I used it before. The Singleton pattern took my attention since I found some different way of its implementation.

This report is also my first report delivered entirely via wiki. I always prefer HTML format over standard "doc" format. This is my personal preference. And now I am glad I have opportunity to create nice reports and share it with my classmates. I hope my reports will be not only demonstrate my abilities in different subjects, but will be helpful to others.

The supporting material for this report is a Microsoft Visual C++ Express Edition solution, containing several projects, each one related to particular pattern. It can be found on course FTP server, under my folder. The C++ code in projects is straight-forward and should be understandable by anyone who has previous experience in programming languages with OO support.

 =Introduction=

Object-oriented(further OO) software design is a complex and hard process. One of the major aspects and purposes of object-oriented software is code reuse. The process of designing well structured, reusable OO software even harder. Design patterns make it easier to reuse successful designs and architectures. Expressing proven techniques as design patterns makes them more accessible to developers of systems. Design patterns help to choose design alternatives that make a system reusable and avoid alternatives that compromise reusability. Design patterns can improve the maintenance of existing system.

Patterns originated as an architectural concept by Christopher Alexander. Based on this concept he released "A Pattern Language: Towns, Buildings, Construction" book (1977/79) with Sara Ishikara and Murray Silverstain as co-authors. Alexander explains patterns as follows: "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". This statement is a platform to the design patterns definition from wikipedia: "In software engineering, a design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not 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. Object-oriented design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved."

In general, a pattern has four essential elements:


 * 1) The **pattern name**, which can be used to describe a design problem, its solution, and consequences in a word or two.
 * 2) The **problem**, which describes when to apply the pattern. It explains the problem and its context. It might describe specific design problems such as how to represent algorithms as objects. It might describe class or object structures that are symptomatic of an inflexible design.
 * 3) The **solution**, which describes the elements that make up the design, their relationships, responsibilities, and collaborations.
 * 4) The **consequences** are the result and trade-offs of applying the pattern. The consequences of a pattern include its impact on a system's flexibility, extensibility, or portability.

Although, design patterns describe OO design, they are based on practical solutions that have been implemented in mainstream OO programming languages such as Smalltalk, C++, Java.  =Documenting Design Patterns=

It might seams to be difficult to describe design patterns. Moreover, there is no standard format for documenting design patterns. I prefer documenting design patterns specified by GoF They established following topics to describe design patterns:


 * **Pattern Name and Classification**

> The pattern's name conveys the essence of the pattern succinctly.


 * **Intent**

> A short element that answers the following questions: What does the design pattern do? What is its rationale and intent? What particular design issue or problem does it address?


 * **Also Known As**

> Other well-known names for the pattern.


 * **Motivation**

> A scenario that illustrates a design problem and how the class and object structures in the pattern solve the problem.


 * **Applicability**

> Situations in which the design pattern can be applied.


 * **Structure**

> A graphical representation of the classes in the pattern using a notation based on the Object Modeling Technique (OMT).


 * **Participants**

> The classes and/or objects participating in the design pattern and their responsibilities.


 * **Collaborations**

> How the participants collaborate to carry out their responsibilities.


 * **Consequences**

> How does the pattern support its objectives? What are the trade-offs and results of using the pattern?


 * **Implementation**

> What pitfalls, hints, or techniques should you be aware of when implementing the pattern?


 * **Sample Code**

> Code fragments that illustrate how we might implement the pattern in specific language.


 * **Known Uses**

> Examples of the pattern found in real systems.


 * **Related Patterns**

> What design patterns are closely related to this one? What are important differences? With which other patterns should this one be used?

I will not follow in the report exactly to specification above, but partially.  =Design Problems and Design Patterns=

Design patterns solve problems of OO design. Here are few of them and how design patterns can solve these problems.


 * //Finding Appropriate Objects//**

The hard part of OO design is decomposing a software into objects. The task is difficult because many factors come into play: encapsulation, granularity, dependency, flexibility, performance, evolution, reusability, etc. They all affect the decomposition. Design patterns help to identify less-obvious abstractions and the objects that can capture them.


 * //Object Granularity//**

Objects can vary in size and number. They can represent everything down to the hardware or all the way up to entire applications. Design patterns describe how to support huge number of objects at the fines granularity. Design patterns also describe specific ways of decomposing an object into smaller objects.


 * //Object Interfaces//**

Interfaces are fundamental in OO software. Objects are known only via their interfaces. But when dynamic binding come into play it means that issuing object request doesn't commit to a particular implementation until run-time. Design patterns help to define interfaces by identifying their key elements and the kinds of data that get sent across an interface. Design patterns also specify relationships between interfaces. In particular, they often require some classes to have similar interfaces, or they place constraints on the interfaces of some classes.


 * //Object Implementations//**

Inheritance gives ability to define families of objects with identical interfaces (by inheriting from an abstract class). It is very important concept since polymorphism has dependency on it. One of the major OO design principles is program to an interface, not an implementation. Design patterns help to instantiate concrete classes (which specified a particular implementation). By abstracting the process of an object creation, patterns give different ways to associate an interface with its implementation transparently at instantiation.


 * //Run-Time and Compile-Time Structures//**

It's easy to confuse object aggregation and object acquaintance, since they are often implemented identically. Object aggregation implies that one object owns or is responsible for another object. Acquaintance implies that an object merely knows of another object. The distinction between aggregation and acquaintance may be hard to see in the compile-time. Design patterns capture the distinction between compile-time and run-time structures explicitly.


 * //Designing for Change//**

Depending on software design it may be difficult to apply changes in the future. Design patterns help to ensure that a system can change in specific way.  =Design Patterns Criticism=

By ignoring people, who seams to have strange opinion on programming languages comparison there are few topics that might be considered as reasonable design patterns criticism.  =Design Patterns Known Issues=

It's might be hard to find a proper structure for particular pattern. Patterns encourage chunks, and it's easy to concentrate on chunks. By concentrating on chunks it's easy to get lost and move away from something meaningful.

An attempt to write a design pattern as flexible as possible may cause growing the code in size. It's better to write few small patterns instead of one which combines all the features.  =Observer Pattern=


 * //Classification//**

Object Behavioral 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.


 * //Motivation//**

A common side-effect of partitioning a system into a collection of cooperating classes is the need to maintain consistency between related objects. It's a bad idea to achieve consistency by making the classes tightly coupled, because that reduces their reusability.

There are number of situations when multiple objects are dependent on the data object and should be notified of any change in its state. And there's no reason to limit the number of dependent objects to two. There may be any number of different user interfaces to the same data.

The Observer pattern describes how to establish these relationships. The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notified whenever the subject undergoes a change in state. In response, each observer will query the subject to synchronize its state with the subject's state. This kind of interaction is also known as publish-subscribe. The subject is the publisher of notifications. It sends out these notifications without having to know who its observers are. Any number of observers can subscribe to receive notifications.

The Observer pattern lets us vary subjects and observers independently. You can reuse subjects without reusing their observers, and vice versa. It lets you add observers without modifying the subject or other observers.


 * //Applicability//**

We can use the Observer pattern in one of the following situations:


 * When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.


 * When a change to one object requires changing others, and you don't know how many objects need to be changed.


 * When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.


 * //Structure//**


 * //Participants//**


 * **Subject** - knows its observers. Any number of Observer objects may observe a subject. Provides an interface for attaching and detaching Observer objects.


 * **Observer** - defines an updating interface for objects that should be notified of changes in a subject.


 * **ConcreteSubject** - stores state of interest to ConcreteObserver objects; sends a notification to its observers when its state changes.


 * **ConcreteObserver** - maintains a reference to a ConcreteSubject object; stores state that should stay consistent with the subject's; implements the Observer updating interface to keep its state consistent with the subject's.


 * //Advantages//**


 * **Abstract coupling between Subject and Observer**. All a subject knows is that it has a list of observers, each conforming to the simple interface of the abstract Observer class. The subject doesn't know the concrete class of any observer. Thus the coupling between subjects and observers is abstract and minimal.

> Because Subject and Observer aren't tightly coupled, they can belong to different layers of abstraction in a system. A lower-level subject can communicate and inform a higher-level observer, thereby keeping the system's layering intact. If Subject and Observer are lumped together, then the resulting object must either span two layers (and violate the layering), or it must be forced to live in one layer or the other (which might compromise the layering abstraction).


 * **Support for broadcast communication**. Unlike an ordinary request, the notification that a subject sends needn't specify its receiver. The notification is broadcast automatically to all interested objects that subscribed to it. The subject doesn't care how many interested objects exist; its only responsibility is to notify its observers. This gives us the freedom to add and remove observers at any time. It's up to the observer to handle or ignore a notification.


 * //Disadvantages//**


 * **Unexpected updates**. Because observers have no knowledge of each other's presence, they can be blind to the ultimate cost of changing the subject. A seemingly innocuous operation on the subject may cause a cascade of updates to observers and their dependent objects. Moreover, dependency criteria that aren't well-defined or maintained usually lead to spurious updates, which can be hard to track down.


 * //Implementation//**

We have to consider the following issues during the Observer pattern implementation:


 * **Mapping subjects to their observers**. The simplest way for a subject to keep track of the observers it should notify is to store references to them explicitly in the subject. However, such storage may be too expensive when there are many subjects and few observers. One solution is to trade space for time by using an associative look-up (e.g., a hash table) to maintain the subject-to-observer mapping. Thus a subject with no observers does not incur storage overhead. On the other hand, this approach increases the cost of accessing the observers.


 * **Observing more than one subject**. It might make sense in some situations for an observer to depend on more than one subject. For example, a spreadsheet may depend on more than one data source. It's necessary to extend the Update interface in such cases to let the observer know which subject is sending the notification. The subject can simply pass itself as a parameter in the Update operation, thereby letting the observer know which subject to examine.


 * **Who triggers the update?** The subject and its observers rely on the notification mechanism to stay consistent. But what object actually calls Notify to trigger the update? Here are two options:

> a. Have state-setting operations on Subject call Notify after they change the subject's state. The advantage of this approach is that clients don't have to remember to call Notify on the subject. The disadvantage is that several consecutive operations will cause several consecutive updates, which may be inefficient.

> b. Make clients responsible for calling Notify at the right time. The advantage here is that the client can wait to trigger the update until after a series of state changes has been made, thereby avoiding needless intermediate updates. The disadvantage is that clients have an added responsibility to trigger the update. That makes errors more likely, since clients might forget to call Notify.


 * **Dangling references to deleted subjects**. Deleting a subject should not produce dangling references in its observers. One way to avoid dangling references is to make the subject notify its observers as it is deleted so that they can reset their reference to it. In general, simply deleting the observers is not an option, because other objects may reference them, or they may be observing other subjects as well.


 * **Making sure Subject state is self-consistent before notification**. It's important to make sure Subject state is self-consistent before calling Notify, because observers query the subject for its current state in the course of updating their own state.


 * **Avoiding observer-specific update protocols: the push and pull models**. Implementations of the Observer pattern often have the subject broadcast additional information about the change. The subject passes this information as an argument to Update. The amount of information may vary widely.

> At one extreme(push model), the subject sends observers detailed information about the change, whether they want it or not. At the other extreme is the pull model; the subject sends nothing but the most minimal notification, and observers ask for details explicitly thereafter. The pull model emphasizes the subject's ignorance of its observers, whereas the push model assumes subjects know something about their observers' needs.

> The push model might make observers less reusable, because Subject classes make assumptions about Observer classes that might not always be true. On the other hand, the pull model may be inefficient, because Observer classes must ascertain what changed without help from the Subject.


 * **Specifying modifications of interest explicitly**. We can improve update efficiency by extending the subject's registration interface to allow registering observers only for specific events of interest. When such an event occurs, the subject informs only those observers that have registered interest in that event.


 * **Encapsulating complex update semantics**. When the dependency relationship between subjects and observers is particularly complex, an object that maintains these relationships might be required. Its purpose is to minimize the work required to make observers reflect a change in their subject.


 * //Example//**

I created the Observer pattern where observer can subscribe to multiple subjects.

code format="C++" // Module:       observer.h // Programmer:    Dmitriy Slipak // Date:       January 31, 2010 // Purpose: //               Header file, //               contains observer pattern classes declaration //
 * Module** observer.h
 * 1) ifndef _OBSERVER_H_
 * 2) define _OBSERVER_H_


 * 1) include

class Subject;

class Observer { public: virtual void update(Subject* s) = 0; };

class Subject { private: std::list observers; std::string message;

public: void set_message(std::string m); std::string get_message;

virtual void subscribe(Observer* o); virtual void unsubscribe(Observer* o); virtual void notify; };

code
 * 1) endif

code format="C++" // Module:       transport.h // Programmer:    Dmitriy Slipak // Date:       January 31, 2010 // Purpose: //               Header file, //               contains transportation related classes declaration // //
 * Module** transport.h
 * 1) ifndef _TRANSPORT_H_
 * 2) define _TRANSPORT_H_


 * 1) include
 * 2) include "observer.h"

class Vehicle : public Observer { protected: std::list subjects;

public: void subscribe(Subject*); void update(Subject* s); virtual void confirm(Subject* s) = 0; };

class Airplane : public Vehicle { public: void confirm(Subject* s); };

class Boat : public Vehicle { public: void confirm(Subject* s); };

class Car : public Vehicle { public: void confirm(Subject* s); };

class Dispatcher : public Subject { public: void inform; };

class Manager : public Subject { public: void inform; };

code
 * 1) endif

code format="C++" // Module:       observer.cpp // Programmer:   Dmitriy Slipak // Date:       January 31, 2010 // Purpose: //               contains observer classes implementation //
 * Module** observer.cpp
 * 1) include "observer.h"

void Subject::set_message(std::string m) { message = m; } std::string Subject::get_message { return message; }

void Subject::subscribe(Observer* o) { observers.push_back(o); } void Subject::unsubscribe(Observer* o) { observers.remove(o); }

void Subject::notify {   std::list::iterator iter;

for(iter=observers.begin; iter != observers.end; ++iter) ((Observer*)*iter)->update(this); } code

code format="C++" // Module:       transport.cpp // Programmer:   Dmitriy Slipak // Date:       January 31, 2010 // Purpose: //               contains transportation hierarchy implementation //
 * Module** transport.cpp
 * 1) include "transport.h"

void Vehicle::subscribe(Subject* s) { subjects.push_back(s); s->subscribe(this); }

void Vehicle::update(Subject* s) { std::list::iterator iter;

for(iter=subjects.begin; iter != subjects.end; ++iter) { if (s == (Subject*)* iter) confirm(s); } }

void Airplane::confirm(Subject* s) { std::cout << "Pilot: confirmed -> " << s->get_message.c_str << '\n'; }

void Boat::confirm(Subject* s) { std::cout << "Captain: confirmed -> " << s->get_message.c_str << '\n'; }

void Car::confirm(Subject* s) { std::cout << "Driver: confirmed -> " << s->get_message.c_str << '\n'; }

void Dispatcher::inform { notify; }

void Manager::inform { notify; } code

code format="C++" Dispatcher* d = new Dispatcher; Manager* m = new Manager; Airplane* a = new Airplane; Boat* b = new Boat; Car* c = new Car;
 * Test run**

a->subscribe(d); a->subscribe(m);

b->subscribe(d); c->subscribe(d);

d->set_message("message from dispatcher"); d->inform;

m->set_message("message from manager"); m->inform;

delete d; delete m; delete a; delete b; delete c; code

In this example, Airplane(observer) will subscribe to both Dispatcher and Manager subjects. Here is the result of test run  =Singleton Pattern=


 * //Classification//**

Creational Pattern


 * //Intent//**

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


 * //Motivation//**

Sometimes it's important for some of classes to have exactly one instance. For instance, in my vehicle examples can be multiple airplanes, but there is only one JFK Airport in the world. The Singleton pattern makes the class itself responsible for keeping track of its sole instance. The class can ensure that no other instance can be created, and it can provide a way to access the instance.


 * //Applicability//**

The Singleton pattern can be used when:


 * There should be exactly one instance of a class, and it must be accessible to clients from well-known access point.


 * The sole instance should be extensible by subclassing, and clients should be able to use an extended instance without code modifications.


 * //Structure//**


 * //Participants//**


 * **Singleton** – defines an instance operation that lets client access its unique instance. May be responsible for creating its own unique instance.


 * //Advantages//**


 * **Controlled access to sole instance**. Because the Singleton class encapsulates its sole instance, it can have strict control over how and when clients access it.


 * **Reduced name space**. The Singleton pattern is an improvement over global variables. It avoids polluting the name space with global variables that store sole instances.


 * **Permits refinement of operations and representation**. The Singleton class may be subclassed, and it's easy to configure an application with an instance of this extended class. You can configure the application with an instance of the class you need at run-time.


 * **Permits a variable number of instances**. The pattern makes it easy to change your mind and allow more than one instance of the Singleton class. Moreover, you can use the same approach to control the number of instances that the application uses. Only the operation that grants access to the Singleton instance needs to change.


 * **More flexible than class operations**. Another way to package a singleton's functionality is to use class operations (static member functions in C++).


 * //Disadvantages//**


 * **Static member functions limitations**. Static member functions make it hard to change a design to allow more than one instance of the class. Static member functions in C++ are never virtual, and this means subclasses can not override them polymorphically.


 * //Implementation//**

We have to consider the following issues during the Singleton pattern implementation:


 * **Ensuring a unique instance**. The Singleton pattern makes the sole instance a normal instance of a class, but that class is written so that only one instance can ever be created. A common way to do this is to hide the operation that creates the instance behind a class operation (that is, either a static member function or a class method) that guarantees only one instance is created. This operation has access to the variable that holds the unique instance, and it ensures the variable is initialized with the unique instance before returning its value. This approach ensures that a singleton is created and initialized before its first use.

code format="C++" class Singleton { private: static Singleton* instance;

protected: Singleton;

public: static Singleton* Instance; }; code

And the class above implementation will be as follows:

code format="C++" Singleton* Singleton::instance = 0;

Singleton* Singleton::Instance { if (instance == 0) instance = new Singleton;

return instance; } code

Here, clients access the singleton exclusively via the Instance member function. The variable "instance" is initialized to 0, and the static member function Instance returns its value, initializing it with the unique instance if it is NULL or 0. Default constructor is set to be protected, so client can not instantiate the Singleton directly.


 * **Subclassing the Singleton class**. The main issue is not so much defining the subclass but installing its unique instance so that clients will be able to use it. In essence, the variable that refers to the singleton instance must get initialized with an instance of the subclass. The simplest technique is to determine which singleton you want to use in the Singleton's Instance operation.

Another way to choose the subclass of Singleton is to take the implementation of Instance out of the parent class and put it in the subclass. That lets a C++ programmer decide the class of singleton at link-time (e.g., by linking in an object file containing a different implementation) but keeps it hidden from the clients of the singleton.

Members of GoF suggest a more flexible approach uses a registry of singletons. Instead of having Instance define the set of possible Singleton classes, the Singleton classes can register their singleton instance by name in a well-known registry.

The registry maps between string names and singletons. When Instance needs a singleton, it consults the registry, asking for the singleton by name. The registry looks up the corresponding singleton (if it exists) and returns it. This approach frees Instance from knowing all possible Singleton classes or instances. All it requires is a common interface for all Singleton classes that includes operations for the registry:

code format="C++" class Singleton { public: static void Register(const char* name, Singleton*); static Singleton* Instance;

protected: static Singleton* Lookup(const char* name);

private: static Singleton* _instance; static std::list* _registry; }; code

Where Register registers the Singleton instance under the given name. Each "NameSingletonPair" maps a name to a singleton. The Lookup operation finds a singleton given its name.

They also assume following implementation for the Instance member function:

code format="C++" Singleton:* Singleton::Instance { if (_instance == 0) { const char* singletonName = getenv(“SINGLETON”); _instance = Lookup(singletonName); }

return _instance; } code

They also propose Singleton derived classes registration in constructor:

code format="C++" MySingleton::MySingleton { Singleton::Register(“MySingleton”, this); } code

and constructor initialzation in the MySingleton class implementation file:

code format="C++" static MySingleton theSingleton; code

This implementation has some drawbacks. Sure it will put only one instance into singleton registry. But it allows to create as many instances of Singleton derived classes as we want. Another problem which can be undesirable at some point of development is that Singleton registers instances under the given name.

I propose following Singleton implementation which will register instances under an instance type. It also put restriction for instances of the Singleton derived classes. It allows only one instance. There is also no need to initialize derived classes in implementation file, since they will be registered in constructors. This implementation tide up to my standard Vehicle example. Complete code can be found in the Singleton example section of this report.

code format="C++" struct Transport { VEHICLE_TYPE type; Singleton* transport;

Transport(VEHICLE_TYPE ty, Singleton* tr) {   type = ty; transport = tr; } };

class Singleton { private: static Singleton* instance; static std::list* registry;

protected: static Singleton* find(VEHICLE_TYPE type); // the class can not be instantiated since ctor is protected

public: static void register_instance(VEHICLE_TYPE type, Singleton* instance); static Singleton* get_instance(VEHICLE_TYPE type); }; code

And here is Singleton's derived class:

code format="C++" class Boat : public Singleton { protected: Boat; // the class can not be instantiated since ctor is protected

public: ~Boat;

friend class Singleton; };

Boat::Boat { Singleton::register_instance(BOAT, this); } code


 * //Example//**

code format="C++"
 * Module** transport.h
 * 1) ifndef _TRANSPORT_H_
 * 2) define _TRANSPORT_H_


 * 1) include
 * 2) include

const enum VEHICLE_TYPE {AIRPLANE, BOAT, CAR, NONE};

class Vehicle { private: static Vehicle* instance;

protected: Vehicle { std::cout << "created new Vehicle object\n"; }

public: static Vehicle* get_instance; };

class Airplane : public Vehicle { public: Airplane; };

class MultiVehicle;

struct Transport {   VEHICLE_TYPE type; MultiVehicle* transport;

Transport(VEHICLE_TYPE ty, MultiVehicle* tr) {       type = ty; transport = tr; }

~Transport { std::cout << "Transport dtor\n"; }; };

class MultiVehicle { private: static MultiVehicle* instance; static std::list* registry;

protected: static MultiVehicle* find(VEHICLE_TYPE type);

public: ~MultiVehicle;

static void register_instance(VEHICLE_TYPE type, MultiVehicle* instance); static MultiVehicle* get_instance(VEHICLE_TYPE type); };

class Boat : public MultiVehicle { protected: Boat;

public: ~Boat;

friend class MultiVehicle; };

class Car : public MultiVehicle { protected: Car;

public: ~Car;

friend class MultiVehicle; };

code
 * 1) endif

code format="C++"
 * Module** transport.cpp
 * 1) include "transport.h"

Vehicle* Vehicle::instance = 0;

Vehicle* Vehicle::get_instance {   if (instance == 0) instance = new Vehicle;

return instance; }

Airplane::Airplane {   std::cout << "created new Airplane object\n"; }

//   MultiVehicle implementation MultiVehicle::~MultiVehicle {   delete registry; }

MultiVehicle* MultiVehicle::instance = 0; std::list* MultiVehicle::registry = new std::list;

MultiVehicle* MultiVehicle::get_instance(VEHICLE_TYPE type) {   if (instance == 0) { if (type == BOAT) instance = new Boat; if (type == CAR) instance = new Car; register_instance(type, instance); } else instance = find(type);

/*if (instance == 0) instance = find(type);*/

return instance; }

void MultiVehicle::register_instance(VEHICLE_TYPE type, MultiVehicle* instance) {   MultiVehicle* inst = find(type);

if (inst == 0) { registry->push_back(new Transport(type, instance)); std::cout << "registered new object\n"; } }

MultiVehicle* MultiVehicle::find(VEHICLE_TYPE type) {   std::list::iterator iter;

for(iter=registry->begin; iter != registry->end; ++iter) { if (type == ((Transport*)* iter)->type) return ((Transport*)* iter)->transport; }

return 0; }

//static Boat boat_singleton; //static Car car_singleton;

Boat::Boat {   MultiVehicle::register_instance(BOAT, this); std::cout << "Boat ctor\n"; }

Boat::~Boat {

}

Car::Car {   MultiVehicle::register_instance(CAR, this); std::cout << "Car ctor\n"; }

Car::~Car {

} code

code format="C++" Boat* b1; b1->get_instance(BOAT);
 * Test run**

Car* c; c->get_instance(CAR); Car* c1; c1->get_instance(CAR); code

Here is the result of test run

 =Factory Method Pattern=


 * //Classification//**

Class Creational 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.


 * //Motivation//**

In C++ constructors have the same name as their class. This means that a subclass cannot override its parent's constructor; and, more importantly, constructors must be invoked explicitly. When a client instantiates a class with "new", that client must know at compile time exactly which class it's instantiating. This penetrates the layer of abstraction normally imposed by polymorphism and a common base class.

The Factory Method pattern is used in circumstances like this to remove specific knowledge of which class to instantiate from the client and instead place it inside the common base class and concrete subclasses where it belongs.


 * //Applicability//**

We can use Factory Method pattern when:


 * A class can't anticipate the class of objects it must create.


 * A class wants its subclasses to specify the objects it creates.


 * Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.


 * //Structure//**


 * //Participants//**


 * **Product** - defines the interface of objects the factory method creates.


 * **ConcreteProduct** - implements the Product interface.


 * **Creator** - declares the factory method, which returns an object of type Product. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object; may call the factory method to create a Product object.


 * **ConcreteCreator** - overrides the factory method to return an instance of a ConcreteProduct.


 * //Advantages//**


 * **Provides hooks for subclasses**. Factory methods eliminate the need to bind application-specific classes into your code. The code only deals with the Product interface; therefore it can work with any user-defined ConcreteProduct classes.


 * **Connects parallel class hierarchies**. Creating objects inside a class with a factory method is always more flexible than creating an object directly. Factory Method gives subclasses a hook for providing an extended version of an object.


 * //Disadvantages//**


 * A potential disadvantage of factory methods is that clients might have to subclass the Creator class just to create a particular ConcreteProduct object. Subclassing is fine when the client has to subclass the Creator class anyway, but otherwise the client now must deal with another point of evolution.


 * //Implementation//**

We should consider following issues during Factory Method implementation:


 * **Two major varieties**. The two main variations of the Factory Method pattern are (1) the case when the Creator class is an abstract class and does not provide an implementation for the factory method it declares, and (2) the case when the Creator is a concrete class and provides a default implementation for the factory method. It's also possible to have an abstract class that defines a default implementation, but this is less common.

> The first case requires subclasses to define an implementation, because there's no reasonable default. It gets around the dilemma of having to instantiate unforeseeable classes. In the second case, the concrete Creator uses the factory method primarily for flexibility. It's following a rule that says, "Create objects in a separate operation so that subclasses can override the way they're created." This rule ensures that designers of subclasses can change the class of objects their parent class instantiates if necessary.


 * **Parameterized factory methods**. Another variation on the pattern lets the factory method create multiple kinds of products. The factory method takes a parameter that identifies the kind of object to create. All objects the factory method creates will share the Product interface. In the Document example, Application might support different kinds of Documents. We shpould pass CreateDocument an extra parameter to specify the kind of document to create.


 * //Example//**

code format="C++"
 * Module** transport.h
 * 1) ifndef _TRANSPORT_H_
 * 2) define _TRANSPORT_H_


 * 1) include

const enum VEHICLE_TYPE {AIRPLANE, BOAT, CAR, NONE};

class Transport;

class Vehicle { protected: Transport* transport;

Transport* create_transport(VEHICLE_TYPE type);

public: virtual Transport* get_transport(VEHICLE_TYPE type) = 0; };

class Transport : public Vehicle { public: //Transport;

Transport* get_transport(VEHICLE_TYPE type); };

class Airplane : public Transport { public: Airplane; };

code
 * 1) endif

code format="C++"
 * Module** transport.cpp
 * 1) include "transport.h"

Transport* Vehicle::create_transport(VEHICLE_TYPE type) {   if (type == AIRPLANE) return new Airplane; }

Transport* Transport::get_transport(VEHICLE_TYPE type) {   if (transport == 0) transport = create_transport(NONE);

if (type == AIRPLANE) return new Airplane;

return transport; }

Airplane::Airplane {   std::cout << "created new Airplane object\n"; } code

code format="C++" //Vehicle* v = Transport.get_transport(AIRPLANE);
 * Test run**

Vehicle* v = new Transport; v->get_transport(AIRPLANE);

Vehicle* a = v->get_transport(AIRPLANE);

delete v; delete a; code Here is the result of test run  =Decorator Pattern=

The Decorator pattern captures class and object relationships that support embellishment by transparent enclosure. In the Decorator pattern, embellishment refers to anything that adds responsibilities to an object. We can think for example of embellishing an abstract syntax tree with semantic actions, a finite state automaton with new transitions, or a network of persistent objects with attribute tags.

Decorator describes how to add responsibilities to objects dynamically. Decorator is a structural pattern that composes objects recursively to allow an open-ended number of additional responsibilities. For example, a Decorator object containing a user interface component can add a decoration like a border or shadow to the component, or it can add functionality like scrolling and zooming. We can add two decorations simply by nesting one Decorator object within another, and so on for additional decorations. To accomplish this, each Decorator object must conform to the interface of its component and must forward messages to it. The Decorator can do its job (such as drawing a border around the component) either before or after forwarding a message.


 * //Classification//**

Object Structural Pattern


 * //Intent//**

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


 * //Motivation//**

Sometimes we want to add responsibilities to individual objects, not to an entire class. Such responsibilities can be easily added with inheritance. However, inheritance will affect every subclass, and this in many cases undesirable.

A more flexible approach is to enclose the component in another object that adds the responsibilities. The enclosing object is called a decorator. The decorator conforms to the interface of the component it decorates so that its presence is transparent to the component's clients. The decorator forwards requests to the component and may perform additional actions before or after forwarding. Transparency lets us nest decorators recursively, thereby allowing an unlimited number of added responsibilities.


 * //Applicability//**

We can use the Decorator pattern:


 * To add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.


 * For responsibilities that can be withdrawn.


 * When extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing.


 * //Structure//**


 * //Participants//**


 * **Component** - defines the interface for objects that can have responsibilities added to them dynamically.


 * **ConcreteComponent** - defines an object to which additional responsibilities can be attached.


 * **Decorator** - maintains a reference to a Component object and defines an interface that conforms to Component's interface.


 * **ConcreteDecorator** - adds responsibilities to the component.


 * //Advantages//**


 * **More flexibility than static inheritance**. The Decorator pattern provides a more flexible way to add responsibilities to objects than can be had with static (multiple) inheritance. With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them. In contrast, inheritance requires creating a new class for each additional responsibility. This gives rise to many classes and increases the complexity of a system. Furthermore, providing different Decorator classes for a specific Component class lets you mix and match responsibilities.


 * **Avoids feature-laden classes high up in the hierarchy**. Decorator offers a pay-as-you-go approach to adding responsibilities. Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects. Functionality can be composed from simple pieces. As a result, an application needn't pay for features it doesn't use. It's also easy to define new kinds of Decorators independently from the classes of objects they extend, even for unforeseen extensions. Extending a complex class tends to expose details unrelated to the responsibilities you're adding.


 * //Disadvantages//**


 * **A decorator and its component aren't identical**. A decorator acts as a transparent enclosure. But from an object identity point of view, a decorated component is not identical to the component itself. Hence we shouldn't rely on object identity when you use decorators.


 * **Lots of little objects**. A design that uses Decorator often results in systems composed of lots of little objects that all look alike. The objects differ only in the way they are interconnected, not in their class or in the value of their variables. Although these systems are easy to customize by those who understand them, they can be hard to learn and debug.


 * //Implementation//**

Several issues should be considered when applying the Decorator pattern:


 * **Interface conformance**. A decorator object's interface must conform to the interface of the component it decorates. ConcreteDecorator classes must therefore inherit from a common class.


 * **Omitting the abstract Decorator class**. There's no need to define an abstract Decorator class when you only need to add one responsibility. That's often the case when you're dealing with an existing class hierarchy rather than designing a new one. In that case, we can merge Decorator's responsibility for forwarding requests to the component into the ConcreteDecorator.


 * **Keeping Component classes lightweight**. To ensure a conforming interface, components and decorators must descend from a common Component class. It's important to keep this common class lightweight; that is, it should focus on defining an interface, not on storing data. The definition of the data representation should be deferred to subclasses; otherwise the complexity of the Component class might make the decorators too heavyweight to use in quantity. Putting a lot of functionality into Component also increases the probability that concrete subclasses will pay for features they don't need.


 * //Example//**

code format="C++" // Module:       transport_2.h // Programmer:    Dmitriy Slipak // Date:       January 31, 2010 // Purpose: //               Header file, //               contains transportation related classes declaration // //
 * Module** transport.h
 * 1) ifndef _TRANSPORT_H_
 * 2) define _TRANSPORT_H_


 * 1) include

class Cargo { private: std::string name; double weight;

public: Cargo {} Cargo(std::string n, double w); virtual ~Cargo {};

void set_name(std::string value); std::string get_name; void set_weight(double value); double get_weight;

void print_cargo; virtual void modify_cargo = 0; };

class CargoDecorator : public Cargo { private: Cargo* cargo;

public: CargoDecorator(Cargo* c); ~CargoDecorator;

void modify_cargo; };

class DecoratedCargo : public CargoDecorator { public: DecoratedCargo(Cargo* cargo);

void modify_cargo; };

class Airplane { private: Cargo* cargo;

public: Airplane(Cargo* c){ cargo = c; }

void print_cargo{ cargo->print_cargo; } };

class AirplaneCargo : public Cargo { public: AirplaneCargo(std::string name, double weight) : Cargo(name, weight) {}

void modify_cargo {}; };

code
 * 1) endif

code format="C++"
 * Module** transport.cpp
 * 1) include "transport_2.h"

Cargo::Cargo(std::string n, double w) { name = n;   weight = w; }

void Cargo::set_name(std::string value) { name = value; } std::string Cargo::get_name { return name; } void Cargo::set_weight(double value) { weight = value; } double Cargo::get_weight { return weight; }

void Cargo::print_cargo {   std::cout << "***Cargo\n" << "name: " << name.c_str << '\n' << "weight: " << weight << '\n'; }

CargoDecorator::CargoDecorator(Cargo *c) {   cargo = c; }

CargoDecorator::~CargoDecorator {   delete cargo; }

void CargoDecorator::modify_cargo {   cargo->set_weight(cargo->get_weight + 200.0); }

DecoratedCargo::DecoratedCargo(Cargo* cargo) : CargoDecorator(cargo) {}

void DecoratedCargo::modify_cargo {   CargoDecorator::modify_cargo; } code

code format="C++" Cargo* cargo = new AirplaneCargo("cargo 1", 100); Airplane* a = new Airplane(cargo);
 * Test run**

cargo->modify_cargo; a->print_cargo;

cargo = new DecoratedCargo(cargo); cargo->modify_cargo;

a->print_cargo;

delete cargo; delete a; code Here is the result of test run  =Command Pattern=

The Command pattern prescribes a uniform interface for issuing requests that lets you configure clients to handle different requests. The interface shields clients from the request's implementation. A command may delegate all, part, or none of the request's implementation to other objects.


 * //Classification//**

Object Behavioral Pattern


 * //Intent//**

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.


 * //Motivation//**

Sometimes it's necessary to issue requests to objects without knowing anything about the operation being requested or the receiver of the request. For example, user interface toolkits include objects like buttons and menus that carry out a request in response to user input. But the toolkit can't implement the request explicitly in the button or menu, because only applications that use the toolkit know what should be done on which object. Toolkit designers usually have no way of knowing the receiver of the request or the operations that will carry it out.


 * //Applicability//**

We can use the Command pattern when we want to:


 * Parameterize objects by an action to perform. We can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks.


 * Support undo. The Command's Execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Unexecute operation that reverses the effects of a previous call to Execute. Executed commands are stored in a history list. Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling Unexecute and Execute, respectively.


 * Support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. Recovering from a crash involves reloading logged commands from disk and reexecuting them with the Execute operation.


 * Structure a system around high-level operations built on primitives operations. Such a structure is common in information systems that support transactions. A transaction encapsulates a set of changes to data. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.


 * Specify, queue, and execute requests at different times. A Command object can have a lifetime independent of the original request. If the receiver of a request can be represented in an address space independent way, then you can transfer a command object for the request to a different process and fulfill the request there.


 * //Structure//**


 * //Participants//**


 * **Command** - declares an interface for executing an operation.


 * **ConcreteCommand** - defines a binding between a Receiver object and an action; implements Execute by invoking the corresponding operation(s) on Receiver.


 * **Client** - creates a ConcreteCommand object and sets its receiver.


 * **Invoker** - asks the command to carry out the request.


 * **Receiver** - knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.


 * //Advantages//**


 * Command decouples the object that invokes the operation from the one that knows how to perform it.


 * Commands are first-class objects. They can be manipulated and extended like any other object.


 * It's easy to add new Commands, because you don't have to change existing classes.


 * //Implementation//**

We should consider the following issues when implementing the Command pattern:


 * **How intelligent should a command be?** A command can have a wide range of abilities. At one extreme it merely defines a binding between a receiver and the actions that carry out the request. At the other extreme it implements everything itself without delegating to a receiver at all. The latter extreme is useful when you want to define commands that are independent of existing classes, when no suitable receiver exists, or when a command knows its receiver implicitly. For example, a command that creates another application window may be just as capable of creating the window as any other object. Somewhere in between these extremes are commands that have enough knowledge to find their receiver dynamically.


 * **Supporting undo and redo**. Commands can support undo and redo capabilities if they provide a way to reverse their execution (e.g., an Unexecute or Undo operation). A ConcreteCommand class might need to store additional state to do so. This state can include:

> - the Receiver object, which actually carries out operations in response to the request;

> - the arguments to the operation performed on the receiver;

> - any original values in the receiver that can change as a result of handling the request. The receiver must provide operations that let the command return the receiver to its prior state.


 * **Avoiding error accumulation in the undo process**. Hysteresis can be a problem in ensuring a reliable, semantics-preserving undo/redo mechanism. Errors can accumulate as commands are executed, unexecuted, and reexecuted repeatedly so that an application's state eventually diverges from original values. It may be necessary therefore to store more information in the command to ensure that objects are restored to their original state.


 * //Example//**

code format="C++"
 * Module** transport.h
 * 1) ifndef _TRANSPORT_H_
 * 2) define _TRANSPORT_H_


 * 1) include

class Vehicle { protected: Vehicle {}

public: ~Vehicle {}

virtual void carry = 0; };

class Airplane;

class Transport : public Vehicle { private: Vehicle* vehicle;

public: Transport {} Transport(Vehicle* v); Transport(Airplane* a);

virtual void carry { vehicle->carry; } };

class Airplane : public Transport { public: void carry; };

class Boat : public Transport { public: void carry; };

class Car : public Transport { public: void carry; };

code
 * 1) endif

code format="C++"
 * Module** transport.cpp
 * 1) include "transport.h"

Transport::Transport(Vehicle* v) { vehicle = v; }

Transport::Transport(Airplane* a) { vehicle = a; }

void Airplane::carry {   std::cout << "Airplane::carry\n"; }

void Boat::carry {   std::cout << "Boat::carry\n"; }

void Car::carry {   std::cout << "Car::carry\n"; } code

code format="C++" Airplane* a = new Airplane; Boat* b = new Boat; Car* c = new Car;
 * Test run**

Vehicle* v = new Transport(a); v->carry;

v = new Transport(b); v->carry;

v = new Transport(c); v->carry;

delete c; delete b; delete a; delete v; code

Here is the result of test run  =Strategy Pattern=

Encapsulating an algorithm in an object is the intent of the Strategy pattern. The key participants in the pattern are Strategy objects (which encapsulate different algorithms) and the context in which they operate. Compositors are strategies; they encapsulate different formatting algorithms. A composition is the context for a compositor strategy.


 * //Classification//**

Object Behavioral Pattern


 * //Intent//**

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.


 * //Motivation//**

There are situations when multiple algorithms can be applied to solve particular problem. Including all of those algorithms into classes that require them might be is not desirable for a few reasons:


 * Clients that need those algorithms will get more complex.


 * It's nice to handle all possible situations by algorithms. But it is much nicer to have in the place only those algorithms which required for particular problems. (Remember unused/dead-code issue from refactorings course?)


 * Maintenance may be not a trivial task when algorithms exist as part of a client.

These issues can be solved with strategy pattern.


 * //Applicability//**

Strategy pattern might be applied when:


 * Many related classes differ only in their behavior.


 * Different variants of an algorithm required.


 * An algorithm use a data that client should not know about.


 * A class defines many behaviors, and these appear as multiple conditional statements in its operations.


 * //Structure//**


 * //Participants//**


 * **Strategy** – declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy.


 * **ConcreteStrategy** – implements the algorithm using the Strategy interface.


 * **Context** – configured with a ConcreteStrategy object and maintains a reference to a Strategy object.


 * //Advantages//**


 * **Families of related algorithms**. Hierarchies of Strategy classes define a family of algorithms or behaviors for contexts to reuse. Inheritance can help factor out common functionality of the algorithms.


 * **An alternative to subclassing**. Inheritance offers another way to support a variety of algorithms or behaviors. You can subclass a Context class directly to give it different behaviors. But this hard-wires the behavior into Context. It mixes the algorithm implementation with Context's, making Context harder to understand, maintain, and extend. And you can't vary the algorithm dynamically. You wind up with many related classes whose only difference is the algorithm or behavior they employ. Encapsulating the algorithm in separate Strategy classes lets you vary the algorithm independently of its context, making it easier to switch, understand, and extend.


 * **Strategies eliminate conditional statements**. The Strategy pattern offers an alternative to conditional statements for selecting desired behavior. When different behaviors are lumped into one class, it's hard to avoid using conditional statements to select the right behavior. Encapsulating the behavior in separate Strategy classes eliminates these conditional statements. Consider following code without strategy applied:

code format="C++" void Vehicle::carry { switch (carryStrategy) { case airplaneStrategy: AirplaneCarry; break; case boatStrategy: BoatCarry; break; case carStrategy: CarCarry; break; } } code

With Strategy pattern applied the code above may be transformed as follows:

code format="C++" voidVehicle::carry { compositionInstance->carry; } code


 * **A choice of implementations**. Strategies can provide different implementations of the same behavior. The client can choose among strategies with different time and space trade-offs.


 * //Disadvantages//**


 * **Clients must be aware of different Strategies**. The pattern has a potential drawback in that a client must understand how Strategies differ before it can select the appropriate one. Clients might be exposed to implementation issues. Therefore you should use the Strategy pattern only when the variation in behavior is relevant to clients.


 * **Communication overhead between Strategy and Context**. The Strategy interface is shared by all ConcreteStrategy classes whether the algorithms they implement are trivial or complex. Hence it's likely that some ConcreteStrategies won't use all the information passed to them through this interface; simple ConcreteStrategies may use none of it! That means there will be times when the context creates and initializes parameters that never get used. If this is an issue, then you'll need tighter coupling between Strategy and Context.


 * **Increased number of objects**. Strategies increase the number of objects in an application. Sometimes you can reduce this overhead by implementing strategies as stateless objects that contexts can share. Any residual state is maintained by the context, which passes it in each request to the Strategy object. Shared strategies should not maintain state across invocations.


 * //Implementation//**

We have to consider the following implementation issues:


 * **Defining the Strategy and Context interfaces**. The Strategy and Context interfaces must give a ConcreteStrategy efficient access to any data it needs from a context, and vice versa.

> One approach is to have Context pass data in parameters to Strategy operations—in other words, take the data to the strategy. This keeps Strategy and Context decoupled. On the other hand, Context might pass data the Strategy doesn't need.

> Another technique has a context pass itself as an argument, and the strategy requests data from the context explicitly. Alternatively, the strategy can store a reference to its context, eliminating the need to pass anything at all. Either way, the strategy can request exactly what it needs. But now Context must define a more elaborate interface to its data, which couples Strategy and Context more closely.


 * **Making Strategy objects optional**. The Context class may be simplified if it's meaningful not to have a Strategy object. Context checks to see if it has a Strategy object before accessing it. If there is one, then Context uses it normally. If there isn't a strategy, then Context carries out default behavior. The benefit of this approach is that clients don't have to deal with Strategy objects at all unless they don't like the default behavior.


 * //Example//**

code format="C++" // Module:       transport.h // Programmer:    Dmitriy Slipak // Date:       January 27, 2010 // Purpose: //               Header file, //               contains transportation related classes declaration //
 * Module** transport.h
 * 1) ifndef _TRANSPORT_H_
 * 2) define _TRANSPORT_H_


 * 1) include

class Vehicle;

class Transport { public: const enum TRANSPORTATION {BY_AIR, BY_WATER, BY_ROAD}; std::string ttos(TRANSPORTATION t); virtual void carry(Vehicle* v) = 0; };

class Vehicle { private: Transport* transport;

std::string id; double empty_weight; double max_gross_weight; double max_speed;

public: Vehicle(Transport* t) : transport(t) {};

void set_id(std::string value); std::string get_id; void set_empty_weight(double value); double get_empty_weight; void set_max_gross_weight(double value); double get_max_gross_weight; void set_max_speed(double value); double get_max_speed;

void carry; void print; };

class Airplane : public Transport { private: TRANSPORTATION transportation;

public: Airplane : transportation(BY_AIR) {};

void carry(Vehicle* v); };

class Boat : public Transport { private: TRANSPORTATION transportation;

public: Boat : transportation(BY_WATER) {};

void carry(Vehicle* v); };

class Car : public Transport { private: TRANSPORTATION transportation;

public: Car : transportation(BY_ROAD) {};

void carry(Vehicle* v); };

code
 * 1) endif

code format="C++"
 * Module** transport.cpp
 * 1) include "transport.h"

std::string Transport::ttos(TRANSPORTATION t) { std::string transportation;

switch (t) { case BY_AIR: transportation = "by air"; break; case BY_WATER: transportation = "by water"; break; case BY_ROAD: transportation = "by road"; break; }

return transportation; }

void Vehicle::set_id(std::string value) { id = value; } std::string Vehicle::get_id { return id; } void Vehicle::set_empty_weight(double value) { empty_weight = value; } double Vehicle::get_empty_weight { return empty_weight; } void Vehicle::set_max_gross_weight(double value) { max_gross_weight = value; } double Vehicle::get_max_gross_weight { return max_gross_weight; } void Vehicle::set_max_speed(double value) { max_speed = value; } double Vehicle::get_max_speed { return max_speed; }

void Vehicle::carry {   transport->carry(this); }

void Vehicle::print {   std::cout << "*** Vehicle" << "\nIdentification: " << get_id.c_str << "\nEmpty weight: " << get_empty_weight << " lb" << "\nMax gross weight: " << get_max_gross_weight << " lb" << "\nMax speed: " << get_max_speed << " mph"; }

void Airplane::carry(Vehicle* v) { v->print; std::cout << "\nTransportation will be " << ttos(transportation).c_str << "\n\n"; }

void Boat::carry(Vehicle* v) { v->print; std::cout << "\nTransportation will be " << ttos(transportation).c_str << "\n\n"; }

void Car::carry(Vehicle* v) { v->print; std::cout << "\nTransportation will be " << ttos(transportation).c_str << "\n\n"; } code

code format="C++" Vehicle* v = new Vehicle(new Airplane); v->set_id("Boeing 777-200ER"); v->set_empty_weight(315000.0); v->set_max_gross_weight(656000.0); v->set_max_speed(587.0); v->carry;
 * Test run**

v = new Vehicle(new Boat); v->set_id("Mark I (PCFs 1-104)"); v->set_empty_weight(36913.0); v->set_max_gross_weight(47047.0); v->set_max_speed(36.8256); v->carry;

v = new Vehicle(new Car); v->set_id("Pontiac Bonneville"); v->set_empty_weight(3633.0); v->set_max_gross_weight(4000.0); v->set_max_speed(182.0); v->carry;

delete v; code

Here is the result of test run

 =Conclusion=

Design patterns require solid understanding of OO principles. Applying proper pattern in a proper place can help dramatically. However, sometimes applying design patterns may be undesirable for several reasons described above. Patterns are a communication medium, and like any communication technique there are situations where they work well and those where they work badly.

Last revision date: {$revisiondate}