1 / 73

A Case Study: Designing a Document Editor

A Case Study: Designing a Document Editor. ZHAO Jianhua Dept. of Computer Sci&Tech, Nanjing University. Overview of This Case Study. A WYSIWYG document editor called Lexi. The document can mix text and graphics freely in a variety of formatting styles. Eight design patterns are illustrated.

ellie
Télécharger la présentation

A Case Study: Designing a Document Editor

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. A Case Study:Designing a Document Editor ZHAO Jianhua Dept. of Computer Sci&Tech, Nanjing University

  2. Overview of This Case Study • A WYSIWYG document editor called Lexi. • The document can mix text and graphics freely in a variety of formatting styles. • Eight design patterns are illustrated. • Using this case study to show • What is design patterns. • How to use design patterns. • Each time we meet a pattern in the case study, we will study the detail of the pattern.

  3. Design Problems • Seven problems in Lexi’s design: (1,2) • Document structure: The choice of internal representation for the document. • Formatting: How to arrange the text and graphics? What objects are responsible for different formatting policies? How do these policies interact with the document’s internal representation?

  4. Design problems • Seven problems in Lexi’s design: (3,4) • Embellishing the user interface. How to design the system such that the embellishment can be easily added or removed? • Supporting multiple look-and-feel standards: Lexi should adapt easily to different look-and-feel standards.

  5. Design Problems • Seven problems in Lexi’s design: (5,6) • Supporting multiple window systems. Lexi should be as independent of the window system as possible. • User operations. To provide a uniform mechanism both for accessing this scattered functionality and for undoing its effects.

  6. Design problems • Seven problems in Lexi’s design: (7) • Spelling checking and hyphenation: How does Lexi support analytical operations such as checking for misspelled words and determining hyphenation points?

  7. Document Structure • A document is ultimately just an arrangement of basic graphical elements. • An author often views these elements in terms of the physical structure: lines, columns, figures, … • Lexi’s user interface should let users manipulate these structure directly.

  8. The goal • The internal representation should support: • Maintaining the document’s physical structure. • Generating and presenting the document visually. • Mapping positions on the display to elements in the internal representation.

  9. The constraints • We should treat text and graphics uniformly. • Our implementation shouldn’t have to distinguish between single elements and groups of elements in the internal representation. • The need to analyze the text for such things as spelling errors and potential hyphenation.

  10. Recursive Composition • A common way to represent hierarchically structed information. • Building increasingly complex elements out of simpler ones. • characters and graphics  lines column  page  …

  11. The structure of objects composite (column) • Figure 2.3 Page 37 composite (row) composite (row) Image G g space

  12. Implementing the structure • Flexibility • Treat the characters and graph uniformly. • Easy to extend to new character sets. • Two implication: • The objects need corresponding classes. • The classes should have compaible interface. (by inheritance)

  13. Glyphs • Glyphs: an abstract class for objects in a document structure. • The subclasses of Glyphs define both primitive graphical elements and structural elements. • The responsibilities: • How to draw themselves, • what space they occupy • their children and parent

  14. class hierarchy Glyph • Figure 2.4, Page 38 Draw() … Character Rectangle Row Draw() … Draw() … Draw() … Insert(Glyph g, int t) char c polygon Draw() …

  15. Basic glyph interface • Table 2.1, Page 39 Responsibility Operations appearance virtual void Draw(Window *) virtual void Bounds(Rect &) hit detection virtual bool Intersects(const Point&) structure virtual void Insert(Glyph *, int) virtual void Remove(Glyph *, int) virtual Glyph * Child(int) virtual Glyph * Parent()

  16. The composit Pattern • Recursive composition is good for more than just documents. • Represent potentially complex, hirarchical structure. • Composit Pattern

  17. 2.3 Formatting • The Lexi must break text into lines, lines into columns, … • Must consider: margin widths, indentation, tabulation, … • Now we will consider only breaking a collection of glyphs into lines.

  18. Encapsulating the Formating Algorithm(to be continued) • We should consider the trade-off between the formatting speed and quality. The users may change they mind when they use it. • It’s desirable to keep the algorithms independent of the document structure. • We want to treat the algorithms and the Glyph subclass seperatly.

  19. Encapsulating the Formating Algorithm(2) • We will define a separate class hierarchy for objects that encapsulate formatting algorithms. • The root of the hierarchy will define an interfact that supports a wide range of formatting algorithms. • Then we can introduce a Glyph subclass that will structure its children automatically using a given algorithm object.

  20. Compositor and Composition • Compositor class for objects that can encapsulate a formatting algorithm. • The interface let the compositor know what and when to formate. Responsibility Operations What to format void SetComposition(Composition *) When to format virtual void Compose()

  21. Compositor and Composition • The glyphs it formats are the children of a special Glyph subclass called Composition. • A composition gets an instance of a Compositor subclass(specialized for an algorithm) when it is created, and it tells the compositor to Compose its glyphs.

  22. Compositor and Composition Glyph Composition and Compositor class relationships children compositor Composition Compositor composition ArrayCompositor TeXCompositor SimpleCompositor

  23. Composition and Compositor • When the composition needs formatting, it calls its compositor’s Compose operator. • The compositor then iterates through the composition’s children and insert new Row and Column glyphs. • Each Compositor subclass can implement a different linebreeaking. • The compositor-Composition class split ensures a strong separation between code for document structure and code for different formatting algorithm.

  24. compositor-directed linebreaking composition compositor column row row Image G g space

  25. Strategy Pattern • Encapsulating an algorithm in an object is the intent of the Strategy. • The key participants are Strategy objects(for different algorithm) and the context in which they operate. • The key to applying the Strategy pattern is designing interfaces for the strategy and its context that are general enough to support a range of algorithm. • Strategy pattern.

  26. Embellishing the User Interface • Consider two embellishments in Lexi’s user interface • Adds a border around the text editing area to demarcate the page of text. • Adds scroll bars that let the user view different parts of the page.

  27. Transparent Enclosure(1) • Embellishing the user interface involves extending exisiting code. Two possible ways: Inheritance and Composition • Using inheritance may cause two major problems: • Precludes rearranging embellishment in run-time. • Explosion of classes because of combination of different embellishment.

  28. Transparent Enclosure(2) • Composition offers a potentially more workable and flexible. • We could make the embellishment an object. • If we make the Glyphs contain a border, we must modify the code of Glyphs. • So we let a Border object contains a Glyphs object.

  29. Transparent Enclosure(3) • About Border class • It should be a Glyph because it has an appearance. • Another more compelling reason: Clients shouldn’t care whether glyphs have borders or not. • So we subclass Border from Glyph.

  30. Transparent Enclosure(4) • The concept of transparent enclosure: • simgle-child composition • compatible interfaces. • A clients generally can’t tell whether they are dealing with the component or its emclosure. • A enclosure may delegate all its operations ot its component or augment the behavior by doint work of its own before and/or after delegating.

  31. Monoglyph(1) • We define MonoGlyph to serve as an abstract class for embellishment glyphs. • MonoGlyph stores a reference to a component and forwards all requests to it. • MonoGlyph subclasses reimplement at least one of the forwarding operations.

  32. Glyph MonoGlyph Border Scroller Draw(Window) Draw(Window) Draw(Window) DrawBorder(W) Draw(Window) MonoGlyph(2)

  33. MonoGlyph(3) • The default implementation for Draw() void MonoGlyph::Draw(Window w){ _component->Draw(w); } • The Border implementation for Draw() void Border::Draw(Window w){ MonoGlyph::Draw(w); DrawBorder(w); }

  34. MonoGlyph(4) • We can add a border and a scrolling interface to Lexi’s text editing area. • First compose the existing Composition instance in a Scroller instance. • Then compose the above in a Border instance.

  35. Decorator Pattern • The Decorator pattern captures class and object relationships that support embellishment by transparent enclosure. • In decorator pattern, embellishment refers to anything that adds responsibilities to an object. • Decorator Pattern

  36. Supporting Multiple Look-and-Feel Standards • Achieving protability across hardware and software platform is a major problem in system design. • The diversity of look-and-feel standards is one of the obstacles to protability. • The standards define guidelines for how applications appear and react to the user. • An application that runs on more than one platform must conform to the user interface style guide on each platform.

  37. Supporting Multiple Look-and-Feel Standards • The design goal: • make Lexi conform to multiple existing look-and-feel standards • make it easy to add support for new standards. • changing Lexi’s look and feel at run-time.

  38. Abstracting Object Creation • Assumption: We have two set of widget glyph classes • A set of abstract Glyph subclasses for each category of widget glyph. For examples: ScrollBar, Button. • A set of concrete subclasses for each abstract subclass that implement different look-and-feel standards. For examples: MotifScrollBard, PMScrollBar, …

  39. Abstracting Object Creation(2) • Lexi must distinguish between widget for different look-and-feel styles. It must be able to instantiate a Glyph subclass for the right style. • Lexi’s implementation can’t do this directly using a constructor call in C++. • We have to track down and change every these call to prot Lexi to another platform. • Littering our code with constructor calls to specific look&feel classes yields a maintenance nightmare.

  40. Abstracting Object Creation(3) • Lexi needs a way to determine the look&feel standard that’s being targeted in order to create the appropriate widgets. • avoid making explicit constructor calls. • bet able to replace an entire widget set easily. • We can achieve both by abstructing the process of object creation.

  41. Factories and Product Classes • Two way to create an instance of Motif scroll bar glyph: • ScrollBar * sb = new MotifScrollBar; • ScrollBar * sb = guiFactory ->CreateScrollBar() • guiFactory is an instance of a MotifFactory class. • Two way have the same effect, but there’s a crucial difference: There’s no longer anything in the code that mentions Motif by name. • guiFactory can be used to manufacture a full range of widget glyphs.

  42. Factories and Product Classes(2) • MotifFactory is a subclass of GUIFactory, an abstract class that defines a general interface for creating widget glyphs. • Subclasses of GUIFactory implement these operations to return glyphs that implement a particular look and feel. • We say that factories create product objects. • The products that a factory produces are related to one another.

  43. Factories and Product Classes(3) • The GUIFactory instance can be instantiated anywhere convenient. • before it’s ever used to create widgets • after it’s clear which look and feel is desired.

  44. GUIFactory MotifFactory PMFactory MacFactory CreateScrollBar() CreateButton() … CreateScrollBar() CreateButton() … CreateScrollBar() CreateButton() … CreateScrollBar() CreateButton() … GUIFactory class hierarchy

  45. Code for using GUIFactory • If the look&feel is know at compile-time • GUIFactory* guiFactory = new MotifFactory • If the look&feel is know at startup time GUIFactory * guiFactory; const char * styleName = getenv(“L&F”); if(!strcmp(styleName, “Motif”)==0){ guiFactory = new MotifFactory; }else if …

  46. Abstract Factory Pattern • This pattern captures how to create families of related product objects without instantiating classes directly. • It is most appropriate when the number and general kinds of product objects stay constant, and there are differences in specific product families. • The Abstract Factory pattern’s emphasis on families of products distinguishes it from other creational patterns.

  47. Supporting Multiple Window Systems • Another portability issues: windowing environment in which Lexi runs. • A platform’s window system creates the illusion of multiple overlapping windows. It manages screen space for windows and routes input to them from the keyboard and mouse. • Several important and largely incompatible window systems exist today: Macintosh, Presentation Manager, Windows, X, … • Make Lexi run on as many of them as possible.

  48. Can we use an Abstract Factory? • The constraints for windows system protability differ significantly from those for look-and-feel independence. • To use Abstract Factory pattern, we must make the different widget hierarcihes to a common set of abstract product interfaces. • Different window systems have incompatible programming interfaces. We can’t afford to implement our own nonstandard window system.

  49. Can we use an Abstract Factory?(2) • However, windows system interfaces aren’t radically different from one another. • We need a uniform set of windowing abstractions that lets us take different window system implementations and slide any one of them under a common interface.

  50. Encapsulating Implementation Dependencies • A Window class is introduced to encapsulate the thing windows tend to do across window systems: • Provide operations for drawing basic geometric shapes. • They can iconify and de-iconify themselves. • They can resize themselves • They can (re)draw their contents on demand.

More Related