html5-img
1 / 60

Introducing Design Patterns Through a Case Study Designing A Document Editor

Introducing Design Patterns Through a Case Study Designing A Document Editor. Daniel POP, Ph.D. The Plan Design Patterns: Elements of Reusable Object-Oriented Design. Review the Case Study in the book 7 Design Problems Discuss each design problem Review the solutions.

kuri
Télécharger la présentation

Introducing Design Patterns Through 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. Introducing Design Patterns Through a Case StudyDesigning A Document Editor Daniel POP, Ph.D

  2. The PlanDesign Patterns: Elements of Reusable Object-Oriented Design • Review the Case Study in the book • 7 Design Problems • Discuss each design problem • Review the solutions

  3. Lexi Case StudyFeatures • LEXI is a WYSIWYG document editor with the following features: • Mix text and graphics in a variety of styles • Pull-down menus • Scrollbars • Icons for jumping to a particular page

  4. Seven Design Problems • Document Structure How do we represent a document? • Formatting How do we arrange text and graphics on the screen (or paper) • Embellishing the user interface • Supporting multiple look-and-feel standards • Supporting multiple window systems • User operations • Spelling checking and hyphenation

  5. Design Issue #1:Document Structure • Affects nearly every aspect of Lexi’s design • What are the impacts of the structure we choose? • What do we need to consider?

  6. Design Issue #1: Document Structure • Documents are a combination of characters, lines, polygons, images etc. • Often a user will want to deal with things at a higher level (ex. a picture or a row or column of a document) • To make Lexi user-friendly, we need to allow the user to deal with these higher level constructs • The internal representation of the document structure should match the physical structure • Allow arrangement of text and graphics into lines, columns, tables, etc. • Need to draw the document on the screen

  7. Design Issue #1: Document Structure

  8. Design Issue #1: Document Structure • Recursive Composition • A method for representing a hierarchy of information • A grouping of simple items to create a composite item • Groupings of items can be a part of even higher level groups

  9. Design Issue #1: Document Structure • Therefore… • Objects need corresponding classes • All of these classes need compatible interfaces so that allows us to handle them uniformly • Meet the Glyph

  10. Design Issue #1: Document Structure

  11. Design Issue #1: Document Structure • Recursive Composition – It’s not just for documents • Useful for any potentially complex, hierarchical structure • The Composite pattern captures this design approach Intent: Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

  12. Design Issue #1: Document StructureThe Composite Pattern Defines behavior For the primitives Forwards requests to children Behavior for composites Stores Child components

  13. Design Issue #1: Document Structure • How ‘deep’ do we go? • Ideally, use objects to represent finer details (characters) to promote flexibility at finest levels of the application • How to represent each character (its position, style etc) in an efficient way? Objects are often not used because of high costs in terms of memory allocation.

  14. Design Issue #1: Document Structure • Sharing objects • Create a pool of objects that are (re)used in more than one place

  15. Design Issue #1: Document Structure • Meet the Flyweightpattern • that is a shared object that can be used in multiple contexts simultaneously • Contexts is captured in the extrinsic state; flyweight stores only the intrinsic state • Flyweight: character objects • Intrinsic state: character code, • Extrinsic state: coordinate position in the document, its typographic style etc (these can be determined from the text layout algorithms and formatting commands in effect wherever the character appears)

  16. Design Issue #1: Document Structure • The Flyweightpattern • Intent: Use sharing to support large numbers of fine-grained objects efficiently. • Flyweight seeks to reduce intrinsic state of an object and externalize details in an extrinsic state. • For LEXI, because the number of different character objects is far less than the number of characters in the document, the total number of objects is substantially less than what a naive implementation would use.

  17. Design Issue #1: Document StructureThe Flyweight Pattern Additional data necessary to perform an operation (extrinsic state) is sent as parameters Reduced intrinsic state with each object

  18. Design Issue #1: Document Structure • Context for LEXI document structure can be stored as a map of typographic information, using B-tree data structure (http://en.wikipedia.org/wiki/B-tree), in a separate structure rather than store the font and type style with each character object. • The map keeps track of runs of characters with the same typographic attributes. When a character draws itself, it receives its typographic attributes as a side-effect of the draw traversal. • Because documents normally use just a few different fonts and styles, storing this information externally to each character object is far more efficient than storing it internally.

  19. Design Issue #1: Document Structure • How to efficiently handle large objects (for example images) within the document structure? • The Proxy pattern addresses this issue. Object Diagram Pattern structure

  20. Design Issue #1: Document Structure • To conclude the Design Issue #1: Several patterns • Composite • Flyweight • Proxy …and advanced data structure • B-tree were combined to achieve a flexible and effective representation of a complex document.

  21. Design Issue #2:Formatting • How to construct a particular physical structure • And maintain separation of data and format • Properly formatted document • Some possible responsibilities: • Break text into lines • Break lines into columns • Margin Widths • Indentation • Tabulation • Single/Double Spacing • Authors restrict the LEXI example to breaking glyphs into lines

  22. Design Issue #2:Formatting • How should we approach formatting? • What are some important trade-offs? • Formatting quality vs. formatting speed • Formatting speed vs. Storage requirements • What are the design goals? • Keep it well-contained • Don’t spread it over many classes • Independent of document structure • Add a new glyph… not have to worry about changing format code • Add new formatting algorithm – not have to change glyphs

  23. Design Issue #2Formatting • It will be complex… for sure • Ideas… ideas… ideas…

  24. Design Issue #2Formatting • Needs to be easy to change the formatting algorithm • If not at run-time, at least at compile-time • We can make it independent, self contained and replaceable by putting it in its own class • We can make it run-time replaceable by creating a class hierarchy for formatting algorithms • Compositor

  25. Design Issue #2Formatting • Composition object – when created contains the glyphs that determine content, but not structure (such as row, column) • When Compose() is called, it iterates the glyphs and composes (formats) them.

  26. Design Issue #2Formatting • Rows and Columns are inserted by the compositor • Why rows and columns? • Inserted by the line-breaking algorithm

  27. Design Issue #2Formatting • Why do we need different Compositor’s? • In the Example: • SimpleCompositor might do a quick pass without regard for such esoterica as the document's "color." Good color means having an even distribution of text and whitespace. • A TeXCompositor would implement the full TeX algorithm, which takes things like color into account in exchange for longer formatting times. • Compositor-Composition class split ensures a strong separation between code that supports the document's physical structure and the code for different formatting algorithms • We can change the line-breaking algorithm at run-time by adding a single SetCompositor operation to Composition's basic glyph interface.

  28. Design Issue #2Formatting • Meet the Strategypattern • Intent: Encapsulating an algorithm in an object • Key participants in the pattern are • Strategy objects (Compositors) • Context object (Composition) • The key to using Strategy • Interfaces for the strategy and the context that will support a range of algorithms • Ideally we don’t want to change these interfaces to support a new algorithm

  29. Design Issue #2Formatting • A reflection before moving forward… • Encapsulating an algorithm in an object is the intent of the Strategy pattern. • Distributing an algorithm among several objects is the intent of the Statepattern • Actually not used in this case-study • Related to Strategy though, sharing similar diagrams, but completely different semantic

  30. Design Issue #3Embellishing the user interface • Two ornaments (embellishments): • a border around the text editing area • scroll bars

  31. Design Issue #3Embellishing the User Interface • Basically, we want to extend the code to provide a Transparent Enclosure • Transparent in that the page itself does not know anything about the changes – it behaves the same • How should we do this? • We could use Inheritance, how would that look? • We have a Composition class… • To add a Border we add a BorderedComposition class • To add a Scroll bar we add a ScrollableComposition class • What about both? BorderedScrollableComposition class? • How could we do it with object composition instead? • What object “has” what object? • How do we make it extensible?

  32. Design Issue #3Embellishing the User Interface • Meet the Decoratorpattern // Delegate it void MonoGlyph::Draw (Window* w) { _component->Draw(w); } // Do it void Border::Draw (Window* w) { MonoGlyph::Draw(w); DrawBorder(w); } Multiple decorations (ornaments)….

  33. Design Issue #3Embellishing the User Interface • To conclude Design Issue #3: • Adding additional functionalities (embellishments, ornaments) to a class can be either achieved either via inheritance (soon you will end-up with an unmanageable hierarchy) or, better, using object composition with the help of patterns like Decorator or Chain of Responsibility (for Chain of Responsibility see also Design Issue #6)

  34. Design Issue #4Supporting Multiple Look-and-Feel Standards • One major problem in portability… consider look-and-feel for • Windows • Max OS X • KDE • If re-targeting is too difficult (expensive), it won’t happen • NOTE: Just one of the issues… Look-and-Feel … we deal with the Windowing system itself next • We use an Abstract Factory Pattern • This allows us to define the product type at compile time or run-time (based on environment or user input)

  35. Design Issue #4Supporting Multiple Look-and-Feel Standards // Creating a scrollbar… ScrollBar* sb = guiFactory->CreateScrollBar();

  36. Design Issue #4Supporting Multiple Look-and-Feel Standards

  37. Design Issue #4Supporting Multiple Look-and-Feel Standards • AbstractFactory classes are often implemented with • Factory Methodpattern, or • Prototype pattern • Because a concrete factory is often unique in the system, it is implemented often as a Singleton.

  38. Design Issue #5Supporting Multiple Window Systems • What about the Windowing System itself? • The APIs differ… not just the visual elements • How do we make classes from different hierarchies comply to the same abstract type? • Can we use Abstract Factory? • Not easily… vendors already define class hierarchies • We use Bridge pattern to • define a uniform set of windowing abstractions (common interface) • Hide the individual implementations

  39. Design Issue #5Supporting Multiple Window Systems • Common things a Window class must do (responsibilities) • Provide operations for drawing basic geometric shapes • Maximize/Minimize • Resize • (re)Draw contents on demand (when restored, overlapped, obscured, etc…) • Two Possible Philosophies (Extremes) • Intersection of functionality – Only define what is common to all • Union of functionality – Incorporate capabilities of all systems

  40. Design Issue #5Supporting Multiple Window Systems • We adopt a hybrid

  41. Design Issue #5Supporting Multiple Window Systems

  42. Design Issue #5Supporting Multiple Window Systems

  43. Design Issue #5Supporting Multiple Window Systems • Bridge pattern is used up-front in a design to let abstractions and implementations vary independently. • On the other hand, but similar to Bridge, the Adapter pattern is geared toward making unrelated classes work together. It is usually applied to systems after they're designed, during implementation phase.

  44. Design Issue #6User Operations • Possible Operations • Document operations: create, open, save, print a document • Editing operations: select, copy, cut, paste, undo, redo • Formatting operations: text formatting, character formatting etc • Miscellaneous operations: context sensitive help • We have different interfaces for these operations • Different Look-and-Feel • Different Windowing Systems • Different Access Points (menu, shortcut key, context menu) • We want independence from the UI • UI triggers the action only, but what is done should not depend on the UI

  45. Design Issue #6User Operations • Other remarks: • The operations are implemented in many different classes • De-coupling: we want to access the functionality without adding dependency between the UI classes (i.e. object that issues the request) and all of the different classes involved (i.e. object that will perform the request) • We also want to support undo and redo for some functionality • We need to encapsulate the request using the CommandPattern

  46. Design Issue #6User Operations • Each MenuItem, ToolbarButton or KeyboardShortcut stores an appropriate command

  47. Design Issue #6User Operations …and there is an entire hierarchy of specific commands, each class (command) being in charge with a specific user operation. Naturally, the same command object will be pointed out (shared) by different triggers, like menu items, toolbar buttons etc. Hence, no matter what triggers a user operation, the behavior is consistently the same.

  48. Design Issue #6User Operations • What about Undo? We add an Unexecute() method and keep a command history… • …and a Memento will keep the state the command requires to undo (Unexecute) its effect. UNDO REDO

  49. Design Issue #6User Operations • How to handle context-sensitive Help?

  50. Design Issue #6User Operations • Chain of Responsibility pattern allows to handle a request by multiple hadlers. • Intent: Avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.

More Related