June 26, 2008
Event-Based ArchitecturesHow Notifications Travel
The most well-known delivery mechanism for sending notifications from one part to another uses indirect method calls, but there are other mechanisms. With indirect method calls, there are essentially two different ways to deliver notifications:
Languages such as Java and C++ natively support typed calls. Languages such as C#, VB.NET, and Delphi support both typed and untyped calls. Java programmers can also use untyped calls, but need to resort to reflection and Method.invoke() to do so.
In Figure 1, assume you have two classes A and B, which interact using notifications. When some event occurs in A, you want B.DoSomething() to be executed. To achieve this, A will have to send a notification to B. To send notifications using typed calls, class A needs to contain a field referencing type B. At runtime, this reference is somehow set; for this example, it doesn't matter how or when. When firing the event, class A invokes the method B.DoSomething() on the referenced object using code of the form:
[Click image to view at full size]
Figure 1: Two classes that interact using notifications.
To send notifications using untyped calls, class A needs to have a field referencing not type B, but a method with the signature of B.DoSomething(). In .NET languages, delegates are language-defined entities that can point to methods with a given signature. In C#, class A might have a delegate defined like this:
The delegate can then be used to define a field to hold a reference to a method with the given signature:
At runtime, myHandler would be initialized somehow (the details of which are not important here) to point at the method DoSomething of some instance of class B. Class A would then use this code to fire an event:
In Java, the same thing can be accomplished using reflection with Method.invoke(). Class A would need to have a field of type Method. At runtime, class A would need to initialize the Method field to point to method DoSomething() of some instance of B. Class A would then use the Method field to invoke B.DoSomething().
Typed and untyped calls achieve the same net result (invoking DoSomething() on an instance of class B), but with important differenceswith typed calls, class A must know about type B, so A must be created with the knowledge of B. Also, any objects that wish to handle notifications from A need to be of type B, or derived from B. With untyped calls, A does need to know about type B. Objects wishing to handle notifications from A don't need to be of any special type. How important this distinction is usually depends on the size of the system you're building, and whether you have control of both the sender and receiver of notifications.
|
|
||||||||||||||||||||||||||||||
|
|
|
|