📄 index.htm
字号:
BEGIN_GUID_MAP(CCow)
GUID_ENTRY(IAnimal)
GUID_ENTRY2(IQueryGuid, IAnimal)
GUID_ENTRY2(IRefCount, IAnimal)
END_GUID_MAP
};
</pre>
</BLOCKQUOTE>
<H3><A NAME="C++Event">C++ Event package</A></H3>
<H4>Overview</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">
Applications and components generate and handle numerous events.Because C++ is an object-oriented language, you should treat events as objects within an application or component.The Events package below provides an object-oriented event model similar to the Java event model. Events are treated as instances of C++ classes so you can invent new types of events through sub-classing. Objects interested in receiving event notifications are called event listeners. Event listeners can subscribe to event routers, which are objects that either generate or route events through the system. A publisher-subscriber relationship exists between event routers and event listeners. This object-oriented approach to event handling is flexible and is ideal for handling applications and components messages, as well as custom events.
</BLOCKQUOTE>
<H4>Event Objects</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">
Events are instances of event classes that implement the IEvent interface. The IEvent interface defines the Dispatch() method, which takes a pointer to the object handling the event and invokes the appropriate handler function. Events implement the Dispatch() method by querying the event handler for the appropriate event listener interface and then invoking the handler method on the interface. The relationship between events and event listeners is an example of the visitor design pattern. Event classes are simply C++ classes that implement the IEvent interface. Developers can create their own custom event types by implementing the IEvent interface and one or more corresponding event listener types.
<pre>
class IEvent
{
public:
virtual XPBool Dispatch(IEventListener* pIListener) = 0;
};
</pre>
</BLOCKQUOTE>
<H4>Event Routers </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">
An event router is an object that generates events and routes them to event listeners.Event listeners can be added and removed from an event router, and it is the event router's responsibility to route the events to interested listeners. Event routers implement the IEventRouter interface, which contains three methods.
<pre>
class IEventRouter
{
public:
/* Routes event objects to event listeners. */
virtual XPBool RouteEvent(IEvent* pIEvent) = 0;
/* Add an event listener to the router. */
virtual XPBool AddListener(IEventListener* pIListener) = 0;
/* Remove an event listener from the router. */
virtual XPBool RemoveListener(IEventListener* pIListener) = 0;
};
</pre>
</BLOCKQUOTE>
<H4>Default Event Router Implementation</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 IEventRouterImpl class provides a default implementation of the IEventRouter interface. Below shows the IEventRouterImpl implementation of RouteEvent().
<pre>
virtual XPBool RouteEvent(IEvent* pIEvent)
{
int nHandledCount = 0;
if (pIEvent != 0 )
{
ListenerVector::const_iterator itListener;
// Give each event listener a chance to handle the event.
for (itListener = m_listeners.begin();itListener != m_listeners.end();itListener++)
if ((*itListener)->HandleEvent(pIEvent))nHandledCount++;
return (nHandledCount > 0);
}
}
</pre>
The IEventRouterImpl class gives each event listener an opportunity to handle the event. An alternative implementation might stop as soon as a listener is found to handle the event.
</BLOCKQUOTE>
<H4>Event Listeners</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">
Event listeners subscribe to event routers to receive events. The IEventListener interface defines a single method, HandleEvent(), as shown in below:
<pre>
IEventListener
{
public:
/* Receive an event and attempt to handle it. */
virtual XPBool HandleEvent(IEvent* pIEvent) = 0;
};
</pre>
An event listener can implement HandleEvent() any way it chooses, but the typical implementation invokes the event's Dispatch() method. below demonstrates a typical implementation of HandleEvent().
<pre>
virtual XPBool HandleEvent(IEvent* pIEvent)
{
XPBool bHandled = XP_FALSE;
if (pIEvent != NULL)
bHandled = pIEvent->Dispatch(this);
return bHandled;
}
</pre>
Notice that the event listener passes a pointer to itself into the event object's Dispatch() method. The Dispatch() method queries the listener for an interface that it understands and then invokes the callback method on that interface.Below demonstrates how the paint event class invokes the OnPaint() callback
function.
<pre>
XPBool CWindowPaintEvent::Dispatch(IQueryGuid* pIListener)
{
XPBool bHandled = XP_FALSE;
//some interface query mechanism (XPDPTL or COM or XPCOM or RTTI or only C++ stuff)
IWindowListener* pIWindowListener =guid_cast<IWindowListener*>((pIListener);
if (pIWindowListener != NULL)
{
bHandled = pIWindowListener->OnPaint(GetDC());
pIWindowListener->Release();
}
return bHandled;
}
</pre>
The event's Dispatch() method checks to see if it has the right type of listener. If it does have the right listener, it invokes the appropriate callback method. In the preceding sample code, the event listener is expected to implement the IWindowListener interface to receive the OnPaint() callback. Although HandleEvent() method is sufficient for handling all the events that a listener is interested in receiving, doing so would be equivalent to writing a window procedure containing a big switch() statement. The idea behind making event handling simpler is to map events onto individual member functions. For example, you could map a WM_PAINT message onto an OnPaint() member function that receives a device context as a parameter. Event listener interfaces extend the base IEventListener interface with callback functions that are invoked to handle events. An example of an event listener interface is IWindowListener, shown in:
<pre>
class IWindowListener : public IEventListener
{
public:
virtual XPBool OnCreate(LPCREATESTRUCT lpCreateStruct) = 0;
virtual XPBool OnDestroy() = 0;
virtual XPBool OnMove(int x, int y) = 0;
virtual XPBool OnSize(UINT nFlag, int cx, int cy) = 0;
virtual XPBool OnEraseBkgnd(HDC hDC) = 0;
virtual XPBool OnPaint(HDC hDC) = 0;
virtual XPBool OnWindowPosChanging(LPWINDOWPOS lpWindowPos) = 0;
virtual XPBool OnWindowPosChanged(LPWINDOWPOS lpWindowPos) = 0;
virtual XPBool OnTimer(UINT nIDTimer) = 0;
};
</pre>
The HandleEvent() method inherited from IEventListener is called to handle all events, but it delegates the work to the callback functions by calling the event object's Dispatch() method. The flow of control for handling events is as follows:
<pre>
Event object->HandleEvent->Dispatch->Callback function
</pre>
<img src="images/event.jpg"></img><br>
The event object is passed to the event listener's HandleEvent() method. The HandleEvent() method delegates the task of invoking the correct callback function to the event object.<br><br>
Be aware that this is only the default behavior, and can easily be overridden. For example, you might handle certain events directly in your event listener's HandleEvent() method without invoking a callback function. It is also possible to implement HandleEvent() in such a way that it bypasses the event object's Dispatch() method and invokes the callback methods directly. The architecture is flexible enough to allow many different event listener implementations.
</BLOCKQUOTE>
<H3><a name= "XPDP" >XP Design Pattern </a></H3>
<H4>Overview</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">
A design pattern is a solution to a problem or class of problems that can be reused over and over. Problems that are similar in nature frequently exhibit recognizable patterns. Experienced software designers learn to recognize these patterns and are able to draw on past experience to reuse old designs to solve new problems. The book Design Patterns: Elements of Reusable Object-Oriented Software identifies and documents many common design patterns and has become a classic software engineering textbook. The XPDPTL provides support for several commonly used design patterns.
<p><p>
Note that for each class, the directories XPDPTL/examples provide a program which demonstrates the use of the class, and verifies that they work correctly.
<p><p>
When you receive the library, it will include the following Design Pattern:
<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0 BGCOLOR=#99CCFF>
<TR VALIGN=TOP>
<TH BGCOLOR=#6699CC>Purpose</TH>
<TH BGCOLOR=#6699CC>Design Pattern</TH>
<TH BGCOLOR=#6699CC>Aspect(s) That Can Vary</TH>
</TR>
<TR VALIGN=TOP>
<TD ROWSPAN=5><B>Creational</B></TD>
<TD>Abstract Factory </TD>
<TD>families of product objects</TD>
<TR VALIGN=TOP>
<TD>Builder </TD>
<TD>how a composite object gets created</TD>
<TR VALIGN=TOP>
<TD>Factory Method </TD>
<TD>subclass of object that is instantiated</TD>
<TR VALIGN=TOP>
<TD>Prototype </TD>
<TD>class of object that is instantiated</TD>
<TR VALIGN=TOP>
<TD><A HREF="#Singleton" >Singleton</A> </TD>
<TD>the sole instance of a class</TD>
<TR VALIGN=TOP>
<TD ROWSPAN=7><B>Structural</B></TD>
<TD>Adapter </TD>
<TD>interface to an object</TD>
<TR VALIGN=TOP>
<TD>Bridge </TD>
<TD>implementation of an object</TD>
<TR VALIGN=TOP>
<TD><a href="#Composite">Composite </a></TD>
<TD>structure and composition of an object</TD>
<TR VALIGN=TOP>
<TD>Decorator </TD>
<TD>responsibilities of an object
without subclassing</TD>
<TR VALIGN=TOP>
<TD>Facade </TD>
<TD>interface to a subsystem</TD>
<TR VALIGN=TOP>
<TD>Flyweight </TD>
<TD>storage costs of objects</TD>
<TR VALIGN=TOP>
<TD>Proxy </TD>
<TD>how an object is accessed; its location</TD>
<TR VALIGN=TOP>
<TD ROWSPAN=11><B>Behavioral</B></TD>
<TD>Chain of Responsibility </TD>
<TD>object that can fulfill a request</TD>
<TR VALIGN=TOP>
<TD>Command </TD>
<TD>when and how a request is fulfilled</TD>
<TR VALIGN=TOP>
<TD>Interpreter </TD>
<TD>grammar and interpretation of a language</TD>
<TR VALIGN=TOP>
<TD>Iterator </TD>
<TD>how an aggregate's elements are accessed, traversed</TD>
<TR VALIGN=TOP>
<TD>Mediator </TD>
<TD>how and which objects interact with each other</TD>
<TR VALIGN=TOP>
<TD>Memento </TD>
<TD>what private information is stored outside an object, and when</TD>
<TR VALIGN=TOP>
<TD><A HREF="#Observer" >Observer </A></TD>
<TD>number of objects that depend on another object; how the dependent
objects stay up to date</TD>
<TR VALIGN=TOP>
<TD>State </TD>
<TD>states of an object</TD>
<TR VALIGN=TOP>
<TD>Strategy </TD>
<TD>an algorithm</TD>
<TR VALIGN=TOP>
<TD>Template Method </TD>
<TD>steps of an algorithm</TD>
<TR VALIGN=TOP>
<TD>Visitor </TD>
<TD>operations that can be applied to object(s)
without changing their class(es)</TD>
</TABLE>
</BLOCKQUOTE>
<a name="Singleton"> </a>
<H4><a href="http://www.bearguru.com/projects/XPDPTL/GOF/hires/pat3efs.htm">The Singleton Pattern</a>
<a href="include/Patterns/Singleton.h">Singleton.h</a>
<a href="http://www.bearguru.com/projects/XPDPTL/GOF/html/Singleton.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">
Singleton is probably the most widely used design pattern. Its intent is to ensure that a class has only one instance, and to provide a global point of access to it. The Singleton pattern provides an elegant solution to this problem by making the class itself responsible for managing its sole instance. The sole instance is an ordinary object of its class, but that class is written so that only one instance can ever be created. This way, you guarantee that no other instance can be created. Furthermore, you provide a global point of access to that instance. The Singleton class hides the operation that creates the instance behind a static member function. This member function, traditionally called instance(), returns a pointer to the sole instance.
<p></p>
The Singleton pattern of XPDPTL offers a reusable mechanism to manage the creation and release of Singleton. Particularly, it addresses the two main issues :
<ul>
<li>Decoupling the real type of object being Singleton from the Singleton implementation</li>
<li>Decoupling memory allocation and cleanup of the Singleton object from its usage </li>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -