Event driven processing is found in almost every user interface, communication subsystem, and is pervasive in the design of operating systems.
A model of window event handling for the Windows operating system is shown in the diagram, below.
Windows Event Processing
Windows Event Handling
Input device events generate messages, created by their device drivers, which are all routed into a raw input queue. These are dequeued by
the window manager and routed to the appropriate window's message queue, e.g., that of the top-most window covering the current mouse coordinates
when a mouse button is clicked, for example.
The UI thread of each window blocks on its message queue until a message arrives. Then, the UI thread routes the message to an event handler.
How does that happen? Well, the application program that created the window defined event handlers for the events it wanted to process and
registered them with the Windows event dispatching mechanism. Exactly how that happens, from the application point of view, depends on whether
the application is using the Windows API or some framework like WPF, WinForms, or MFC to implement its processing.
.Net Delegate Structure
.Net Event Handling
Let's identify code that has events to publish as "Publisher" packages, and code that wants to react to those events
as "Subscriber" packages.
The Publisher creates instance of a class derived from MulticastDelegate and exposes it as a public resource.
Its purpose is to hold references to functions called when a specific event occurs. Here, the event is just something that happend in the
application code that the designer thinks of as significant. The Publisher part of the code that generates the event invokes its delegate
to, in turn, invoke function references it holds to subscriber's event handlers. These references came from subscriber code, during its
initialization.
This apparatus decouples the Publisher and Subscriber. The Publisher doesn't need to know anything about the Subscriber
or its event handlers, and the Subscriber doesn't need to know anything about how the event got generated in the Publisher. It only knows
that the Publisher exposes a delegate that it promises to call when the event occurs.
Event Triggers Invocation of Invokers Commands
Command Pattern Event Handling
The Command Pattern generalizes the notion of a delegate. Actually the Command Pattern was invented first, and oddly, .Net decided to
use a less flexible delegate structure.
The Command Pattern is composed of an Invoker type that plays the same role as the .Net Delegate. However, it binds to a command interface
that can be implemented by derived classes to call global or member functions of any desired signature. Since the invoker binds to the
interface, the invoker can hold a mix of derived command types and hence call any type of handler. The derived concrete command objects
are responsible for acquiring any data necessary to pass to the event handlers in its receiver.
Think of the library code as Publisher and the client code as subscriber.
Conclusions for Delegation and Events:
One important design goal for event handling is to decouple event publishers from event subscribers.
.Net Delegates allow the publisher to be entirely ignorant of the subscribers. It doesn't need to know how many nor their types.
Subscribers need to know the publisher and its delegate types, but don't need to know any details of how the event generation is
implemented.
Because of the way Delegates are implemented, each Delegate type can hold references to functions with only one specified signature, but
that function can be a member of any type.
Command Pattern event handling also decouples Publisher and Subscriber, but in a slightly more flexible way than the .Net Delegate.
Since the concreteCommand objects derive from command and are implemented by the Subscriber, their execute methods can hold
references to functions of any signature, and the invoker can hold any mixture of concreteCommand objects needed for the application.