Decoupling Interfaces from Implementations
Readers of Design Patterns (see the Bibliography) may recognize handle-body as an alias for the Bridge Pattern. The intent of Bridge is to “decouple an abstraction from its implementation so that the two can vary independently.” While the full implications of the Bridge pattern are beyond the scope of this guide, the primary benefit, again, is simplicity. Handle-body allows for simplicity without giving up flexibility. Often the complexity of a class hierarchy stems from implementation considerations, like the desire to reuse certain code or variations in how an object must accomplish its task. In many cases, these variations can and should be hidden from the user. For example, a printer object should have the same simple interface regardless of the brand of printer that is currently selected. Behind the scenes, however, each printer probably requires its own class to issue commands peculiar to its brand. A single printer handle can point to any of many printer implementation bodies. Not only does the user deal with one simple interface, but the handle also takes care of which concrete body to instantiate. With a single hierarchy, on the other hand, the user would have to figure out which printer is currently selected in the application and instantiate the appropriate one.
Now imagine you want to extend your printer hierarchy by adding a two-sided printer class. Here’s where the separation of interface from implementation really pays off. You can simply derive, say, handle class TwoSidedPrinter from handle class Printer. This is all the user needs to see. On the body side, you now have different brands, as well as one- and two-sided printers within those brands. Trying to do this all within one class hierarchy is difficult. Handle-body makes it clean. In Threads Module, the use of handle-body in the Functor package is a prime example.