+ All Categories
Home > Documents > Lexi case study (Part 2)

Lexi case study (Part 2)

Date post: 11-Feb-2016
Category:
Upload: neva
View: 45 times
Download: 0 times
Share this document with a friend
Description:
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 - PowerPoint PPT Presentation
26
Lexi case study (Part 2) Presentation by Matt Deckard
Transcript
Page 1: Lexi case study (Part 2)

Lexi case study (Part 2)

Presentation by Matt Deckard

Page 2: Lexi case study (Part 2)

User Operations Support different operations

Cut, copy, paste Formatting Printing Etc.

Support different Uis Menus Buttons Keyboard shortcuts Etc.

Page 3: Lexi case study (Part 2)

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

Page 4: Lexi case study (Part 2)

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?

Page 5: Lexi case study (Part 2)

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

Page 6: Lexi case study (Part 2)

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

Page 7: Lexi case study (Part 2)

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

Page 8: Lexi case study (Part 2)

Command class

Page 9: Lexi case study (Part 2)

Command class

Page 10: Lexi case study (Part 2)

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)

Page 11: Lexi case study (Part 2)

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

Page 12: Lexi case study (Part 2)

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

Page 13: Lexi case study (Part 2)

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

Page 14: Lexi case study (Part 2)

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)

Page 15: Lexi case study (Part 2)

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

Page 16: Lexi case study (Part 2)

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

Page 17: Lexi case study (Part 2)

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

Page 18: Lexi case study (Part 2)

Iterator class

Page 19: Lexi case study (Part 2)

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

Page 20: Lexi case study (Part 2)

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

Page 21: Lexi case study (Part 2)

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

Page 22: Lexi case study (Part 2)

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

Page 23: Lexi case study (Part 2)

Performing the analysis

Page 24: Lexi case study (Part 2)

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()

Page 25: Lexi case study (Part 2)

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

Page 26: Lexi case study (Part 2)

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?)


Recommended