Download presentation
Presentation is loading. Please wait.
Published byGeorgiana Smith Modified over 8 years ago
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
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 void First(Traversal) – initializes specified traversal void Next() – advances to next Glyph in traversal bool IsDone() – reports if traversal is over Glyph* GetCurrent() – accesses current glyph Replaces Child() void Insert(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 Iterator at top of stack Returns result Next() Calls CreateIterator() on top Iterator Calls First() on returned Iterator Pushes Iterator onto 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 tell SpellChecker 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
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?)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.