Containment Delegation  «Prev  Next»
Lesson 9 Containment/delegation issues
Objective Understand some of the issues encountered when using containment/delegation.

Containment and Delegation Issues in COM

Using containment/delegation, we can reuse any COM object. First, we design the outer COM object with interfaces that mirror one or more interfaces in an inner COM object. Next, we write code in the outer COM object that creates an instance of the inner COM object and, in the mirrored interfaces, delegates calls into the inner COM object.
One issue with using containment/delegation is that we always have to add additional interfaces into the outer object. If the outer object simply passes calls through to the inner object (that is, the outer object does not filter data or method calls), we incur a development time and performance penalty. We lose time on the development side specifying and implementing pass-through interfaces in the outer COM object. We lose time when the object is running code that simply passes through calls into the inner COM object. The performance problem incurred when using containment/delegation is especially acute when the level of nested containment is deep. For example, consider a case where object A uses B, object B uses C, and object C uses D:

Performance problem when using containment/delegation
Performance problem when using Containment and Delegation
Notice how calling methods in Interface4 require three pass-through delegation calls in objects A, B, and C.
Is there a way to create a composite COM object without incurring the development and performance overhead depicted in the nested containment/delegation scenario presented above? Yes. COM's other reusability mechanism which is aggregation, provides a mechanism that allows us to create such an object.

COM Reusability Mechanisms

The key point to building reusable components is black-box reuse which means the piece of code attempt-ing to reuse another component knows nothing, and does not need to know anything, about the internal structure or implementation of the component being used. In other words, the code attempting to reuse a component depends upon the behavior of the component and not the exact implementation. To achieve black-box reusability, COM supports two mechanisms through which one object may reuse another. For convenience, the object being reused is called the inner object and the object making use of that inner object is the outer object.
  1. Containment/Delegation: the outer object behaves like an object client to the inner ob-ject. The outer object contains the inner object and when the outer object wishes to use the services of the inner object the outer object simply delegates implementation to the inner object’s interfaces. In other words, the outer object uses the inner’s services to im-plement itself. It is not necessary that the outer and inner objects support the same inter-faces; in fact, the outer object may use an inner object's interface to help implement parts of a different interface on the outer object especially when the complexity of the inter-faces differs greatly.
  2. Aggregation: the outer object wishes to expose interfaces from the inner object as if they were implemented on the outer object itself. This is useful when the outer object would always delegate every call to one of its interfaces to the same interface of the inner object. Aggregation is a convenience to allow the outer object to avoid extra implementation overhead in such cases.

These two mechanisms are illustrated in Figures 2-9 and 2-10 (in lesson 10). The important part to both these mechanisms is how the outer object appears to its clients. As far as the clients are concerned, both objects implement interfaces A, B, and C. Furthermore, the client treats the outer object as a black box, and thus does not care, nor does it need to care, about the internal structure of the outer object, since the client only cares about behavior. Containment is simple to implement for an outer object: during its creation, the outer object creates whatever inner objects it needs to use as any other client would. The process is like a C++ object that itself contains a C++ string object that it uses to perform certain string functions even if the out-er object is not considered a string object in its own right.

Containment of an inner object and delegation to its interfaces.
Figure 2-9: Containment of an inner object and delegation to its interfaces.