Frameworks vs. Patterns, Pattern Selection, and the Lexi Document Editor Case Study
This section covers the distinction between frameworks and design patterns, practical strategies for selecting and applying patterns, and begins an extended case study designing a WYSIWYG document editor called Lexi. The case study demonstrates how design problems naturally lead to specific patterns — Composite for document structure and Strategy for formatting algorithms.
Key Concepts
Frameworks vs. Design Patterns: Three key differences — (1) patterns are more abstract (frameworks are concrete code, patterns must be re-implemented each time), (2) patterns are smaller (a framework contains several patterns, never vice versa), (3) patterns are less specialized (frameworks target specific domains, patterns apply across domains)
Frameworks and reuse: Mature frameworks incorporate several design patterns. Documenting a framework with its patterns accelerates learning and reduces the steep learning curve
Recursive composition: Building complex elements from simpler ones — characters form lines, lines form columns, columns form pages. Each element (visible or structural) is represented as an object
Glyph: Abstract class for all objects in the document structure. Three responsibilities: (1) draw themselves, (2) report space occupied, (3) manage children and parent
Uniform treatment: Text and graphics share the same interface — no special-casing. Single elements and groups of elements are treated uniformly
Composition/Compositor separation: Composition holds the glyphs; Compositor encapsulates the formatting algorithm. The compositor inserts structural glyphs (Row, Column) into the composition's children
Design patterns should not be applied indiscriminately — they introduce indirection that can complicate design and cost performance. Apply only when the flexibility is actually needed
7. Implement operations per responsibilities and collaborations
Relationships
Composite pattern — captures recursive composition; used for Lexi's document structure where glyphs contain child glyphs uniformly
Strategy pattern — encapsulates interchangeable algorithms; used for formatting via Compositor subclasses (SimpleCompositor, TeXCompositor)
Flyweight pattern — referenced as applicable to share glyph objects and reduce storage costs (not implemented in the example)
Table 1.2 maps each pattern to the design aspect it lets you vary — e.g., Factory Method varies "subclass of object instantiated," Observer varies "number of dependent objects," Strategy varies "an algorithm"
Decorator pattern — foreshadowed for embellishing the user interface (scroll bars, borders, drop shadows)
Abstract Factory — foreshadowed for supporting multiple look-and-feel standards
Exam-Relevant Points
Frameworks contain patterns, never vice versa — a framework embodies multiple patterns; a pattern is a smaller architectural element
Table 1.2: Know which design aspect each pattern encapsulates — Abstract Factory: families of product objects; Bridge: implementation of an object; Composite: structure and composition; Decorator: responsibilities without subclassing; Strategy: an algorithm; Template Method: steps of an algorithm; Visitor: operations without changing classes
Six strategies for selecting a pattern: (1) match to design problem categories, (2) scan Intent sections, (3) study pattern interrelationships, (4) compare patterns of like purpose, (5) examine causes of redesign, (6) consider what should be variable
Composition vs. Compositor: Composition is the context (holds glyphs), Compositor is the strategy (algorithm). Compositor can be changed at run-time via SetComposition
Glyph's three responsibilities: drawing, space reporting, child/parent management
Anti-pattern warning: Don't apply patterns when the flexibility they provide isn't needed — unnecessary indirection adds complexity and costs performance