CSC223 2004F, Class 37: Design Patterns (2): Case Study: Text Editor Admin: * Discussion/a moment of silence * Sam runs eboard today * Consideration of final: Retrospective essay on project: How would I have applied the four books to the project if I knew everything when I started? * Consideration of project: Due Friday the 10th * Gifts! Overview: * The case: Designing a text editor * Questions and Answers * Nine key patterns: * Composite (163): Make the compound object implement the same interface as the objects it contains * Strategy (315): Done * Decorator (175): Done * Abstract Factory (87): Groups constructors * Bridge (151) * Command (223): Encapsulate an algorithm in an object * Iterator (257): Visit complex structures * In Java * Visitor (331): Visit complex structures * In Java * Flyweight (195): Limit explosion of objects * Strings in Java The Problem: We need to design a graphical text editor * Identify subproblems * Find patterns that will help us solve the subproblems * Learn more about those patterns Global issues in designing a graphical text editor: * Layout: How do you figure where on the screen stuff goes? * "Look and Feel": How do you design your text editor so that it adapts to different looks and feels? * Platform: How do you design your text editor so that it ports easily to different platforms? * Spell-checking: How do you design your data so that it's easy to check spelling (and do other analyses of the text)? * Data representation: How do we internally represent the structure of the text? * Commands: How do we separate the operation from the UI stuff for making the commands? * Undo: How do we permit someone to "undo" an operation? /Layout/ * Figuring out where stuff goes on the screen * Given a sequence of stuff, figure out the line breaks given known restrictions on width (etc) * Handle the problem of images next to text. (This changes width.) * Centering text (might be doable by the basics) * Uniformity of spacing. A paragraph in which some lines are spaced really far apart andothersareclosedlyspacedtogether doesn't look very good * "Color" of document (ratio of text to spacing) * Inter-word vs. intra-word spacing * No rivers * Conclusion: There are many different algorithms I might write. We might apply different ones at different times. * How do we handle different algorithms? * Our solution: * Add "attributes" to algorithms to help the user decide which one to use * Encapsulate the algorithm into methods and take advantage of polymorphism * Have a generic interface for the kind of algorithm public interface Sorter { public void sortInPlace(Object[] stuff); } * Each implementation gets put into a different class public class InsertionSorter implements Sorter { public void sortInPlace(Object[] stuff) { for (int i = 1; i < stuff.length; i++) insert(stuff, i); } public void insert(Object[] stuff, int top) { while (stuff[top] < stuff[top-1]) { swap(stuff, top, top-1) top--; } } } public interface Formatter { public void format(Text t); } Solution: Use the Strategy Pattern * Name: Strategy * Type: Object, Behaviorial * About objects (rather than classes) * About behavior rather than structure or creation * Intent: Define and encapsulate a family of algorithms; Let algorithms vary independently of client * AKA: Policy, Encapsulated Algorithm * Motivation: Our example * Applicability: * Related classes that differ in behavior * Multiple versions of an algorithm * Clients don't know about data * Attempt to code multiple behaviors as a switch * Structure: Ooh UML * Participants: * Strategy (interface) * Impelemtnatiuon of the Strategy (ConcreteStrategy implements Strategy) * Conext (user of the strategy) * Collaborations: * Context and strategy communicate * Context sends data (or itself) to strategy * Clients send strategy *once* to context * Clients interact with context * Consequences: * Group families of related algorithms * Alternative to subclassing context * Eliminates conditionals * Problem: More objects * Problem": Client must know different strategies * Implementation * Sample Code (in C++) * Known Uses: (Famous Programs) * Related Patterns: FlyWeights Problem: How to support more complex UIs (scrollbars, borders, etc.) * One strategy: Subclassing Pane BorderedPane BordredShadowedPane BorderedScrollbarPane ScrollbarPane ShadowedScrolbarPane ShadowedPane * Problems: * Hard-wiring extensions * What happens when you want multiple extensions: You get a whole bunch of classes Solution? Decorator/Wrapper * Instead of subclassing, you build wrappers that implement the same interface and *take an object of the main interface* as parameters public interface Pane { ... } public class RealPane implements Pane { ... } public class BorderedPane implement Pane { public BorderedPane(Pane base) ... } public class ScrollBarPane implement Pane { public ScrollBarPane(Pane base) ... } To get a bordered scrollbar pane Pane p = new BorderedPane(new ScrollBarPane(new RealPane())); Have you seen this pattern before? If so, where? * Sam used it for extending functionality of candy machines * Swing does some of this * Java I/O does some of this Advantages? * Reduces profusion of classes * Eases combination * ... Disadvantages? * Permit unreasonable combinations * ...