分类: C/C++
2009-01-29 10:59:53
Prototype Design Pattern [A fully initialized instance to be copied or cloned]
A prototype pattern is a creational design pattern used in software development when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used for example when the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) is prohibitively expensive for a given application. To implement the pattern, declare an abstract base class that specifies a pure virtual clone() member function. Any class that needs a "polymorphic constructor" capability derives itself from the abstract base class, and implements the clone() operation. The client, instead of writing code that invokes the "new" operator on a hard-wired class name, calls the clone() member function on the prototype, calls a factory member function with a parameter designating the particular concrete derived class desired, or invokes the clone() member function through some mechanism provided by another design pattern.
class CPrototypeMonster { protected:
CString _name;
public:
CPrototypeMonster();
CPrototypeMonster( const CPrototypeMonster& copy );
~CPrototypeMonster();
virtual CPrototypeMonster* Clone() const=0; // This forces every derived class to provide an overload for this function. void Name( CString name );
CString Name() const;
};
class CGreenMonster : public CPrototypeMonster { protected:
int _numberOfArms;
double _slimeAvailable;
public:
CGreenMonster();
CGreenMonster( const CGreenMonster& copy );
~CGreenMonster();
virtual CPrototypeMonster* Clone() const;
void NumberOfArms( int numberOfArms );
void SlimeAvailable( double slimeAvailable );
int NumberOfArms() const;
double SlimeAvailable() const;
};
class CPurpleMonster : public CPrototypeMonster { protected:
int _intensityOfBadBreath;
double _lengthOfWhiplikeAntenna;
public:
CPurpleMonster();
CPurpleMonster( const CPurpleMonster& copy );
~CPurpleMonster();
virtual CPrototypeMonster* Clone() const;
void IntensityOfBadBreath( int intensityOfBadBreath );
void LengthOfWhiplikeAntenna( double lengthOfWhiplikeAntenna );
int IntensityOfBadBreath() const;
double LengthOfWhiplikeAntenna() const;
};
class CBellyMonster : public CPrototypeMonster { protected:
double _roomAvailableInBelly;
public:
CBellyMonster();
CBellyMonster( const CBellyMonster& copy );
~CBellyMonster();
virtual CPrototypeMonster* Clone() const;
void RoomAvailableInBelly( double roomAvailableInBelly );
double RoomAvailableInBelly() const;
};
// Note! Very Important
CPrototypeMonster* CGreenMonster::Clone() const { return new CGreenMonster(*this);
} CPrototypeMonster* CPurpleMonster::Clone() const { return new CPurpleMonster(*this);
} CPrototypeMonster* CBellyMonster::Clone() const { return new CBellyMonster(*this);
}
A client of one of the concrete monster classes only needs a reference (pointer) to a CPrototypeMonster class object to be able to call the ‘Clone’ function and create copies of that object. The function below demonstrates this concept:
void DoSomeStuffWithAMonster( const CPrototypeMonster* originalMonster ) { CPrototypeMonster* newMonster = originalMonster->Clone();
ASSERT( newMonster );
newMonster->Name("MyOwnMoster");
// Add code doing all sorts of cool stuff with the monster. delete newMonster; //don't forget this code to release the pointers
}
Now originalMonster can be passed as a pointer to CGreenMonster, CPurpleMonster or CBellyMonster.