1 / 26

Lexi case study (Part 2)

Lexi case study (Part 2). Presentation by Matt Deckard. User Operations. Support different operations Cut, copy, paste Formatting Printing Etc. Support different Uis Menus Buttons Keyboard shortcuts Etc. User Operations. Avoid coupling operations and UIs

neva
Download Presentation

Lexi case study (Part 2)

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. Lexi case study (Part 2) Presentation by Matt Deckard

  2. User Operations • Support different operations • Cut, copy, paste • Formatting • Printing • Etc. • Support different Uis • Menus • Buttons • Keyboard shortcuts • Etc.

  3. User Operations • Avoid coupling operations and UIs • Use multiple UIs for single operations • Change UIs in the future • Avoid creating dependencies to classes operations are defined in • Undo and Redo • Want some, but not all operations to be undoable • Un-undoable operations: • Saving • Creating new documents • Printing • Don’t want arbitrary limit on levels of undo

  4. User Operations • Encapsulate user operations • GUI menus are just glyphs that perform actions in response to user interaction • Create subclass of Glyph called MenuItem • But don’t want to make each operation a subclass of MenuItem (avoid decoupling!) • Parameterize menu items by uper operations • How?

  5. User Operations • How should user operations be parameterized? • Simple function call has drawbacks: • Doesn’t address undo/redo • Hard to associate state with function • Difficult to extend, reuse • Use objects instead • Can store state, implement undo/redo • Use inheritance to extend, reuse

  6. Command class • Command: abstract class representing user operation • Based on abstract method Execute() • Subclasses will implement Execute() according to the operation they represent • Subclasses can delegate parts of user operation to other objects • Command objects are treated uniformly by requestor • MenuItem will store instance of Command object to encapsulate its associated user operation

  7. Command class • Undoability • Add abstract Unexecute() method • During Execute(), Commands will store whatever information they need to undo later • Add abstract Reversible() method • Returns true if and only if this Command is undoable • Allows Commands to determine undoability at runtime • i.e. redundant or vacuous Commands shouldn’t be undoable • Command history • Need list of Commands to support multiple undos • Traverse back and forth through list to undo and redo • Call Unexecute() when undoing, Execute() when redoing

  8. Command class

  9. Command class

  10. Command Pattern • Encapsulates a request (user operation) • Prescribes uniform interface for requests • Shields clients from request’s implementation • Allows delegation of request to other objects • Provides centralized access to functionality • Allows to queue or log requests • Supports undo, redo • AKA “Action”, “Transaction” • Similar to functor (but not quite the same)

  11. Command Pattern • Related patterns • Use with Composite and you’ve got: macros! • Use with Memento to remember state (for undo) • Use Prototype to copy command before putting in undo list, to distinguish multiple invocations of same command

  12. Spellchecking and Hyphenation • Textual analysis • Want to support multiple algorithms, addition of new ones in future • Avoid coupling to document structure • Add other types of analysis in future • i.e. search, word count, etc. • Two pieces: • Accessing information to be analyzed • Performing the analysis

  13. Accessing scattered information • Data access • Glyphs may be stored in different ways • Need mechanism to access all of them • Traversal • Different analyses may access Glyphs in different ways (i.e. forward vs. reverse search) • Issues • Only Glyphs know their data structure • Glyph interface shouldn’t be biased toward one structure over another • i.e. using integer index biased us toward arrays • Want to provide multiple access and traversal methods

  14. Accessing scattered information • One approach: adding methods to Glyph • voidFirst(Traversal) – initializes specified traversal • voidNext() – advances to next Glyph in traversal • boolIsDone() – reports if traversal is over • Glyph* GetCurrent() – accesses current glyph • Replaces Child() • voidInsert(Glyph*) – inserts Glyph at current pos • Replaces Insert(Glyph*, int)

  15. Accessing scattered information • Issues with this approach • Must extend Traversal enumeration to support new traversals • Would also have to change lots of subclasses • Difficult to reuse mechanism for other object structures • Doesn’t support multiple traversals in parallel

  16. Iterator class • Better approach: encapsulate access and traversal • Iterator • Abstract class • Defines interface for access and traversal • Subclass contains reference to structure it traverses • CreateIterator() • By default, will return NullIterator • Subclasses can override, based on their structure • Iterators can use CreateIterator() on their root glyphs to support different traversal

  17. Iterator class • Example: PreorderIterator • First() • Calls CreateIterator() on root • Calls First() on returned Iterator • Pushes Iterator onto stack • CurrentItem() • Calls CurrentItem() on Iteratorat top of stack • Returns result • Next() • Calls CreateIterator() on top Iterator • Calls First() on returned Iterator • Pushes Iteratoronto stack • Calls IsDone() on latest Iterator. If true, pops it off and repeats

  18. Iterator class

  19. Iterator Pattern • Abstracts traversal algorithm • Shields clients from internal structure of objects traversed • Gain flexability, usability • Easy to extend • Easy to reuse by parameterizing object type • Can perform multiple traversals in parallel

  20. Performing the analysis • Want to distinguish analysis from traversal • Flexibility, reusability • Different analyses might require same traversal • Want to distinguish different types of glyphs • Different analyses consider different glyphs • Could abstract in Glyph, have subclasses implement • Drawbacks to this approach: • Have to change multiple subclasses • Obscures basic glyph interface

  21. Performing the analysis • Encapsulate the analysis • Create analysis classes • For now, let’s consider a SpellChecker class • Iterator has instance of SpellChecker • Uses SpellChecker instance as it traverses • SpellChecker accumulates information as it is used

  22. Performing the analysis • How to distinguish glyphs? • SpellChecker treats different glyph types differently • Don’t want to resort to type tests or casting (gross) • Instead, have the glyph object tellSpellChecker to check it • Glyph has abstract CheckMe() method • SpellChecker has methods for every glyph subclass, i.e. CheckCharacter(), CheckRow(), CheckImage(), etc. • Glyph sublcasses will override CheckMe() to call the appropriate method in SpellChecker

  23. Performing the analysis

  24. Performing the analysis • Adding new analyzers • Will be difficult if we define them as separate classes • Instead, abstract it as a Visitor class • CheckMe() becomes the Accept() method • Takes any Visitor as parameter, so don’t have to touch glyph subclasses when adding new analyzers • CheckCharacter(), etc become the Visit() method • Overloaded, takes visited subclass as parameter • Need one for every subclass that implements Accept()

  25. Visitor Pattern • Can be applied to any object structure • Visitees needn’t have common parent class • Tradeoff: • When you add Visitors you don’t have to update object structure, BUT: • When you add subclasses to object structure, you DO have to update your Visitor classes • Sometimes can provide default “do nothing” operation in Visitor • Helps avoid “polluting” classes with many operations • Helps to separate groups of common operations • Can accumulate state as they visit elements • Sometimes compromises encapsulation of visitee • elements

  26. Summary • Needed to support different user operations • Encapsulate the concept that varies (Command) • Needed to support different methods of accessing and traversing data • Encapsulate the concept that varies (Iterator) • Needed to support different analysis algorithms • Encapsulate the concept that varies (Visitor) • (Are we seeing a pattern here?)

More Related