📄 index.htm
字号:
</ul>
The implementation of Singleton is the class Singleton in the Singleton.h header file, located in your include/Patterns directory. The declaration of this class is presented in below:
<pre>
template <typename TYPE,typename _A = std::allocator<TYPE>>
class Singleton
</pre>
The template parameter TYPE is the type of the object being Singleton.The second template parameter specifies an allocation strategy. The default strategy used is the standard C++ allocator, which internally uses the standard C memory allocation routines. However, other strategies with more complex allocation algorithms can be plugged into the Singleton using this parameter. Below the example code How to use the Singleton :
<pre>
class Number
{
public:
virtual void setValue( int in ) { value = in; }
virtual int getValue() { return value; }
protected:
int value;
};
Singleton<Number>::instance()->setValue( 42 );
Singleton<Number>::instance()->getValue();
Singleton<Number>::close()
</pre>
<HR>
<strong>
To destroy the your object being Singleton, Always call Singleton<TYPE>::close();
</strong>
<HR>
</BLOCKQUOTE>
<a name="Observer"> </a>
<H4><a href="http://www.bearguru.com/projects/XPDPTL/GOF/hires/pat5gfs.htm">The Subject-Observer Pattern</a>
<a href="include/Patterns/SubjectObserver.h">SubjectObserver.h</a>
<a href="http://www.bearguru.com/projects/XPDPTL/GOF/html/Observer.html">UML notation</a>
</H4>
<BLOCKQUOTE
style="BACKGROUND-COLOR: #eeeeee; BORDER-BOTTOM: 1px dashed; BORDER-LEFT: 1px dashed; BORDER-RIGHT: 1px dashed; BORDER-TOP: 1px dashed; PADDING-BOTTOM: 4px; PADDING-LEFT: 4px; PADDING-RIGHT: 4px; PADDING-TOP: 4px">
The subject-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. In the subject-observer relationship, a subject encapsulates related data and functionality that an observer monitors. If the state of the subject changes, the observer needs to know about it. To accomplish this, the subject defines a notification dictionary that is the set of all notifications of change a subject may broadcast. A notification is any class that implements the IMessage interface. It is the responsibility of the subject to define a notification dictionary and to broadcast individual notifications of change to its list of observers. It is the responsibility of the observer to subscribe to the notifications sent by a subject and to understand and react to the notifications it receives.
<pre>
A subject is any class that implements the ISubject interface, shown in below:
class ISubject : public IQueryGuid, public IRefCount
{
public:
virtual void AddObserver(IObserver* pObserver) = 0;
virtual void RemoveObserver(IObserver* pObserver) = 0;
virtual void UpdateAllObservers(IObserver* pObserver,IMessage* pMsg) = 0;
};
</pre>
The AddObserver() method allows observers to subscribe to notifications sent by the subject. The RemoveObserver() method removes a particular observer from the subject. The UpdateAllObservers() method sends a notification message to all observers.A notification message is any class that implements the IMessage interface, shown in below:
<pre>
class IMessage : public IQueryGuid, public IRefCount
{
public:
virtual XPUint32 GetTypeID() const = 0;
};
</pre>
Each message type is associated with an integer identifier, which can be used by observers to identify the message given an IMessage pointer. It is also possible to use QueryGuid() or the guid_cast operator to cast an IMessage pointer to another type.The IObserver interface, shown in below, is implemented by classes that need to observe subjects:
<pre>
class IObserver : public IQueryGuid, public IRefCount
{
public:
virtual void OnUpdate(ISubject* pSubject, IMessage* pMsg) = 0;
};
</pre>
The subject invokes the OnUpdate() method to send notification messages to observers. Subjects typically implement the UpdateAllObservers() method by iterating over each observer and calling their OnUpdate() method. An object can implement both the ISubject and IObserver interfaces, producing an object that observes one object and acts as a subject for others. This makes it possible to chain together or nest subjects and observers.
</BLOCKQUOTE>
<a name="Composite"> </a>
<H4><a href="http://www.bearguru.com/projects/XPDPTL/GOF/hires/pat5gfs.htm">The The Composite Pattern</a>
<a href="include/Patterns/Composite.h">Composite.h</a>
<a href="http://www.bearguru.com/projects/XPDPTL/GOF/html/Composite.html">UML notation</a>
</H4>
<BLOCKQUOTE
style="BACKGROUND-COLOR: #eeeeee; BORDER-BOTTOM: 1px dashed; BORDER-LEFT: 1px dashed; BORDER-RIGHT: 1px dashed; BORDER-TOP: 1px dashed; PADDING-BOTTOM: 4px; PADDING-LEFT: 4px; PADDING-RIGHT: 4px; PADDING-TOP: 4px">
The composite pattern composes objects into tree structures to represent part-whole hierarchies. The composite pattern lets client code treat individual objects and compositions of objects uniformly. For example, a composite shape is made up of several individual shapes such as rectangles and ellipses. The composite pattern allows simple shapes and complex shapes to be handled the same way.
<p></p>
The CComposite template class provides an implementation of the composite pattern.It maintains a list of child objects that are accessed through methods such as AddChild(), RemoveChild(), and GetChildrenCount(). In addition to having a list of children, each composite object maintains a pointer to its parent. The declaration of this templated class is shown in below:
<pre>
template <typename _Component, const XPIID* _guid>
class CComposite: public IQueryGuid
{
...
};
</pre>
The first parameter passed into the CComposite template is the component type,which determines the type of parent and child objects in the composite. Objects in the tree are accessed using that type. For example, the declaration of the GetParent() method returns a pointer to a _Component object, not a CComposite<> object:
<pre>
_Component* GetParent() const;
</pre>
The second parameter in the template is a XPIID that will identify the composite interface within the set of interfaces implemented by the component classes. The composite implementation does not assume an inheritance relationship between the CComposite<> class and the _Component class. Rather than an implicit conversion, casting from one to the other is performed using the guid_cast<> mechanism, standard in XPDPTL. Whenever the CComposite<> interface is needed in some operation, a guid_cast<> is performed using the XPIID passed in the second template parameter. Derived classes are responsible of providing an adequate interface map that allows this guid_cast<> call to succeed. All classes that mix-in the CComposite<> template among their base classes are indirectly deriving from IQueryGuid, as seen earlier in above.
<p></p>
Below uses the CComposite class to compose complex shapes from simple shapes.The sample defines an entire class hierarchy that mixes in the composite pattern for all of its classes.
<pre>
// Abstract base class for all shapes
#define XP_ISHAPE_IID \
{ 0x8a156043, 0xb5e8, 0x4c7e, { 0x97, 0xfc, 0xa2, 0x2e, 0x57, 0x7, 0xe6, 0x5f } };
#define XP_ICOMPOSITESHAPE_IID \
{ 0x8a156043, 0xb5e8, 0x4c7e, { 0x97, 0xfc, 0xa2, 0x2e, 0x57, 0x7, 0xe6, 0x5f } };
class Shape
{
public:
virtual Draw(CDC* pDC) = 0;
static const XPIID& IID() { static XPIID iid = XP_ISHAPE_IID; return iid; }
};
typedef CComposite<Shape,XP_ICOMPOSITESHAPE_IID)> CompositeShape;
// Default implementation for composite shapes
class CompositeShapeBase :
public Shape,
public CompositeShape
{
public:
virtual Draw(CDC* pDC)
{
// Iterate over list of contained shapes
// using the CComposite<> interface facilities. . .
// Draw each child shape
}
BEGIN_GUID_MAP(CompositeShapeBase)
GUID_ENTRY_IID(XP_ICOMPOSITESHAPE_IID, CompositeShape)
GUID_ENTRY_IID(Shape::IID(), Shape)
END_GUID_MAP
};
// A normal composite shape
class CompositeShapeNormal : public CompositeShapeBase
{
public:
virtual Draw(CDC* pDC)
{
// Draw shapes front to back
}
};
// A reverse Z-order composite shape
class CompositeShapeRev : public CompositeShapeBase
{
public:
virtual Draw(CDC* pDC)
{
// Reverse order and draw shapes back to front
}
};
// Simple shapes
class Polygon : public Shape
{
public:
virtual Draw(CDC* pDC)
{
// Draw a polygon. . .
}
BEGIN_GUID_MAP(Polygon)
GUID_ENTRY_IID(Shape::IID(), Shape)
END_GUID_MAP
};
class Rectangle : public Shape
{
public:
virtual Draw(CDC* pDC)
{
// Draw a rectangle
}
BEGIN_GUID_MAP(Rectangle)
GUID_ENTRY_IID(Shape::IID(), Shape)
END_GUID_MAP
};
</pre>
Below sets up a composite tree with three descendents, one of which is,in turn, a composite:
<pre>
Shape* pRootShape = new CompositeShapeNormal;
CompositeShape* pComposite = guid_cast<CompositeShape>(pRootShape);
pComposite->AddChild(new Rectangle);
pComposite->AddChild(new Polygon);
Shape* pSubShape = new CompositeShapeRev;
CompositeShape* pSubComposite =guid_cast<CompositeShape>(pSubShape);
pSubComposite->AddChild(new Rectangle);
pComposite->AddChild(pSubComposite);
</pre>
</BLOCKQUOTE>
<H4>The Object Factory Pattern <a href="include/Patterns/Factory.h">Factory.h</a></H4>
<BLOCKQUOTE
style="BACKGROUND-COLOR: #eeeeee; BORDER-BOTTOM: 1px dashed; BORDER-LEFT: 1px dashed; BORDER-RIGHT: 1px dashed; BORDER-TOP: 1px dashed; PADDING-BOTTOM: 4px; PADDING-LEFT: 4px; PADDING-RIGHT: 4px; PADDING-TOP: 4px">
In general, it is a good programming practice to decouple the object creation and destruction processes from the actual usage of the object. On one hand, it facilitates the application of interface-oriented programming practices. Under this paradigm the objects are supposed to be manipulated only through their interfaces. However, there is one place in the program where the real type of the object needs to be known, and that is when a new instance needs to be created. Interface-based programming can greatly benefit if that unique place can be isolated from the rest of the program.
<p></p>
The other benefit of decoupling an object’s creation process from its usage is that it offers a greater degree of freedom in the memory allocation of the object, that is, the location in memory where the object will reside and the mechanism followed to release that memory upon destruction of the object.
<p></p>
The object factory pattern offers a reusable mechanism to manage the creation and release of objects. Particularly, it addresses the two main issues stated above. XPDPTL offers an implementation of the object factory in the Factory.h header file, located in your include directory. This implementation is
centered around the class CObjectFactory. The declaration of this class is presented in below:
<pre>
template <typename _Base, typename _Derived,
typename _A = std::allocator<_Derived>>
class CObjectFactory:
public CObjectFactoryBase<_Base>
</pre>
The template parameter _Base is the type of the object being returned by the factory.The second template parameter, _Derived, specifies the actual type of the object being created. _Base and _Derived are not necessarily the same type (although it is possible), but they are assumed to be related by inheritance: a pointer to _Derived must be implicitly convertible to a pointer to _Base.
<p></p>
The third template parameter specifies an allocation strategy. The default strategy used is the standard C++ allocator, which internally uses the standard C memory allocation routines. However, other strategies with more complex allocation algorithms can be plugged into the factory using this parameter.
<p></p>
CObjectFactoryBase<> declares the interface of the factory. The two methods declared on this interface, and implemented by the object factory are:
<pre>
virtual _Base* CreateObject() const = 0;
virtual void DestroyObject(_Base* pObject) const = 0;
</pre>
This base class is only templated by _Base, the type of the interface being returned.This allows you to give polymorphic treatment to a set of object factories that have only that element in common, but differ in the type of the actual object being instantiated or in the allocation scheme.
<p></p>
Creation of a new instance is achieved by calling the CreateObject() method in a CObjectFactory. The allocator functions are used to reserve the memory and initialize the object, and a pointer to the desired interface on that object is returned.
<center><hr><strong>
CAUTION—Always call DestroyObject() on the same factory class that created the object. Otherwise, the deallocation process might not correspond
to the allocation, and this would cause unexpected errors in a program.
</strong></center>
<hr>
Consider the following code.
<pre>
interface IElementBase {...};
class CElemImpl1: public IElementBase {...};
class CElemImpl2: public IElementBase {...};
typedef CObjectFactoryBase<IElementBase> ElementFactory;
typedef CObjectFactory<IElementBase, CElemImpl1> Impl1Factory;
typedef CObjectFactory<IElementBase, CElemImpl2> Impl2Factory;
IElementBase* CreateElement(ElementFactory& factory)
{
return factory.CreateObject();
}
</pre>
In the sample above, an interface is declared and two implementations of that interface are provided. The creation of the objects is centralized on the CreateElement() routine, regardless of the actual implementation.
<pre>
IElementBase* p1 = CreateElement(Impl1Factory);
IElementBase* p2 = CreateElement(Impl2Factory);
</pre>
The same creation mechanism could be employed if we declare a new factory with
a different allocation strategy:
<pre>
IElementBase* pShared = CreateElement(Impl1OnSharedMemoryFactory);
</pre>
To destroy the instances, use the same factory class used to create them:
<pre>
Impl1Factory factory1;
factory1.DestroyObject(p1);
</pre>
</BLOCKQUOTE>
<H3><a name="references"> References </a> </H3>
<UL>
<LI>Gamma E., Helm R., Johnson R., Vlissides J.: <a href="http://www.bearguru.com/projects/XPDPTL/GOF/">Design Patterns - Elements of Reusable Object-Oriented Software<a>, Addison-Wesley 1995, ISBN 0-201-63361-2 </LI>
<LI>James W. Cooper: <a href="http://www.bearguru.com/projects/XPDPTL/DPJava/designpatternjava.pdf">The Design Patterns Java companion<a>, Addison-Wesley design patterns series</LI>
<LI>Stingray Foundation Library User's Guide</LI>
</UL>
<div style="border-width:1px; border-style:dashed; padding:4px; background-color:#eeffff;">
<H5><a name="author"> About the author</a></H5>
<a href="http://www.bearguru.com/">Tony</a> is dedicating to internet related technologies.<br>
He is married to a beautiful woman ...
</div>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -