Top Banner
GoF: 2.1-2.6 Document Editor Example A Case Study
68
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: GoF: 2.1-2.6 Document Editor Example A Case Study.

GoF: 2.1-2.6Document Editor Example

A Case Study

Page 2: GoF: 2.1-2.6 Document Editor Example A Case Study.

Designing Lexi, a WYSIWYG Document Editor

• The purpose is to show how design patterns capture solutions to design problems in lexi

• The document can mix text and graphics freely in a variety of formatting styles. It has pull-down menus, scroll bars and collection of page icons for navigation in the document.

Page 3: GoF: 2.1-2.6 Document Editor Example A Case Study.
Page 4: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Editor

• What are your first thoughts about how to build a document editor?

–Internal structure–Formatting–Gui–Spell Check

Page 5: GoF: 2.1-2.6 Document Editor Example A Case Study.

Design Problems

• Document Structure– Internal structure; will affect every aspect of the

design of Lexi, need to traverse

• Formatting– Need to arrange text and graphics into lines &

columns– Which objects carry out formatting– How interact with internal representation

Page 6: GoF: 2.1-2.6 Document Editor Example A Case Study.

Design Problems

• Embellishing the user interface– Scroll bars, borders etc

– Independent of the rest of the application

– Embellishments likely to change as Lexi evolves

• Support multiple look-and-feel (motif, java, pm,..)• Support multiple window systems (MS window,

X, mac, ..)

Page 7: GoF: 2.1-2.6 Document Editor Example A Case Study.

Design Problems

• User Operations– Buttons, pull-down menus, Uniform access

with undo capability

• Spelling checking and hyphenation

Page 8: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Structure• Arrangement of graphical elements (characters,

lines, polygons, etc..)• An author however views theses as document’s

physical structure- lines, columns, figures, tables, and other substructures (not in graphical terms)

So, Users need to treat collection and single elements the same. For example user should be able to refer to a table as a whole not as an unstructured mass of text and graphics.

Page 9: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Structure

• Internal Representation need to support:– Maintaining document’s physical structure, that

is, the arrangement of text and graphics into lines and columns, tables, etc

– Generating and presenting visually– Map position on the display to the internal

representation (lexi would know what s being pointed to)

Page 10: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document structure • We should treat text and graphics uniformly• We should not have to distinguish between a

single element and a group of elements in the internal representation. ( e.g. the tenth element in line five of column two could be a single character or a complex diagram)

-- As long as an element can draw itself and set its dimensions, its complexity should not affect where it appears

• Opposing the above is to analyze for spell checking

Page 11: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Structure • Use Recursive Composition

A technique to represent a hierarchy of structured information

Building increasingly complex elements out of simpler ones.

e.g. we can tile a set of characters and graphics to form a line. Multiple lines can be arranged to form columns, multiple columns to form a page, etc

Page 12: GoF: 2.1-2.6 Document Editor Example A Case Study.
Page 13: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Structure

• We can assign an object to each important element, also to invisible structural elements such as line, column, etc..

Page 14: GoF: 2.1-2.6 Document Editor Example A Case Study.

• Two implications: 1- These Objects need corresponding classes 2- These classes must have compatible interfaces, if we want to treat them uniformly, So the classes must be related through inheritance, possibly through an abstract class.

Page 15: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Structure

• Glyphs: An abstract class for – Primitive graphical elements, and– Structural elements

Page 16: GoF: 2.1-2.6 Document Editor Example A Case Study.
Page 17: GoF: 2.1-2.6 Document Editor Example A Case Study.
Page 18: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document StructureGlyph Responsibilities:

• Draw themselves

Each know how to render itself on the screen

• Where they are, how much space they occupy

A parent glyph needs to know how much space a child occupies, for example to arrange it in line

• Children and parent

We need interfaces to add and remove and access children. A line’s children are the glyphs arranged into a row.

Page 19: GoF: 2.1-2.6 Document Editor Example A Case Study.

• Glyph Subclasses redefine Draw to render themselves on the window

Void Rectangle::Draw(Window* w)

{

W-> DrawRect(_x0, _y0, _x1, _y1);

}

Page 20: GoF: 2.1-2.6 Document Editor Example A Case Study.

Document Structure

• Are there any problems with these Glyphs?

-Strict hierarchy

-Object for every character (efficiency)

-Could share Glyphs

-Flyweight Pattern: share objects between different contexts; operation takes extrinsic state; objects represent internal state

Page 21: GoF: 2.1-2.6 Document Editor Example A Case Study.

Composite Pattern

• Recursive composition can be used to represent any potentially complex hierarchical structure.

• Composite pattern captures the essence of recursive composition in OO terms.

Page 22: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting• We have so far settled on how to represent

the document’s physical structure

• Next we need to decide on how to construct the document’s physical structure (Formatting)

• These two are distinct

Page 23: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• Formatting: breaking collection of glyphs into lines, lines into columns, etc

• For example, the user might vary margin, single or double space, indentation, etc

Page 24: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• Formatting is a complex task. There are variety of algorithms

• Trade-offs: quality, speed

• Many new might be invented

• We need to keep formatting algorithm well contained, completely independent of document structure

Page 25: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• We should be able to add a new glyph subclass without regard to formatting algorithm, and conversely adding a new algorithm should not require changing existing glyphs

Page 26: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• So, we should design Lexi so that it’s easy to change the formatting algorithm (at compile-time, event at run-time).

To do this:

• We can isolate the algorithm and make it easily replaceable by encapsulating it in an object

Page 27: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• More specifically, we’ll define a separate class hierarchy of algorithm objects.

• The root will contain interfaces for a wide range of formatting algorithms, and each subclass will implement a particular algorithm.

• Then we can introduce a new Glyph subclass that will structure its children automatically using a given algorithm object

Page 28: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting• Encapsulating Format algorithm

– Compositor: class for formatting algorithm objects

• What glyphs to format and when to do the formatting

Responsibility Operation

What to format Void SetComposition(Composition *)

When to format Virtual void Compose()

Page 29: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

Page 30: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

Composition: special glyph subclass• It formats children of a special glyph subclass called

composition

• A composition gets an instance of a Compositor (e.g specific line-breaking algorithm) when created and tells compositor to compose its glyphs

Page 31: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

Page 32: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• How it works: An unformatted object contains only visible glyphs, not Rows or columns. The composition is in this state just after initialized with the glyphs it should format. It then calls its compositor’s compose operation to format it’s children according to a particular algorithm.

Page 33: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

column

rowrow

Page 34: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• Compositor-Composition ensures strong separation between physical representation and formatting

• We can even change algorithm at run-time by adding a single SetCompositor operation to composition’s basic glyph interface

Page 35: GoF: 2.1-2.6 Document Editor Example A Case Study.

Formatting

• Strategy Pattern– Objects encapsulate algorithms and the context in

which they operate

– Compositors are strategies,

– A Composition is the context for compositor strategy

– The Key is to design interface to support range of algorithms. Shouldn’t have to change the strategy or context interface to support a new algorithm.

Page 36: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

• Border and Scrollbar

• Easily add and remove– No inheritance (run-time, lots of classes)To easily add and remove embellishments specially at runtime we

should not use inheritance. We should be able to add and

remove embellishments without changing other classes.

Page 37: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

• We could add a border to composition by sub-classing it (BorderedComposition class), or the same way for scrollbar to get ScrollableComposition

• Subclass it again to get ScrollableBorderedComposition Class

Problem: we end up a class for every possible combination, an unworkable solution

Page 38: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

– Object composition potentially more workable (embellishment is object)

Who composes whom?• Border contain Glyph?

• Glyph contain Border? (need to modify glyph class to be aware of border)

First choice keeps the border-drawing code entirely in the Border class leaving other classes alone

Page 39: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

• Borders have an appearance, so they should actually be glyphs (Border should be subclass of Glyph)

• In addition clients should not care whether Glyph have borders or not. If a glyph is composed in a border, clients should not treat it differently than a plain glyph

So, we need to subclass Border from Glyph to guarantee this

Page 40: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

All this leads us to the concept of:

• Transparent enclosure– 1) single child (or single component)

composition– 2) compatible interfaces (clients can’t tell if they

are dealing with a component or it’s enclosure.)

Page 41: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface– Enclosure can augment component’s behavior by doing work

before and/or after delegating an operation.. So we define a new

subclass of Glyph, the MonoGlyph to serve as an abstract class for embellishment glyph.

– MonoGlyph (subclass of glyph)– Stores reference to a component (glyph) and

forwards requests to it (see the code)

Border

Draw()DrawBorder()

Glyph

Drwa()

MonoGlyph

Draw()

Scroller

Draw()

MonoGlyph

Draw()

component

MonoGlyph class diagram

Page 42: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing ..

Void MonoGlyph::Draw (window* w) {

-component->Draw(w);}

– Performs embellishment before or after sending glyph the request (draw itself) Void MonoGlyph::Draw (window* w) {

-component->Draw(w);

DrawBorder(w);}

Page 43: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

• The same way we define another Monoglyph, the scroller.

• We put composition instance in the scroller instance, and the resulting

composition in the Border instance.

Page 44: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishment..

Question: Should border contain scroller or the reverses?

Result: Transparent enclosure keeps clients free of embellishment code.

Page 45: GoF: 2.1-2.6 Document Editor Example A Case Study.

Embellishing the User Interface

• Decorator Pattern– Attach additional responsibilities to object

dynamically– Enclose component in another component– Nest decorators recursively– Forwards requests to component– Can perform additional actions before or after

Page 46: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

• Portability across hardware and software platforms is a major problem in system design. Part of portability is supporting multiple user interface style guides on each platform.

• Look-and-feel standards define guidelines for how applications appear and react to the user.

• Lexi should support multiple existing look-and-feel standards and make it is to support future ones

• Also support changing look-and-feel at runtime

Page 47: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

• Everything we see in Lexi is a glyph composed in some invisible glyph. look-and-feel style guides deal with “widgets”, visible glyphs such as buttons,etc

We assume we have 2 sets of widget glyph classes:– Set of abstract glyph subclass for each widget category

– Set of concrete subclasses to implement different standards

Page 48: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

• Lexi needs to use different concrete widget glyphs for different look-and-feel, for example, MotifButton, PMButton, MacButton, etc

• But How? Can Lexi create theses directly in say a constructor?

- Hard-coding the button of particular style make it impossible to select the style at run-time

( e.g scrollBar* sb= new MotifScrollBar;)

- We also have to track down and change every such constructor call to port to another platform

- Littering code with constructor calls to specific look-and-feel classes yields a maintenance nightmare

Page 49: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

1- We Must avoid making explicit constructor calls

2- We must be able to replace an entire widget set easily

We can achieve both by:

abstracting the process of object creation

Page 50: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

Example (C++):

Scrollbar* sb= new MotifScrollbar; (this is what we want to avoid)

But suppose we do this: Scrollbar* sb= guiFactory->CreateScrollbar();Where guiFactory is an instance of MotifFactory class.

For Clients the effect is the same, but there is one crucial difference: There is no mentioning of Motif by name in the code.

Page 51: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

• guiFactory objects abstract the process of creating scrollbars for any look-and-feel standard. And it can manufacture any widget glyph for that standard.

Figure 2-9 shows GUIFactory class heierachy for guiFactory objects.

Page 52: GoF: 2.1-2.6 Document Editor Example A Case Study.
Page 53: GoF: 2.1-2.6 Document Editor Example A Case Study.

• Factories make product objects that are related (belong to the same look-and-feel in this case)

Page 54: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

• Question: Where doe GUIFactory instance come from?

Answere: Anywhere convenient, guiFactory can be a global, an static member of a well known class, or a Singleton object ( another design pattern)

The important point is to initialize before it’s used and after it’s clear which look-and-feel is desired.

(Look at the initialization code next slide)

If we change our mind, we can reinitialize guiFactory and get a new look-and-feel at runtime

Page 55: GoF: 2.1-2.6 Document Editor Example A Case Study.

GUIFactory* guiFactory; const char* styleName= getenv(*LOOK_AND_FEEL*);If (strcmp(styleName, “Motif”) == 0) {

guiFactory=new MotifFactory;} else if (strcmp(styleName, “Presentation_Manager”) ==0) { guiFactory = new PMFactory;} else …

Supporting Multiple Look-and-Feel Standards

Page 56: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Look-and-Feel Standards

• Abstract Object Creation with Factories– One class is responsible for creating objects– Set standard and then all objects are created with that

standard

• Abstract Factory Pattern– Provides interface for creating families of related or

dependent objects without specifying concrete classes– Swap entire families of products by replacing the concrete

factory• Singleton

– Ensure a class has only on instance– Provide global point of access

Page 57: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• Can we use an Abstract Factory?– Unlikely interface for different vendors are

compatible thus don’t have common abstract product class

Remember we could only apply Abstract factory where we could define a common abstract product (e.g. Button widget) from which we could subclass concrete

products (MotifButton, PMButton,MacButton)

Page 58: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• Things are a bit tougher since different windowing systems do not provide compatible interfaces

• We need a uniform set of windowing abstractions that let us take different window system implementations and slide any one of them under a common interface

Page 59: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

– Encapsulating Implementation Dependencies• Window Class: general actions

– Draw basic geometric shapes

– Iconifiy and de-iconify themselves

– Resize self

– Redraw contents on demand

Page 60: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

The Two extreme:

• Intersection of functionalities? Trouble: We loose a lot of functionalities

• or union of functionality?Trouble: the resulting interface maybe huge and incoherent. We also have

to revise the code for every new vendor

Page 61: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• The solution falls somewhere between the two. The Window class would have interfaces that support the most popular windowing features. Table 2.3 provides a sample.

Page 62: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• The concrete subclasses of our Window class support different kinds (not platform) of windows such as

dialogWindow, warningWindow, applicationWindow, etc

Page 63: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• Now where does platform-specific window come in?

One approach: Implement one version of our Window class and subclasses for each Windowing platform? Imagine the maintenance headache to keep track of multiple classes all named “Window” but each implemented for a different windowing system

Page 64: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• Another approach: Implementation specific subclasses of Window class?

And end up with another subclass explosion

• In addition, none of these approaches give the flexibility to change the window system after compile. So we need to keep

several different executables. • So, what can we do?

Page 65: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

• Encapsulate the concept that varies (window system implementation in this case)

• WindowImp class: abstract class for objects that encapsulate system-dependent code

• Configure window object with instance of WindowImp subclasses

Page 66: GoF: 2.1-2.6 Document Editor Example A Case Study.

Supporting Multiple Windows Systems

Page 67: GoF: 2.1-2.6 Document Editor Example A Case Study.

• Bridge Pattern:– Decouple abstraction from implementation

The relationship between Window and WindowImp is an example of Bridge pattern

The intent is to allow separate class hierarchies work together even as they evolve independently.

Supporting Multiple Windows Systems

Page 68: GoF: 2.1-2.6 Document Editor Example A Case Study.

Take Away

• You’re not a fortune teller• Decoupling/Independence

– Internal/external, abstraction/implementation

• Use patterns appropriately:– Inheritance vs. object composition (user interface)– Abstract Factory vs. Encapsulate Dependencies

(Window)

• Transparency• Focus on the concept that varies