Download presentation
Presentation is loading. Please wait.
1
Basic Design Patterns 2. Designing a Document Editor Gabriel Mañana Ed. 453 Of. 120 Ext. 14080 gjmananag @ unal.edu.co
2
Basic Design Patterns Document Structure Formatting User Interface Supporting Look & Feel Standards Supporting Window Systems User Operations Spelling Checking & Hyphenation
3
Basic Design Patterns Document Structure (Composite) The choice of internal representation for the document affects nearly every aspect of the editor’s design. All editing, formatting, displaying and textual analysis will require traversing the representation. The way we organize this information will impact the design of the rest of the application.
4
Document Structure page column paragraph text line chars table image...
5
Document Structure Maintaining the document’s physical structure, that is, the arrangement of text and graphics into lines, columns, tables, etc. Generating and presenting the document visually Mapping positions on the display to elements in the internal representation T he internal representation should support:
6
Constraints: It should treat text and graphics uniformly The implementation shouldn’t have to distinguish between single elements and groups of elements in the internal representation classes must have compatible interfaces It should treat text and graphics uniformly The implementation shouldn’t have to distinguish between single elements and groups of elements in the internal representation classes must have compatible interfaces Document Structure
7
Glyph draw(Window) intersects(Point) insert(Glyph, int) Character draw(Window w) intersects(Point p) char c Rectangle draw(...) intersects(...) Row draw(Window w) intersects(Point p) insert(Glyph, int) Polygon draw(...) intersects(...) return true if p intersects this character w->drawChar(c)insert g into children at position i for all c in children if c->intersects(p) return true for all c in children ensure c position c->draw(w) Recursive Composition children
8
Recursive composition is good for more than just documents. It can be used to represent any potentially complex, hierarchical structure. The Composite pattern captures the essence of recursive composition in object-oriented terms. Composite Pattern
9
Basic Design Patterns Formatting (Strategy) How does the editor arrange text and graphics into lines and columns? What objects are responsible for carrying out different formatting policies? How do these policies interact with the document’s internal representation?
10
Basic Design Patterns Formatting ResponsibilityOperation what to formatvoid setComposition( Composition ) when to formatvoid compose() we’ll define a Compositor class for objects that can encapsulate a formatting algorithm the glyphs it formats are the children of a special Glyph subclass called Composition we’ll define a Compositor class for objects that can encapsulate a formatting algorithm the glyphs it formats are the children of a special Glyph subclass called Composition
11
Glyph insert(Glyph, int) Composition insert(Glyph, int) Compositor compose() setComposition() Glyph::insert(g, i) compositor.compose() children Strategy ArrayCompositor compose() TeXCompositor compose() SimpleCompositor compose() compositor composition
12
Encapsulating an algorithm in an object is the intent of the Strategy pattern. The key participants in the pattern are strategy objects and the context in which they operate. Compositors are strategies; they encapsulate different formatting algorithms. A Composition is the context for a Compositor strategy. Strategy Pattern
13
Basic Design Patterns User Interface (Decorator) The editor’s UI includes scroll-bars, borders and drop shadows. Such embellishments are likely to change as the editor’s UI evolves. Hence it is important to be able to add and remove embellishments easily without affecting the rest of the application.
14
Basic Design Patterns User Interface Embellishing the users interface involves extending existing code. Using inheritance to do such extension precludes rearranging embellishments at run- time. An equally serious problem, is the explosion of classes that can result from an inheritance- based approach.
15
CompositionScrollableCompositionBorderedCompsosition
16
CompositionScrollableCompositionBorderedCompsositionBorderedScrollableComposition
17
Object composition offers a potentially more workable and flexible extension mechanism: Since we know we’re embellishing an existing glyph, we could make the embellishment itself an object (class Border f.i.) Glyph and Border: the next step is to decide who composes whom If we put the Border in the Glyph then we must make modifications to all Glyph subclasses to make them aware of the border User Interface
18
All this lead us to the concept of transparent enclosure, which combines the notions of User Interface (1)single child (or single-component) composition, and (2)compatible interfaces Clients generally can’t tell whether they’re dealing with the component or its enclosure: the enclosure delegates all its operations to its component and augments the component’s behaviour by doing work of its own (before or after) delegating an operation.
19
Glyph draw(Window) MonoGlyph draw(Window) Scroller draw(Window) Monoglyph component Border draw(Window) drawBorder(Window)
20
The Decorator pattern captures class and object relationships that support “embellishment” by transparent enclosure. In the Decorator pattern, “embellishment” referes to anything that adds responsibilities to an object. Decorator Pattern
21
Basic Design Patterns Supporting multiples L&F Standards (Abstract Factory) The editor should adapt easily to different look-and-feel standards such as Motif and Windows GUI without major modification.
22
GUIFactory createButton() createMenu()... return new MotifMenu return new MotifButton MotifFactory createButton() createMenu()... return new WindowMenu return new WindowButton WindowsFactory createButton() createMenu()... return new MacMenu return new MacButton MacFactory createButton() createMenu()... Factory Hierarchy
23
Glyph... Button pressed()... Menu popup()... MotifButton pressed()... MacButton pressed()... WindowsButton pressed()... MotifMenu popup()... MacMenu popup()... WindowsMenu popup()... Product Hierarchy
24
Factories and Products are the key participants in the Abstract Factory pattern. This pattern captures how to create families of related product objects without instantiating classes directly. It’s most appropriate when the number and general kinds of products objects stay constant, and there are differences in specific product families. Abstract Factory Pattern
25
The Abstract Factory pattern’s emphasis on families of products distinguishes it from other creational patterns, which involve only one kind of product object. Abstract Factory Pattern
26
Basic Design Patterns Supporting multiples Window Systems (Bridge) Different look-and-feel standards are usually implemented on different window systems. The editor’s design should be as independent of the window system as possible.
27
Basic Design Patterns Can we use an Abstract Factory? At first glance this may look like another opportunity to apply the Abstract Factory pattern. But the constraints for window system portability differ significantly from those for look-and-feel independence.
28
Basic Design Patterns Answer: NO In applying the Abstract Factory pattern, we assumed that we would define the concrete widget glyphs classes for each L&F standard. It’s highly unlikely that window class hierarchies from different vendors are compatible in any way. Hence, we won’t have a common abstract product for each kind of widget (ScrollBar, Button, etc.)
29
Basic Design Patterns We have to make the different widget hierarchies adhere to a common set of abstract product interfaces. Only then could we declare the create...() operations properly in our abstract factory’s interface. We need a uniform set of windowing abstractions that let us take different window system implementations and slide any one of them under a common interface.
30
Basic Design Patterns Encapsulating Implementation Dependencies The Window class encapsulates the things that windows tend to do across window systems: Provide operations for drawing basic geometric shapes Iconify and de-iconify themselves Resize themselves (Re)draw their contents on demand
31
Basic Design Patterns Two extreme philosophies: The Window class must span the functionality of windows from different window systems: 1.Intersection of functionality The window class provides only functionality that’s common to all window systems 2.Union of functionality Create an interface that incorporates the capabilities of all window systems
32
Basic Design Patterns Window class interface ResponsibilityOperations window management virtual void redraw() virtual void raise() virtual void lower() virtual void iconify() virtual void deiconify()... graphicsvirtual void drawLine() virtual void drawRect() virtual void drawText()...
33
glyph Glyph draw( Window ) Window redraw() iconify()... drawLine() drawText()... owner->lower() IconWindow iconify() DialogWindow lower() FrameWindow glyph->draw( this ) owner
34
Basic Design Patterns Now we have defined a window interface for the document editor to work with, where does the real platform-specific window come in? We can do the same thing we did for formatting and embellishment, namely, encapuslate the concept that varies.
35
Window raise()... drawText()... IconWindowDialogWindowFrameWindow imp WindowImp deviceRaise()... deviceText()... XWindowImp deviceRaise() MSWindowImp deviceRaise() MacWindowImp deviceRaise()
36
The intent behind Bridge is to allow separate class hierarchies to work together even as they evolve independently. The Bridge pattern lets us maintain and enhance our logical window abstractions without touching window system- dependent code, and vice versa. Bridge Pattern
37
Basic Design Patterns User Operations (Command) Users control the editor through various user interfaces, including buttons and pull-down menus. The functionality behind these interfaces is scattered throughout the objects in the application. The challenge here is to provide a uniform mechanism both for accessing this scattered functionality and for undoing its effects.
38
Command execute() paste m_buffer into document PasteCommand execute() --------------- m_buffer make selected text appear in m_font FontCommand execute() --------------- m_font pop up a dialog box that lets the user name the document and then save the document SaveCommand execute() Command Hierarchy
39
GlyphMenuItem clicked() MenuItem- Command command Command execute() command->execute()
40
The Command pattern describes how to encapsulate a request. It prescribes a uniform interface for issuing requests that lets you configure clients to handle different requests. The interface shields clients from the request’s implementation. Command Pattern
41
Basic Design Patterns Spelling Checking and Hyphenation (Iterator/Visitor) How does the editor support analytical operations such as checking for misspelled words and determining hyphenation points? How can we minimize the number of classes we have to modify to add a new analytical operation?
42
Basic Design Patterns Spelling Checking and Hyphenation As was the case with line-breaking strategies, there’s more than one way to check spelling and compute hyphenation points. So here too we want to support (and add easily) multiple algorithms. We also want to avoid wiring this functionality into the document structure.
43
Basic Design Patterns Spelling Checking and Hyphenation There are actually two pieces to this puzzle: 1.accessing the information to be analyzed, which we have scattered over the glyphs in the document structure, and 2.doing the analysis.
44
Basic Design Patterns Spelling Checking and Hyphenation The text we need to analyse is scattered throughout a hierarchical structure of glyphs objects. Some glyphs might store their children in linked lists, others might use arrays, and still others might use more esoteric data structures. The access mechanism must be able to handle all of these possibilities.
45
Basic Design Patterns Encapsulating Access and Traversal An important role of the glyphs abstraction is to hide the data structure in which children are stored. That way we can change the data structure a glyph class uses without affecting other classes. We can solve this problem and support several different kinds of traversals at the same time.
46
Basic Design Patterns Encapsulating Access and Traversal We can add the following abstract operations to the Glyph’s interface: void first( Traversal ) void next() boolean isDone() Glyph current() void insert( Glyph )
47
Iterator first() next() isDone() current() return trueglyph->draw( this ) iterators PreorderIterator first() next() isDone() current() ArrayIterator first() next() isDone() current() currentItem ListIterator first() next() isDone() current() NullIterator first() next() isDone() current() Glyph... createIterator() root return new NullIterator 1..*
48
The Iterator pattern captures the techniques for supporting access and traversal over object structures. It’s applicable not only to composite structures but to collections as well. Iterator Pattern
49
The Iterator pattern abstracts the traversal algorithm and shields clients from the internal structure of the objects (containers) they traverse. It illustrates once more how encapsulating the concept that varies helps us gain flexibility and reusability. Iterator Pattern
50
Basic Design Patterns Traversal vs. Traversal Actions Now that we have a way of traversing the glyph structure we can check the spelling and do the hyphenation. Both analyses involves accumulating information during the traversal. First we have to decide where to put the responsibility for analysis (1. iterator classes, 2. glyph classes, 3. separate class).
51
Basic Design Patterns Traversal vs. Traversal Actions 1. Different analyses might require the same kind of traversal: analysis and traversal should be separate. 2. We’ll have to change every glyph class whenever we add a new kind of analysis. 3.We need to encapsulate the analysis in a separate object: the iterator would “carry” the instance to each glyph in the structure.
52
Basic Design Patterns Traversal vs. Traversal Actions The fundamental question with this approach is how the analysis object distinguishes different kinds of glyphs without resorting to type tests or downcasts:
53
Basic Design Patterns Traversal vs. Traversal Actions void SpellingChecker::check( Glyph g ) { Char c; Row r; Image i; if (c = dynamic_cast ( g )) {... // else, else
54
Basic Design Patterns Traversal vs. Traversal Actions void Glyph::checkMe( SpellingChecker )
55
Basic Design Patterns Traversal vs. Traversal Actions void GlyphSubClass::checkMe( SpellingChecker checker ) { checker.checkGlyphSubClass( this ); }
56
Basic Design Patterns Traversal vs. Traversal Actions Using overloading: void GlyphSubClass::checkMe( SpellingChecker checker ) { checker.check( this ); }
57
Basic Design Patterns Traversal vs. Traversal Actions This approach works for finding spelling errors, but how does it help us support multiple kinds of analyses? It looks like we have to add an operation like checkMe( SpellingChecker ) to Glyph and its subclasses whenever we add a new kind of analysis.
58
Basic Design Patterns Traversal vs. Traversal Actions We’ll use the term visitor to refer generally to classes of objects that “visit” other objects during a traversal and do something appropriate.
59
Basic Design Patterns Traversal vs. Traversal Actions abstract class Visitor { public void visit( Char ); public void visit( Row ); public void visit( Image );... } (polymorphism)
60
Basic Design Patterns Traversal vs. Traversal Actions void Glyph::visitMe( Visitor v ) { v.visit( this ); } Now adding a new analysis requires just defining a new subclass of Visitor : we don’t have to touch any of the Glyph classes.
61
The Visitor class and its subclasses described are the key particpants in the pattern. Visitor lets you define a new operation without changing the classes of the elements on which it operates. Visitor Pattern
62
Summary 1.Composite to represent the document’s physical structure 2.Strategy to allow different formatting algorithms 3.Decorator for embellishing the user interface 4.Abstract Factory for supporting multiple look & feel standards
63
Summary 5.Bridge to allow multiple windowing platforms 6.Command for undoable user operations 7.Iterartor for accessing and traversing object structures 8.Visitor for allowing an open-ended number of analytical capabilities without complicating the document’s structure implementation
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.