design’paern’’ a’case’study:’...
TRANSCRIPT
Design Pa*ern A Case Study:
Designing A Document Editor
CSCI 3132 Summer 2011 1
Lexi Features • WYSIWYG Document Editor
• Mix text and graphics in a variety of styles
• pull-‐down menus
• scrollbars • Icons for jumping to a
parJcular page
2
Design Problems
1. Document Structure How do we represent a document?
2. FormaPng How do we arrange text and graphics on the screen (or paper)
3. Embellishing the user interface
4. SupporJng mulJple look-‐and-‐feel standards
5. SupporJng mulJple window systems
6. User OperaJons 3
Document Structure
• Affects nearly every aspect of Lexi’s design • What are the impacts of the structure we choose?
• What do we need to consider?
4
Design Issue #1: Document Structure
• Documents are really just a combinaJon of characters, lines, polygons, etc.
• O^en a user will want to deal with things at a higher level (ex. a picture or a row or column of a document)
• To make Lexi user-‐friendly, we need to allow the user to deal with these higher level constructs
5
Design Issue #1: Document Structure
• The internal representaJon of the document structure should match the physical structure
• Allow arrangement of text and graphics into lines, columns, tables, etc.
• Need to draw the document on the screen
• Need to map mouse clicks to specific parts of the document to be handled at the right level.
• Treat text and graphics uniformly. So we can embed graph within text or vice versa.
6
Design Issue #1: Document Structure
7
Design Issue #1: Document Structure
Recursive Composi.on • A method for represenJng a hierarchy of informaJon • A grouping of simple items to create a composite item • Groupings of items can be a part of even higher level
groups
8
Design Issue #1: Document Structure
– ImplicaJons • Objects need corresponding classes
• All of these classes need compaJble interfaces – Allows us to treat them uniformly
– Meet the Glyph
Responsibility Operations
Appearance virtual void Draw(Window*)!
virtual void Bounds(Rect&)!
Hit Detection virtual bool Intersects(const Point&)!
Structure virtual boid Insert(Glyph*, int)!
virtual void Remove(Glyph*)!
virtual Glyph* Child(int)!
virutal Glyph* Parent()! 9
Design Issue #1: Document Structure
10
Design Issue #1: Document Structure
– Recursive ComposiJon – It’s not just for documents
– Useful for any potenJally complex, hierarchical structure
– The Composite pa*ern captures this design approach
– Intent: Compose objects into tree structures to represent part-‐whole hierarchies.
Composite lets clients treat individual objects and composiJons of objects uniformly.
11
The Composite Pa*ern
Defines behavior For the primitives
Forwards requests to children
- Behavior for composites - Stores Child components
12
Design Issue #2 FormaPng
• How to construct a par+cular physical structure • And maintain separaJon of data and view (format)
• Properly forma*ed document • Some possible responsibiliJes:
• Break text into lines • Break lines into columns
• Margin Widths • IndentaJon
• TabulaJon
• Single/Double Spacing
– Authors restrict the example to breaking glyphs into lines 13
Design Issue #2 FormaPng
– Important Trade-‐Off • FormaPng quality vs. formaPng speed • FormaPng speed vs. Storage requirements
– It will be complex… so our goals: • Keep it well-‐contained
• Independent of document structure – Add a new glyph… not have to worry about changing format code
– Add new formaPng algorithm – not have to change glyphs
14
Design Issue #2 FormaPng
– Needs to be easy to change the formaPng algorithm
• If not at run-‐Jme, at least at compile-‐Jme – We can make it independent, self contained and replaceable by puPng it in its own class
– We can make it run-‐Jme replaceable by creaJng a class hierarchy for formaPng algorithms
– Compositor
Responsibility Operations
What to format void SetComposition(Composition)!
When to format virtual void Compose()!
15
SoluJon
– ComposiJon object – when created contains the glyphs that determine content, but not structure (such as row, column)
– When Compose() is called, it iterates the glyphs and composes (formats) them.
16
Design Issue #2 FormaPng
– Rows and Columns are inserted by the compositor according to the line-‐breaking algorithm.
17
– Why do we need different Compositor’s? • SimpleCompositor might do a quick pass without regard for such esoterica as the document's "color." Good color means having an even distribuJon of text and whitespace.
• A TeXCompositor would implement the full TeX algorithm, which takes things like color into account in exchange for longer formaPng Jmes.
– Compositor-‐ComposiJon class split ensures a strong separaJon between code that supports the document's physical structure and the code for different formaPng algorithms
– We can change the linebreaking algorithm at run-‐Jme by adding a single SetCompositor operaJon to ComposiJon's basic glyph interface.
SoluJon
18
Strategy Pa*ern
– Have we seen this before?
– EncapsulaJng an algorithm in an object is the intent of the Strategy pa*ern.
– Key parJcipants in the pa*ern are • Strategy objects (Compositors) • Context object (ComposiJon)
– The key to using Strategy
• Interfaces for the strategy and the context that will support a range of algorithms
• Ideally we don’t want to change these interfaces to support a new algorithm
19
Design Issue #3 Embellishing the user interface
– Two Embellishments • Add a Border around the text ediJng area • Add scroll bars
20
– Basically, we want to extend the code to provide a Transparent Enclosure
• Transparent in that the page itself does not know anything about the changes – it behaves the same
– How should we do this? • We could use Inheritance, how would that look? • We have a ComposiJon class…
– To add a Border we add a BorderedComposiJon
– To add a Scroll bar we add a ScrollableComposiJon
– What about both? BorderedScrollableComposiJon?
– How could we do it with object composiJon instead? • What object “has” what object? • How do we make it extensible?
Design Issue #3 Embellishing the user interface
21
Design Issue #3 Embellishing the User Interface
– This is an example of the Decorator Pa*ern
– called “MonoGlyph” in the book // I pass the buck…!void MonoGlyph::Draw (Window* w) !{ _component->Draw(w); } !
// Extend Draw!void Border::Draw (Window* w) { MonoGlyph::Draw(w); DrawBorder(w); }
Multiple Embellishments….
22
Decorator
23
Decorator Related Pa*erns
– Adapter: A decorator is different from an adapter in that a decorator only changes an object's responsibiliJes, not its interface; an adapter will give an object a completely new interface.
– Composite: A decorator can be viewed as a degenerate composite with only one component. However, a decorator adds addiJonal responsibiliJes—it isn't intended for object aggregaJon.
– Strategy: A decorator lets you change the skin of an object; a strategy lets you change the guts. These are two alternaJve ways of changing an object.
24
Design Issue #4 SupporJng MulJple Look-‐and-‐Feel Standards
– One major problem in portability… consider look-‐and-‐feel for
• Windows
• Max OS X • KDE
– If re-‐targeJng is too difficult (expensive), it won’t happen
– NOTE: Just one of the issues… Look-‐and-‐Feel … we deal with the Windowing system itself next
– We want to define the product type at compile Jme or run-‐Jme (based on environment or user input)
25
SoluJon // Creating a scrollbar…!ScrollBar* sb = new MotifScrollBar(); //?!ScrollBar* sb = guiFactory->CreateScrollBar(); !
Abstracting the process of object creation 26
SoluJon
27
Abstract Factory Related Pa*erns
– AbstractFactory classes are o^en implemented with factory methods (Factory Method ), but they can also be implemented using Prototype.
– A concrete factory is o^en a singleton (Singleton) that specifies a Single Instance.
28
Design Issue #5 SupporJng MulJple Window Systems
– What about the Windowing System itself?
– The APIs differ… not just the visual elements – Can we use Abstract Factory?
• Not easily… vendors already define class hierarchies
• How do we make classes from different hierarchies comply to the same abstract type?
29
Design Issue #5 SupporJng MulJple Window Systems – Common things a Window class must do (responsibiliJes)
• Provide operaJons for drawing basic geometric shapes
• Maximize/Minimize • Resize
• (re)draw contents on demand (when restored, overlapped, obscured, etc…)
– We can • define a uniform set of windowing abstracJons (common interface)
• Hide the individual implementaJons
30
SoluJon
Responsibility Operations
window management virtual void Redraw()!
virtual void Raise()!
virtual void Lower()!
virtual void Maximize()!
virtual void Minimize()!
graphics virtual void DrawLine()!
virutal void DrawRect()!
virtual void DrawPolygon()!
Virtual void DrawText()!
31
SoluJon
32
Bridge
Encapsulating Implementation Dependencies
void Rectangle :: Draw (Window* w) {! w -> DrawRect(_x0, _y0, _x1, _y1);!}!void Windsow::DrawRect (coord x0, coord y0, coord x1, coord y1)
{ _imp->DeviceRect(x0, y0, x1, y1); }!
33
Bridge Pa*ern Related Pa*erns
– An Abstract Factory can create and configure a parJcular Bridge
– The Adapter pa*ern is geared toward making unrelated classes work together. It is usually applied to systems a^er they're designed. Bridge, on the other hand, is used up-‐front in a design to let abstracJons and implementaJons vary independently.
34
Design Issue #6 User OperaJons
– Possible OperaJons • CreaJng a new document • Open, save, print a document
• Cut and Paste • Format text
– We have different interfaces for these operaJons • Different Look-‐and-‐Feel
• Different Windowing Systems • Different Access Points (menu, shortcut key, context menu)
– We want independence from the UI • UI triggers the acJon, but I don’t depend on the UI
35
Design Issue #6 User OperaJons
– Furthermore… • The operaJons are implemented in many different classes
• We want to access the funcJonality without adding dependency between the UI classes and all of the different classes involved
– That’s not all • We also want to support undo and redo for some funcJonality
– We need to encapsulate the request.
36
Command
37
SoluJon
– Each MenuItem can store an appropriate command
38
SoluJon
– What about Undo? We add an Unexecute() method and keep a command history…
UNDO REDO
39
Command Pa*ern Related Pa*erns
– A Composite can be used to implement MacroCommands.
– A Memento can keep state the command requires to undo its effect.
– A command that must be copied before being placed on the history list acts as a Prototype.
40