a case study: designing a document editor “ lexi ”

75
A Case Study: A Case Study: Designing a Document Designing a Document Editor Editor “ Lexi ” “ Lexi ”

Upload: adela-parks

Post on 29-Dec-2015

306 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A Case Study: Designing a Document Editor “ Lexi ”

A Case Study:A Case Study:Designing a Document Designing a Document

EditorEditor

“ Lexi ”“ Lexi ”

Page 2: A Case Study: Designing a Document Editor “ Lexi ”

IntroductionIntroduction

This chapter presents a case study in This chapter presents a case study in the design of a “the design of a “WWhat-hat-YYou-ou-SSee-ee-IIs-s-WWhat-hat-YYou-ou-GGet” (“et” (“WYSIWYGWYSIWYG”) document ”) document editor called editor called LexiLexi..

The document can mix text and graphics The document can mix text and graphics freely in a variety of formatting styles, freely in a variety of formatting styles, Surrounding the document are the Surrounding the document are the usual pull-down menu, scroll bars, page usual pull-down menu, scroll bars, page icons,…icons,…

Page 3: A Case Study: Designing a Document Editor “ Lexi ”
Page 4: A Case Study: Designing a Document Editor “ Lexi ”

2.1 Design Problems2.1 Design Problems

We will examine seven problems in Lexi`s We will examine seven problems in Lexi`s design:design:

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 5: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 6: A Case Study: Designing a Document Editor “ Lexi ”

2.2 Document Structure2.2 Document StructureA document in an arrangement of graphical A document in an arrangement of graphical

elements (characters, lines, polygons, … etc)elements (characters, lines, polygons, … etc)

Yet author views these elements not in graphical Yet author views these elements not in graphical terms but in terms of the document's physical terms but in terms of the document's physical structure, logical structure, and other structure, logical structure, and other substructures.substructures.

In particular, the internal representation should In particular, the internal representation should support the following:support the following:

1.1. Maintaining the document's physical structure.Maintaining the document's physical structure.

2.2. Generating and presenting the document Generating and presenting the document visually.visually.

3.3. Mapping positions on the display to elements in Mapping positions on the display to elements in the internal representation.the internal representation.

Page 7: A Case Study: Designing a Document Editor “ Lexi ”

Recursive CompositionRecursive Composition

A common way to represent A common way to represent hierarchically structured information hierarchically structured information is though a technique called is though a technique called recursive compositionrecursive composition, which , which entails building increasingly complex entails building increasingly complex elements out of simple ones.elements out of simple ones.

Page 8: A Case Study: Designing a Document Editor “ Lexi ”

Recursive composition of text and Recursive composition of text and graphicsgraphics

Page 9: A Case Study: Designing a Document Editor “ Lexi ”

Object structure for recursive Object structure for recursive composition of text and composition of text and

graphicsgraphics

Page 10: A Case Study: Designing a Document Editor “ Lexi ”

This approach has two important This approach has two important implications:implications:

The First:The First: ‘Obvious’ The Objects need ‘Obvious’ The Objects need corresponding classes.corresponding classes.

The Second:The Second: ‘Less Obvious’ these ‘Less Obvious’ these classes must have compatible classes must have compatible interfaces, because we want to treat interfaces, because we want to treat the objects uniformly.the objects uniformly.

Page 11: A Case Study: Designing a Document Editor “ Lexi ”

GlyphsGlyphs

We’ll define a Glyph abstract class for all We’ll define a Glyph abstract class for all objects that can appear in a document objects that can appear in a document structure. Its subclasses define both structure. Its subclasses define both primitive graphical elements primitive graphical elements (characters, images) and structural (characters, images) and structural elements (rows, columns)elements (rows, columns)

Glyphs have thee basic responsibilities:Glyphs have thee basic responsibilities: 1- how to draw themselves.1- how to draw themselves. 2- what space the occupy.2- what space the occupy. 3- their parent and children.3- their parent and children.

Page 12: A Case Study: Designing a Document Editor “ Lexi ”

Partial Glyph class Partial Glyph class hierarchyhierarchy

Page 13: A Case Study: Designing a Document Editor “ Lexi ”

Basic Glyph interfaceBasic Glyph interface

virtual void Insert (Glyph*, virtual void Insert (Glyph*, int)int)

virtual void Remove(Glyph*)virtual void Remove(Glyph*)

virtual Glyph* Child(int)virtual Glyph* Child(int)

virtual Glyph* Parent()virtual Glyph* Parent()

StructureStructure

virtual bool Intersects(const virtual bool Intersects(const Point&)Point&)

Hit DetectionHit Detection

virtual void Draw(Window*)virtual void Draw(Window*)

virtual void Bounds(Rect&)virtual void Bounds(Rect&)AppearanceAppearance

OperationsOperationsResponsibiliResponsibilityty

Page 14: A Case Study: Designing a Document Editor “ Lexi ”

11stst Pattern Pattern

Composite Pattern:Composite Pattern:

Recursive composition is good for Recursive composition is good for more than just documents. We can more than just documents. We can use it to represent any potentially use it to represent any potentially complex hierarchical structure.complex hierarchical structure.

The Composite Pattern captures the The Composite Pattern captures the essence of recursive composition in essence of recursive composition in object-oriented terms.object-oriented terms.

Page 15: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 16: A Case Study: Designing a Document Editor “ Lexi ”

2.3 Formatting2.3 FormattingWe’ve settled on a way to represent the We’ve settled on a way to represent the

document’s physical structure. Next, we document’s physical structure. Next, we need to figure out how to construct need to figure out how to construct particular physical structure, one that particular physical structure, one that corresponds to a properly formatted corresponds to a properly formatted document.document.

We’ll restrict “formatting” to mean breaking We’ll restrict “formatting” to mean breaking a collection of glyphs into lines. In fact, a collection of glyphs into lines. In fact, we’ll use the terms “formatting” and we’ll use the terms “formatting” and “linebreaking” interchangeably (break “linebreaking” interchangeably (break lines into columns, columns into pages …)lines into columns, columns into pages …)

Page 17: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating the Formatting Encapsulating the Formatting AlgorithmAlgorithm

The formatting process, with all its constraints The formatting process, with all its constraints and details, isn’t easy to automate.and details, isn’t easy to automate.

Because formatting algorithms tend to be Because formatting algorithms tend to be complex, it’s also desirable to keep them or -complex, it’s also desirable to keep them or -better yet- completely independent of the better yet- completely independent of the document structure.document structure.

These characteristics suggest we should These characteristics suggest we should design Lexi so that it’s easy to change the design Lexi so that it’s easy to change the formatting algorithm at least at compile formatting algorithm at least at compile time, if not at run time.time, if not at run time.

Page 18: A Case Study: Designing a Document Editor “ Lexi ”

Compositor & Compositor & CompositionComposition

We’ll define a We’ll define a Compositor Compositor class for objects that class for objects that can encapsulate a formatting algorithm.can encapsulate a formatting algorithm.

The interface lets the compositor know The interface lets the compositor know whatwhat glyphs to format and glyphs to format and whenwhen to do the formatting. to do the formatting.

virtual void Compose()virtual void Compose()when to when to formatformat

void SetComposition void SetComposition (Composition*)(Composition*)

what to what to formatformat

OperationsOperationsResponsibilitResponsibilityy

Basic compositor interface

Page 19: A Case Study: Designing a Document Editor “ Lexi ”

Composition and Compositor class Composition and Compositor class relationshiprelationship

Page 20: A Case Study: Designing a Document Editor “ Lexi ”

An unformatted Composition object An unformatted Composition object contains only the visible glyphs that contains only the visible glyphs that make up the document’s basic content.make up the document’s basic content.

Each Compositor subclass can Each Compositor subclass can implement a different linebreaking implement a different linebreaking algorithm. (SimpleCompositor, algorithm. (SimpleCompositor, TeXCompositor).TeXCompositor).

The Compositor-Composition calss split The Compositor-Composition calss split ensures a strong separation between ensures a strong separation between code the support the document’s code the support the document’s physical structure and the code physical structure and the code different formatting algorithm.different formatting algorithm.

Page 21: A Case Study: Designing a Document Editor “ Lexi ”

Object structure reflecting Object structure reflecting compositor-composition compositor-composition

linebreakinglinebreaking

Page 22: A Case Study: Designing a Document Editor “ Lexi ”

22ndnd Pattern Pattern

Strategy Pattern:Strategy Pattern:Encapsulating an algorithm in an object Encapsulating an algorithm in an object

is the intent of the Strategy Pattern.is the intent of the Strategy Pattern.The key participants in the pattern are The key participants in the pattern are

Strategy object and the context in Strategy object and the context in which they operate.which they operate.

The key to applying the Strategy Pattern The key to applying the Strategy Pattern is designing interfaces for the strategy is designing interfaces for the strategy and its context that are general enough and its context that are general enough to support a range of algorithms.to support a range of algorithms.

Page 23: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 24: A Case Study: Designing a Document Editor “ Lexi ”

2.4 Embellishing the User 2.4 Embellishing the User InterfaceInterface

We consider two embellishments in We consider two embellishments in Lexi’s user interface:Lexi’s user interface:

The First: Adds a border around the text The First: Adds a border around the text editing area.editing area.

The Second: Adds scroll bars.The Second: Adds scroll bars.- Don’t use Don’t use inheritanceinheritance..- Achieve the most Achieve the most flexibilityflexibility..- Add and remove Add and remove without changingwithout changing

other classes.other classes.

Page 25: A Case Study: Designing a Document Editor “ Lexi ”

Transparent EnclosureTransparent Enclosure

From a programming P.O.V., embellishing the From a programming P.O.V., embellishing the user interface extending existing code.user interface extending existing code.

Using inheritance: - unrearrangable.Using inheritance: - unrearrangable. - explosion.- explosion.

We could add a border to Composition by We could add a border to Composition by subclassing it to yield a BorderComposition subclassing it to yield a BorderComposition calss, Scrolling – ScrollableComposition, Both – calss, Scrolling – ScrollableComposition, Both – BorderedScrollableComposition …BorderedScrollableComposition …

We need class for every possible composition.We need class for every possible composition. (Unworkable).(Unworkable).Object composition offers a potentially more Object composition offers a potentially more

workable and flexible mechanism. workable and flexible mechanism.

Page 26: A Case Study: Designing a Document Editor “ Lexi ”

Transparent EnclosureTransparent Enclosure

But what Objects do we compose ???But what Objects do we compose ???

What does the Border Class look What does the Border Class look like ???like ???

All this leads us to the concept of All this leads us to the concept of Transparent EnclosureTransparent Enclosure,, which combines which combines the notions of: the notions of:

1- single-child (single-component) 1- single-child (single-component) Composition.Composition.

2- compatible interfaces.2- compatible interfaces.

Page 27: A Case Study: Designing a Document Editor “ Lexi ”

MonoglyphMonoglyph

We can apply the concept of transparent enclosure to We can apply the concept of transparent enclosure to all glyphs that embellish other glyphs.all glyphs that embellish other glyphs.

Page 28: A Case Study: Designing a Document Editor “ Lexi ”

Embellished object Embellished object structurestructure

Page 29: A Case Study: Designing a Document Editor “ Lexi ”

33rdrd Pattern Pattern

Decorator Pattern:Decorator Pattern:

The Decorator Pattern capture class The Decorator Pattern capture class and object relationships that support and object relationships that support embellishment by transparent embellishment by transparent enclosure.enclosure.

Page 30: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 31: A Case Study: Designing a Document Editor “ Lexi ”

2.5 Supporting multiple look-2.5 Supporting multiple look-and-feel standardsand-feel standards

Achieving portability across hardware and Achieving portability across hardware and software platforms is a major problem in software platforms is a major problem in system design. system design.

One obstacle to portability is the diversity of One obstacle to portability is the diversity of look-and-feel standards, which are look-and-feel standards, which are intended to enforce uniformity between intended to enforce uniformity between applications. applications.

Our design goals are to make Lexi conform Our design goals are to make Lexi conform to multiple existing look-and-feel standards to multiple existing look-and-feel standards and to make it easy to add support for new and to make it easy to add support for new standards as they (invariably) emerge. standards as they (invariably) emerge.

Page 32: A Case Study: Designing a Document Editor “ Lexi ”

Abstracting Object Abstracting Object Creation Creation

Everything we see and interact with in Everything we see and interact with in Lexi's user interface is a glyph composed Lexi's user interface is a glyph composed in other, invisible glyphs like Row and in other, invisible glyphs like Row and Column. Column.

We'll assume we have two sets of widget We'll assume we have two sets of widget glyph classes with which to implement glyph classes with which to implement multiple look-and-feel standards:multiple look-and-feel standards:

1.1. A set of abstract Glyph subclasses for A set of abstract Glyph subclasses for each category of widget glyph.each category of widget glyph.

2.2. A set of concrete subclasses for each A set of concrete subclasses for each abstract subclass that implement abstract subclass that implement different look-and-feel standards. different look-and-feel standards.

Page 33: A Case Study: Designing a Document Editor “ Lexi ”

Factories and Product Factories and Product Classes Classes

Normally we might create an instance of Normally we might create an instance of a Motif scroll bar glyph with the following a Motif scroll bar glyph with the following C++ code:C++ code:

ScrollBar* sb = new MotifScrollBar; ScrollBar* sb = new MotifScrollBar; This is the kind of code to avoid if you This is the kind of code to avoid if you

want to minimize Lexi's look-and-feel want to minimize Lexi's look-and-feel dependencies. But suppose we initialize dependencies. But suppose we initialize sb as follows:sb as follows:

ScrollBar* sb = guiFactory-ScrollBar* sb = guiFactory->CreateScrollBar(); >CreateScrollBar();

Page 34: A Case Study: Designing a Document Editor “ Lexi ”

Factories and Product Factories and Product Classes Classes

where guiFactory is an instance of a where guiFactory is an instance of a MotifFactoryMotifFactory class. CreateScrollBar class. CreateScrollBar returns a new instance of the proper returns a new instance of the proper ScrollBar subclass for the look and feel ScrollBar subclass for the look and feel desired, Motif in this case. desired, Motif in this case.

All this is possible because MotifFactory All this is possible because MotifFactory is a subclass of is a subclass of GUIFactoryGUIFactory, an , an abstract class that defines a general abstract class that defines a general interface for creating widget glyphs. interface for creating widget glyphs.

Page 35: A Case Study: Designing a Document Editor “ Lexi ”

Factories and Product Factories and Product Classes Classes

We say that factories create We say that factories create productproduct objects. Moreover, the products that objects. Moreover, the products that a factory produces are related to one a factory produces are related to one another; in this case, the products are another; in this case, the products are all widgets for the same look and feel. all widgets for the same look and feel.

The last question we have to answer The last question we have to answer is, is, Where does the GUIFactory Where does the GUIFactory instance come from?instance come from? The answer is, The answer is, Anywhere that's convenient. Anywhere that's convenient.

Page 36: A Case Study: Designing a Document Editor “ Lexi ”

  GUIFactory class GUIFactory class hierarchy hierarchy

Page 37: A Case Study: Designing a Document Editor “ Lexi ”

Abstract product classes Abstract product classes and concrete subclasses and concrete subclasses

Page 38: A Case Study: Designing a Document Editor “ Lexi ”

44thth Pattern Pattern

Abstract Factory pattern:Abstract Factory pattern:

Factories and products are the key participants in Factories and products are the key participants in the Abstract Factory pattern. This pattern the Abstract Factory pattern. This pattern captures how to create families of related product captures how to create families of related product objects without instantiating classes directly. objects without instantiating classes directly.

We choose between families by instantiating a We choose between families by instantiating a particular concrete factory and using it particular concrete factory and using it consistently to create products thereafter. consistently to create products thereafter.

The Abstract Factory pattern's emphasis on The Abstract Factory pattern's emphasis on familiesfamilies of products distinguishes it from other of products distinguishes it from other creational patterns, which involve only one kind creational patterns, which involve only one kind of product object.of product object.

Page 39: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 40: A Case Study: Designing a Document Editor “ Lexi ”

2.62.6 Supporting Multiple Supporting Multiple Window SystemWindow System

A platform's window system creates A platform's window system creates the illusion of multiple overlapping the illusion of multiple overlapping windows on a bitmapped display. windows on a bitmapped display.

We'd like Lexi to run on as many of We'd like Lexi to run on as many of them as possible for exactly the them as possible for exactly the same reasons we support multiple same reasons we support multiple look-and-feel standards. look-and-feel standards.

Page 41: A Case Study: Designing a Document Editor “ Lexi ”

Can We Use an Abstract Can We Use an Abstract Factory? Factory?

At first glance this may look like At first glance this may look like another opportunity to apply the another opportunity to apply the Abstract Factory pattern. But the Abstract Factory pattern. But the constraints for window system constraints for window system portability differ significantly from portability differ significantly from those for look-and-feel those for look-and-feel independence. independence.

Page 42: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Implementation Encapsulating Implementation DependenciesDependencies

The Window class encapsulates the things The Window class encapsulates the things windows tend to do across window systems:windows tend to do across window systems:

They provide operations for drawing basic They provide operations for drawing basic geometric shapes. geometric shapes.

They can iconify and de-iconify themselves. They can iconify and de-iconify themselves. They can resize themselves. They can resize themselves. They can (re)draw their contents on demand, They can (re)draw their contents on demand,

for example, when they are de-iconified or for example, when they are de-iconified or when an overlapped and obscured portion of when an overlapped and obscured portion of their screen space is exposed. their screen space is exposed.

Page 43: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Implementation Encapsulating Implementation DependenciesDependencies

The Window class must span the The Window class must span the functionality of windows from different functionality of windows from different window systems. Let's consider two window systems. Let's consider two extreme philosophies:extreme philosophies:

Intersection of functionality.Intersection of functionality. The The Window class interface provides only Window class interface provides only functionality that's common to functionality that's common to allall window systems. window systems.

Union of functionality.Union of functionality. Create an Create an interface that incorporates the interface that incorporates the capabilities of capabilities of allall existing systems. existing systems.

Page 44: A Case Study: Designing a Document Editor “ Lexi ”

virtual void DrawLine(...)virtual void DrawRect(...)virtual void DrawPolygon(...)virtual void DrawText(...)

Encapsulating Implementation Encapsulating Implementation DependenciesDependencies

  Window class interface

GraphicsGraphics

virtual void Redraw()virtual void Raise()virtual void Lower()virtual void Iconify()virtual void Deiconify()

Window Window ManagmentManagment

OperationsOperationsResponsibiliResponsibilityty

Page 45: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Implementation Encapsulating Implementation DependenciesDependencies

Page 46: A Case Study: Designing a Document Editor “ Lexi ”

Window & WindowImpWindow & WindowImp

Page 47: A Case Study: Designing a Document Editor “ Lexi ”

55thth Pattern Pattern

Bridge Pattern:Bridge Pattern:

The relationship between Window and The relationship between Window and WindowImp is an example of the Bridge WindowImp is an example of the Bridge pattern. The intent behind Bridge is to allow pattern. The intent behind Bridge is to allow separate class hierarchies to work together separate class hierarchies to work together even as they evolve independently. Our design even as they evolve independently. Our design criteria led us to create two separate class criteria led us to create two separate class hierarchies, one that supports the logical notion hierarchies, one that supports the logical notion of windows, and another for capturing different of windows, and another for capturing different implementations of windows. The Bridge implementations of windows. The Bridge pattern lets us maintain and enhance our pattern lets us maintain and enhance our logical windowing abstractions without logical windowing abstractions without touching window system-dependent code, and touching window system-dependent code, and vice versa.vice versa.

Page 48: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 49: A Case Study: Designing a Document Editor “ Lexi ”

2.7 User Operations2.7 User OperationsSome of Lexi's functionality is available through Some of Lexi's functionality is available through

the document's WYSIWYG representation. the document's WYSIWYG representation. directly in the documentdirectly in the document

You enter and delete text,You enter and delete text, functionality accessed indirectly through user functionality accessed indirectly through user

operations in Lexi's pull-down menus, buttons, operations in Lexi's pull-down menus, buttons, and keyboard accelerators : creating a new and keyboard accelerators : creating a new document, document,

opening, saving, and printing an existing opening, saving, and printing an existing document, cutting selected text out of the document, cutting selected text out of the document and pasting it back in, changing the document and pasting it back in, changing the font and style of selected text, changing the font and style of selected text, changing the formatting of text, such as its alignment and formatting of text, such as its alignment and justification, quitting the application, and on justification, quitting the application, and on and on. and on.

Page 50: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating a RequestEncapsulating a Request work-performing glyphs are instances of a work-performing glyphs are instances of a

Glyph subclass called MenuItem and that they Glyph subclass called MenuItem and that they do their work in response to a request from a do their work in response to a request from a client client

Carrying out the request might involve an Carrying out the request might involve an operation on one object, or many operations operation on one object, or many operations on many objects, or something in between. on many objects, or something in between. parameterize MenuItem with a function to parameterize MenuItem with a function to call, it’s not a complete solution for at least call, it’s not a complete solution for at least three reasons:three reasons:

1-It doesn't address the undo/redo problem.1-It doesn't address the undo/redo problem.2-It's hard to associate state with a function 2-It's hard to associate state with a function 3-Functions are hard to extend, and it's hard to 3-Functions are hard to extend, and it's hard to

reuse parts of them.reuse parts of them.

Page 51: A Case Study: Designing a Document Editor “ Lexi ”

Command Class and Command Class and SubclassesSubclasses

encapsulate each request in a command encapsulate each request in a command object .object .

define a Command abstract class to define a Command abstract class to provide an interface for issuing a request .provide an interface for issuing a request .

basic interface consists of a single basic interface consists of a single abstract operation called ’ Execute’ abstract operation called ’ Execute’ ..

Command implement Execute in different Command implement Execute in different ways to fulfill different requests .ways to fulfill different requests .

Page 52: A Case Study: Designing a Document Editor “ Lexi ”

Partial Command class hierarchy

Page 53: A Case Study: Designing a Document Editor “ Lexi ”

MenuItem-Command relationship

Page 54: A Case Study: Designing a Document Editor “ Lexi ”

UndoabilityUndoability

Undo/redo is an important capability in Undo/redo is an important capability in interactive applications .interactive applications .

add an Unexecute operation to add an Unexecute operation to Command's interface .Command's interface .

Sometimes undoability must be Sometimes undoability must be determined at run-time.determined at run-time.

Page 55: A Case Study: Designing a Document Editor “ Lexi ”

Present

Command HistoryCommand History The final step in supporting arbitrary-level undo The final step in supporting arbitrary-level undo

and redo is to define a command history .and redo is to define a command history .

Past Commands Unexecute()Past Future Execute()Past Future

Page 56: A Case Study: Designing a Document Editor “ Lexi ”

66thth Pattern Pattern

Command Pattern:Command Pattern:

Lexi's commands are an application of the Lexi's commands are an application of the Command pattern, which describes how to Command pattern, which describes how to encapsulate a request. The Command encapsulate a request. The Command pattern prescribes a uniform interface for pattern prescribes a uniform interface for issuing requests that lets you configure issuing requests that lets you configure clients to handle different requests. The clients to handle different requests. The interface shields clients from the request's interface shields clients from the request's implementation. A command may delegate implementation. A command may delegate all, part, or none of the request's all, part, or none of the request's implementation to other objects. implementation to other objects.

Page 57: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 58: A Case Study: Designing a Document Editor “ Lexi ”

2.8 Spelling checking and 2.8 Spelling checking and HyphenationHyphenation

problem involves textual analysis, problem involves textual analysis, specifically checking for misspellings specifically checking for misspellings and introducing hyphenation points and introducing hyphenation points where needed for good formatting.where needed for good formatting.

(1) accessing the information to be (1) accessing the information to be analyzed, which we have scattered over analyzed, which we have scattered over the glyphs in the document structure, the glyphs in the document structure, and (2) doing the analysis. We'll look at and (2) doing the analysis. We'll look at these two pieces separately.these two pieces separately.

Page 59: A Case Study: Designing a Document Editor “ Lexi ”

Accessing Scattered Accessing Scattered InformationInformation

The text we need to analyze is scattered The text we need to analyze is scattered throughout a hierarchical structure of throughout a hierarchical structure of glyph objects.glyph objects.

we need an access mechanism that has we need an access mechanism that has knowledge about the data structures in knowledge about the data structures in which objects are storedwhich objects are stored

access mechanism must accommodate access mechanism must accommodate differing data structures, and we must differing data structures, and we must support different kinds of traversals, such support different kinds of traversals, such as preorder, postorder, and inorder. as preorder, postorder, and inorder.

Page 60: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Access and Encapsulating Access and TraversalTraversal

glyph interface uses an integer index to let glyph interface uses an integer index to let clients refer to children. Although that might be clients refer to children. Although that might be reasonable for glyph classes that store their reasonable for glyph classes that store their children in an array, it may be inefficient for children in an array, it may be inefficient for glyphs that use a linked list. An important role of glyphs that use a linked list. An important role of the glyph abstraction is to hide the data the glyph abstraction is to hide the data structure in which children are stored. That way structure in which children are stored. That way we can change the data structure a glyph class we can change the data structure a glyph class uses without affecting other classes uses without affecting other classes

glyph interface shouldn't be biased toward one glyph interface shouldn't be biased toward one data structure or another. It shouldn't be better data structure or another. It shouldn't be better suited to arrays than to linked lists suited to arrays than to linked lists

Page 61: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Access and Encapsulating Access and TraversalTraversal

solve this problem and support several solve this problem and support several different kinds of traversals at the same time. different kinds of traversals at the same time. We can put multiple access and traversal We can put multiple access and traversal capabilities directly in the glyph classes and capabilities directly in the glyph classes and provide a way to choose among them, perhaps provide a way to choose among them, perhaps by supplying an enumerated constant as a by supplying an enumerated constant as a parameter. The classes pass this parameter parameter. The classes pass this parameter around during a traversal to ensure they're all around during a traversal to ensure they're all doing the same kind of traversal. They have to doing the same kind of traversal. They have to pass around any information they've pass around any information they've accumulated during traversal.accumulated during traversal.

Page 62: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Access and Encapsulating Access and TraversalTraversal

abstract operations to Glyph's interfaceabstract operations to Glyph's interfacevoid First(Traversal kind) void First(Traversal kind) void Next() void Next() bool IsDone() bool IsDone() Glyph* GetCurrent() Glyph* GetCurrent() void Insert(Glyph*) void Insert(Glyph*) code to do a preorder traversal of a glyph code to do a preorder traversal of a glyph

structure rooted at g structure rooted at g Glyph* g; Glyph* g; for (g->First(PREORDER); !g->IsDone(); g-for (g->First(PREORDER); !g->IsDone(); g-

>Next()) { Glyph* current = g->Next()) { Glyph* current = g->GetCurrent(); >GetCurrent();

// do some analysis // do some analysis } }

Page 63: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating Access and Encapsulating Access and TraversalTraversal

better solution is to encapsulate the concept better solution is to encapsulate the concept that varies, in this case the access and that varies, in this case the access and traversal mechanisms. We can introduce a traversal mechanisms. We can introduce a class of objects called class of objects called iteratorsiterators whose sole whose sole purpose is to define different sets of these purpose is to define different sets of these mechanisms. We can use inheritance to let mechanisms. We can use inheritance to let us access different data structures uniformly us access different data structures uniformly and support new kinds of traversals as well. and support new kinds of traversals as well. And we won't have to change glyph And we won't have to change glyph interfaces or disturb existing glyph interfaces or disturb existing glyph implementations to do it.implementations to do it.

Page 64: A Case Study: Designing a Document Editor “ Lexi ”

Iterator Class and Iterator Class and SubclassesSubclasses

We'll use an abstract class called We'll use an abstract class called IteratorIterator to to define a general interface for access and define a general interface for access and traversal. Concrete subclasses like traversal. Concrete subclasses like ArrayIteratorArrayIterator and and ListIteratorListIterator implement the implement the interface to provide access to arrays and lists, interface to provide access to arrays and lists, while while PreorderIteratorPreorderIterator, , PostorderIteratorPostorderIterator, , and the like implement different traversals on and the like implement different traversals on specific structures. Each Iterator subclass has specific structures. Each Iterator subclass has a reference to the structure it traverses. a reference to the structure it traverses. Subclass instances are initialized with this Subclass instances are initialized with this reference when they are created reference when they are created

Page 65: A Case Study: Designing a Document Editor “ Lexi ”
Page 66: A Case Study: Designing a Document Editor “ Lexi ”

77thth Pattern Pattern

Iterator Pattern:Iterator Pattern:

The Iterator pattern captures these techniques The Iterator pattern captures these techniques for supporting access and traversal over for supporting access and traversal over object structures. It's applicable not only to object structures. It's applicable not only to composite structures but to collections as composite structures but to collections as well. It abstracts the traversal algorithm and well. It abstracts the traversal algorithm and shields clients from the internal structure of shields clients from the internal structure of the objects they traverse. The Iterator pattern the objects they traverse. The Iterator pattern illustrates once more how encapsulating the illustrates once more how encapsulating the concept that varies helps us gain flexibility concept that varies helps us gain flexibility and reusability.and reusability.

Page 67: A Case Study: Designing a Document Editor “ Lexi ”

Traversal versus Traversal Traversal versus Traversal Actions Actions

Now that we have a way of traversing Now that we have a way of traversing the glyph structure, we need to check the glyph structure, we need to check the spelling and do the hyphenation. the spelling and do the hyphenation. Both analyses involve accumulating Both analyses involve accumulating information during the traversal. information during the traversal.

First we have to decide where to put First we have to decide where to put the responsibility for analysis. the responsibility for analysis.

So analysis and traversal should be So analysis and traversal should be separate. Where else can we put the separate. Where else can we put the responsibility for analysis? responsibility for analysis?

Page 68: A Case Study: Designing a Document Editor “ Lexi ”

Traversal versus Traversal Traversal versus Traversal Actions Actions

Therefore a given analysis must be able Therefore a given analysis must be able to distinguish different kinds of glyphs. to distinguish different kinds of glyphs.

But the trouble with that approach is that But the trouble with that approach is that we'll have to change every glyph class we'll have to change every glyph class whenever we add a new kind of analysis. whenever we add a new kind of analysis.

Yet even if a default implementation Yet even if a default implementation reduces the number of changes, an reduces the number of changes, an insidious problem remains: Glyph's insidious problem remains: Glyph's interface expands with every new interface expands with every new analytical capability. analytical capability.

Page 69: A Case Study: Designing a Document Editor “ Lexi ”

Encapsulating the Analysis Encapsulating the Analysis

Page 70: A Case Study: Designing a Document Editor “ Lexi ”

Visitor Class and Visitor Class and Subclasses Subclasses

We'll use the term We'll use the term visitorvisitor to refer generally to refer generally to classes of objects that "visit" other to classes of objects that "visit" other objects during a traversal and do something objects during a traversal and do something appropriate.In this case we can define a appropriate.In this case we can define a Visitor class that defines an abstract Visitor class that defines an abstract interface for visiting glyphs in a structure. interface for visiting glyphs in a structure.

Concrete subclasses of Visitor perform Concrete subclasses of Visitor perform different analyses. different analyses.

A discretionary glyph has one of two A discretionary glyph has one of two possible appearances depending on whether possible appearances depending on whether or not it is the last character on a line. or not it is the last character on a line.

Page 71: A Case Study: Designing a Document Editor “ Lexi ”
Page 72: A Case Study: Designing a Document Editor “ Lexi ”

88thth Pattern PatternVisitor Pattern:Visitor Pattern:The Visitor class and its subclasses described earlier are the The Visitor class and its subclasses described earlier are the

key participants in the pattern. The Visitor pattern key participants in the pattern. The Visitor pattern captures the technique we've used to allow an open-ended captures the technique we've used to allow an open-ended number of analyses of glyph structures without having to number of analyses of glyph structures without having to change the glyph classes themselves. Another nice feature change the glyph classes themselves. Another nice feature of visitors is that they can be applied to of visitors is that they can be applied to anyany object object structure. That includes sets, lists, even directed-acyclic structure. That includes sets, lists, even directed-acyclic graphs.graphs.

An important question to ask before applying the Visitor An important question to ask before applying the Visitor pattern is, Which class hierarchies change most often? pattern is, Which class hierarchies change most often? The pattern is most suitable when you want to be able to The pattern is most suitable when you want to be able to do a variety of different things to objects that have a do a variety of different things to objects that have a stable class structure. Adding a new kind of visitor stable class structure. Adding a new kind of visitor requires no change to that class structure, which is requires no change to that class structure, which is especially important when the class structure is large. But especially important when the class structure is large. But whenever you add a subclass to the structure, you'll also whenever you add a subclass to the structure, you'll also have to update all your visitor interfaces to include a have to update all your visitor interfaces to include a Visit... operation for that subclass. Visit... operation for that subclass.

Page 73: A Case Study: Designing a Document Editor “ Lexi ”

Design ProblemsDesign Problems

1- Document structure.1- Document structure.

2- Formatting.2- Formatting.

3- Embellishing the user interface.3- Embellishing the user interface.

4- Supporting multiple look-and-feel 4- Supporting multiple look-and-feel standards.standards.

5- Supporting multiple window system.5- Supporting multiple window system.

6- User operations.6- User operations.

7- Spelling checking and hyphenation.7- Spelling checking and hyphenation.

Page 74: A Case Study: Designing a Document Editor “ Lexi ”

SummarySummary

We've applied eight different patterns to Lexi's design:We've applied eight different patterns to Lexi's design:1.1. Composite: Composite: to represent the document's physical to represent the document's physical

structure. structure. 2.2. Strategy: Strategy: to allow different formatting algorithms.to allow different formatting algorithms.3.3. Decorator: Decorator: for embellishing the user interface.for embellishing the user interface.4.4. Abstract Factory: Abstract Factory: for supporting multiple look-and-for supporting multiple look-and-

feel standards.feel standards.5.5. Bridge: Bridge: to allow multiple windowing platforms.to allow multiple windowing platforms.6.6. Command: Command: for undoable user operations.for undoable user operations.7.7. Iterator: Iterator: for accessing and traversing object for accessing and traversing object

structures. structures. 8.8. Visitor: Visitor: for allowing an open-ended number of for allowing an open-ended number of

analytical capabilities without complicating the analytical capabilities without complicating the document structure's implementation. document structure's implementation.

Page 75: A Case Study: Designing a Document Editor “ Lexi ”

Questions ?Questions ?????????