You are on page 1of 5

Design Patterns: Elements of Reusable Object-Oriented Software

encapsulating it in an object.More specifically, we'll define a separate classhierarchy for objectsthat encapsulate formatting algorithms. The root of thehierarchy willdefine an interface that supports a wide range offormattingalgorithms, and each subclass will implement the interface to carryouta particular algorithm. Then we can introduce a Glyph subclassthat will structureits children automatically using a given algorithmobject. Compositor and Composition We'll define a Compositor class for objectsthat can encapsulate a formattingalgorithm. The interface (Table 2.2) letsthe compositor know what glyphs to formatand when to do the formatting. The glyphs it formats are the children ofa specialGlyph subclass called Composition . Acomposition gets an instance of a Compositorsubclass (specializedfor a particular linebreaking algorithm) when it is created,andit tells the compositor to Compose its glyphs whennecessary, for example, whenthe user changes a document.Figure 2.5 depicts the relationships between theComposition and Compositor classes. Responsibility Operations what to format void SetComposition(Composition*)when to format virtual void Compose() Table 2.2 Basic compositor interfaceFigure 2.5: Composition and Compositor class relationshipsAn unformatted Composition object contains only the visibleglyphs that make upthe document's basic content. It doesn't containglyphs that determine the

Design Patterns: Elements of Reusable Object-Oriented Software document's physical structure, such asRow and Column. The composition is in thisstate just after it'screated and initialized with the glyphs it should format.Whenthe composition needs formatting, it calls its compositor'sCompose operation.The compositor in turn iteratesthrough the composition's children and insertsnew Row and Columnglyphs according to its linebreaking algorithm. Figure 2.6 showsthe resulting objectstructure. Glyphs that the compositor created and insertedintothe object structure appear with gray backgrounds in the figure.Figure 2.6: Object structure reflectingcompositor-directed linebreakingEach Compositor subclass can implement a different linebreaking algorithm.Forexample, a SimpleCompositor might do a quick pass without regard forsuch esotericaas the document's "color." Good color means having an evendistribution of textand whitespace. A TeXCompositor would implement thefull TeX algorithm [Knu84],which takes things like color into accountin exchange for longer formatting times.The Compositor-Composition class split ensures a strong separationbetween codethat supports the document's physical structure and thecode for differentformatting algorithms. We can add new Compositorsubclasses without touching theglyph classes, and vice versa. Infact,

we can change the linebreaking algorithmat run-time by adding asingle SetCompositor operation to Composition's basicglyphinterface. Strategy Pattern Encapsulating an algorithm in an object is the intent of the Strategy (349) pattern.The key participants in thepattern are Strategy objects (which encapsulatedifferent algorithms)and the context in which they operate. Compositors are

Design Patterns: Elements of Reusable Object-Oriented Software


strategies;they encapsulate different formatting algorithms. A composition isthecontext for a compositor strategy.The key to applying the Strategy pattern is designing interfaces forthe strategyand its context that are general enough to support arange of algorithms. Youshouldn't have to change the strategy orcontext interface to support a newalgorithm. In our example, thebasic Glyph interface's support for child access,insertion, andremoval is general enough to let Compositor subclasses changethedocument's physical structure, regardless of the algorithm they use todo it.Likewise, the Compositor interface gives compositions whateverthey need toinitiate formatting. Embellishing the User Interface

We consider two embellishments in Lexi's user interface. Thefirst adds a borderaround the text editing area to demarcate the pageof text. The second adds scrollbars that let the user view differentparts of the page. To make it easy to addand remove theseembellishments (especially at run-time), we shouldn't useinheritanceto add them to the user interface. We achieve the most flexibilityifother user interface objects don't even know the embellishments arethere. Thatwill let us add and remove the embellishments withoutchanging other classes. Transparent Enclosure From a programming point of view, embellishing the user interface involvesextending existing code. Using inheritance to do such extensionprecludesrearranging embellishments at run-time, but an equally serious problemis the explosion of classes that can result from an inheritancebasedapproach.We could add a border to Composition by subclassing it to yieldaBorderedComposition class. Or we could add a scrolling interface inthe same wayto yield a ScrollableComposition. If we want both scrollbars and a border, wemight produce a BorderedScrollableComposition,and so forth. In the extreme, weend up with a class for everypossible combination of embellishments, a solutionthat quicklybecomes unworkable as the variety of embellishments grows.Object composition offers a potentially more worka

You might also like