The design of hush and its extensions can be understood by a consideration of two basic patterns and their associated idioms, that is the nested-component pattern (which allows for nesting components that have a similar interface) and the actor pattern (which allows for attributing different modes or roles to objects). The realizations of these patterns are based on idioms that extend an improved version of the familiar handle/body idiom. Our improvement concerns the introduction of an explicit invocation context which is needed to repair the disruption of the virtual function call mechanism caused by the delegation to `body implementation' objects.
In this section, we will first discuss the handle/body idiom and its improvement. Then we will discuss the two basic patterns underlying the design of hush and we will briefly sketch their realization by extensions of the (improved) handle/body idiom.
The (improved version of) the idiom is frequently used
in the hush class library.
The widget library is build of a stable
interface hierarchy, offering several common GUI widgets classes like
buttons, menus and scrollbars. The widget (handle) classes are
implemented by a separate, hidden implementation hierarchy, which
allows for changing the implementation of the widget library, without the
need to recompile dependent applications. Additionally, the idiom
helps us to ensure that the various widget implementations are used in
a consistent manner.
The nested component pattern
The nested component pattern is closely
related to the Decorator pattern treated in
The nested component pattern is realized by applying the virtual self-reference idiom. Key to the implementation of that idiom is the virtual self() member of a component. The self() member returns a reference to the object itself (e.g. this in C++) by default, but returns the inner component if the outer object explicitly delegated its functionality by using the redirect() method. Note that chasing for self() is recursive, that is (widget) components can be nested to arbitrary depth. The self() member must be used to access the functionality that may be realized by the inner component.
The nested component pattern is employed
in designing the hush widget hierarchy.
Every (compound) widget
can delegate part of its functionality to an inner component.
It is common practice to derive a compound widget from another
widget by using interface inheritance only, and to delegate
functionality to an inner component by explicit redirection.
The actor pattern
Changing roles or modes can be regarded
as some kind of state transition, and
indeed the actor pattern
(and its associated dynamic role-switching idiom)
is closely related to the
State pattern treated in
The realization of the actor pattern employs the dynamic role-switching idiom, which is implemented by extending the handle class with a set of several bodies instead of only one. To enable role-switching, some kind of indexing is needed. Usually, a dictionary or a simple array of roles will be sufficient.
In the hush library the actor pattern is used to give access to multiple interpreters via the same interface class (i.e. the kit class). The pattern is essential in supporting the multi-paradigm nature of the DejaVU framework. In our description of the design of the Web components in section Web, we will show how dynamic role-switching is employed for using various network protocols via the same (net)client class. The actor pattern is also used to define a (single) viewer class that is capable of displaying documents of various MIME-types (including SGML, HTML, VRML).