1 / 23

6894 · workshop in software design lecture 5 · october 14, 1998 · design patterns

6894 · workshop in software design lecture 5 · october 14, 1998 · design patterns. topics. schedule October 19 reading on concurrent design patterns catalog of about 10 design patterns http://gee.cs.oswego.edu/dl/cpj/index.html October 21 instead of Problem Frames, discuss design proposals

Download Presentation

6894 · workshop in software design lecture 5 · october 14, 1998 · design patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 6894 · workshop in software designlecture 5 · october 14, 1998 · design patterns

  2. topics • schedule • October 19 • reading on concurrent design patterns • catalog of about 10 design patterns • http://gee.cs.oswego.edu/dl/cpj/index.html • October 21 • instead of Problem Frames, discuss design proposals • each team bring a 5-10 minute presentation • design proposals • scope • can be on some aspect of the CM • on an entire redesign of the CM • form • 1. problem addressed • 2. solution proposed • 3. strategy, esp. minimal subset

  3. origins • motivation • capture expertise of experienced designers • reuse of design practice and form • provide vocabulary for design • history • Christopher Alexander et al: A Pattern Language (1977) • Erich Gamma’s PhD thesis (1991): about half of the GOF patterns • Coplien: Advanced C++ Styles and Idioms (1992) • Helm, Vlissides, Johnson: summary of pattern catalog in ECOOP (1993) • Gamma et al: Design Patterns (1995) • often referred to as the Gang of Four Book (GOF)

  4. how patterns help • flexibility • make code less susceptible to changes • confine changes as much as possible • examples: confine changes in … • representation (Factory, Bridge, Memento, Proxy) • algorithm (Builder, Iterator, Strategy, Template, Visitor) • platform (Factory, Bridge) • adding new features (Observer, State, Mediator) • documentation • patterns are familiar to programmers • name alone says a lot • archaeology • patterns record best practices • target for research ideas, language evaluation, etc

  5. what’s in a pattern? • GOF style presentation • name • very important! • problem • difficulty addressed by pattern • motivating example • solution • general form of pattern • implementation advice • variants • consequences • not just benefits – liabilities too • all patterns add complexity • most reduce efficiency

  6. how patterns work • standard use of language constructs • algebraic datatypes (Composite) • closures (Factory) • class variables (Singleton) • inheritance (Template) – but maybe not standard use? • ad hoc tricks • hand-coded dispatch (Visitor) • dynamic reclassification (State) • cloning + cursor (Iterator) • opaque association • (my term) • Adapter, Bridge, Mediator, Observer, Proxy

  7. GOF bias: delegation over inheritance • example • Window and Rectangle • with inheritance • Window subclass of Rectangle • getArea method of Window is inherited • resize method of Window calls methods and uses instance vars of Rectangle • with delegation • Window’s rep includes a Rectangle • getArea method of Window just invokes getArea of Rectangle • advantages of delegation • runtime composition: Window can become circular by switching Rep • better modularity: avoid abstraction violations of inheritance • disadvantages of delegation • a bit clumsier than inheritance • objects have distinct types: can’t pass Window to method expecting Rectangle • but Window is probably not a subtype of Rectangle anyway • less of an issue in dynamically-typed languages, eg. Scheme

  8. GOF bias: others • no parametric polymorphism • most useful at lower level of abstraction? • notion of association (from OMT) hides representation of set or table • objects, not functions • closures rarely used • with exception of Visitor, State, …? • patterns are very imperative in flavour

  9. opaque association • motivation • behaviour of two objects A and B is tightly coupled • want coupling only at runtime, not compile time • change to B’s code should not affect A’s • basic idea • loosen compile time coupling by • having A access B through an opaque association • A’s code no longer depends on B’s interface • two ways to achieve • indirection • A accesses B through another object, X • specification • A accesses B as if it has a specification S that is weaker than its actual specification • consequences of this style of design • more complex compile-time structure • greater disparity between compile-time and runtime structures • more elaborate runtime invariants

  10. class models • elements • a box represents a class • a bar represents a specification • an arrow from box A to box B means • A’s code calls a method on a B object • an arrow from A to B through spec S • A’s code calls a method of a B object, but views B as having spec S • if arrow is dotted, association is transient: B object not in rep of A A B A B S

  11. why yet another notation? • object model plays two roles • abstract state • what objects exist, what invariants hold, etc • class structure • what code modules exist, dependences, namespace, etc • shouldn’t be conflated • specs are not just sets of objects! • spec describes what properties are expected in the future • class structure should be postponed • abstract state description is a specification activity • allocation of methods and state to classes is a design activity • design patterns suggest major deviation from problem domain structure • snags caused by shared notation • OCL’s typecasts: much more complex than Alloy’s simple set ops • no superclass/interface distinction • only one occurrence of an interface node with a given name • so Enumeration, eg, can only occur once! • but different Enumerations often unrelated

  12. disentangling design patterns: observer • essential feature • ConcreteSubject views ConcreteObserver through Observer • code sharing in Subject is a minor detail Subject Attach (Observer)Detach (Observer)Notify () Observer Update () observers * for all o in observers { o.Update (); } observerState = subject.GetState () Concrete Subject GetState ()SetState () subjectState Concrete Observer Update () observerState ! subject return subjectState

  13. CLIENT ADAPTER ADAPTEE TARGET adapter CLIENT PROXY SERVICE SERVICE proxy IMPL-A CLIENT REFINED IMPL-B ABSTRACTION bridge examples of opaque association (1)

  14. COLL-1 CMEDIATOR COLL-2 MEDIATOR mediator CSUBJECT COBSERVER observer OBSERVER STATE-A CLIENT CONTEXT STATE-B state STATE examples of opaque association (2)

  15. examining a DP: visitor • visitor is unusual • designed to overcome OO-ness of OO language • a great idea or a clever hack? • discussed in detail in • Felleisen & Friedman, A Little Java, A Few Patterns ELEMENT-A VISITOR-X ELEMENT-B

  16. visitor example • AST for arithmetic expressions • suppose language is • expr ::= literal | variable | expr + expr | expr * expr | - expr • might implement as AST with: • interface Expr • class Literal implements Expr • class Variable implements Expr • abstract class BinaryExpr implements Expr • class MinusExpr implements Expr • operations on AST • evaluate for given binding of variables to literals • pretty print • reduce (eg, replace e + 0 by e) • observation • many involve similar traversals • awkward to implement each new operation by adding method to each class • would rather add a new class for each operation

  17. sample Visitor code • interface Visitor { void for_Literal (Literal x); void for_Variable (Variable x); void for_BinaryExpr (BinaryExpr x); void for_MinusExpr (MinusExpr x); } • class Literal implements Expr { … void accept (Visitor v) { v.for_Literal (this); } } • class PrettyPrintV implements Visitor { PrettyPrintV () {}; void for_Literal (Literal x) { System.out.println (x.toString()); } void for_BinaryExpr (BinaryExpr x) { x.left.accept (this); System.out.println (x.op.toString()); x.right.accept (this); } } • note • Visitor accesses representation of visited class!

  18. visitor as closure • basic idea • visitor provides convenient context for state to be maintained over traversal • examples • encapsulate output stream • PrettyPrintV (Stream s) {stream = s;}void for_Literal (Literal x) {stream.println (x.toString());} • encapsulate Variable -> Literal binding • EvaluateV (Binding b) {…}Object for_Variable (Variable x) {return b.get (x);} • other examples • instrumentation/debugging

  19. functional visitor • basic idea • a kind of ‘map’ • transforms one AST to another with nodes of different types • operation types • C’ Visitor::for_C (C) • C’ C::accept (Visitor) • inflexibility of Java’s subtyping rules a pain • lots of unnecessary downcasts; C’ must be Object • sample code • class C { • D d; E e; Object accept _functional (FunctionalVisitor v) { return v.for_C (this); } • class VisitorX implements FunctionalVisitor { Object for_C (C c) { DD dd = (DD) c.d.accept_functional (this); EE ee = (EE) c.e.accept _functional (this); return someFunction (dd, ee); }

  20. imperative visitor • basic idea • mutates each element of AST • operation types • void Visitor::for_C (C) • void C::accept (Visitor) • sample code • class C { • D d; E e; void accept_imperative (ImperativeVisitor v) { v.for_C (this); } • class VisitorX implements ImperativeVisitor { void for_C (C c) { c.d.accept_imperative (this); c.e.accept_imperative (this); … return; }

  21. replacing visitor • replacing visitor • type structure of functional visitor, but mutates like imperative visitor • operation types • C’ Visitor::for_C (C) • C’ C::accept (Visitor) • sample code • class C { D d; E e; Object accept _replacer (ReplacingVisitor v) { return v.for_C (this); } • class VisitorX implements ReplacingVisitor { Object for_C (C c) { if (…) return new C (…) else { c.d = (D) c.d.accept_replacer (this); c.e = (E) c.e.accept_replacer (this); return c; } }

  22. exploiting subclassing • basic idea • make Visitor a superclass, not an interface • dummy implementation for each element type • imperative visitor: applies the visitor to the subelements • replacing visitor: replaces the subelements using the visitor • each visitor implementation only overrides behaviour for some elements • examples • imperative: to print out all literals • class PrintLiteralV extends ImperativeVisitor { void for_Literal (Literal x) {stream.println (x.toString());} } • replacing: replace all variables by dummy literals • class InstantiateR extends ReplacingVisitor { Object for_Variable (Variable x) {return new Literal ();} } • then all you need is the first call • expr.accept (new FooVisitor (…)); • this is a major advantage of Visitors!

  23. but … subclassing snags • can’t subclass in the element hierarchy • suppose we have • abstract class BinaryExprclass PlusExpr extends BinaryExprclass TimesExpr extends BinaryExpr • now suppose we want a visitor that prints out binary exprs only • will this work? • class PrintBinExprV implements Visitor { for_BinaryExpr (BinaryExpr x) { stream.println (x.toString ()); } } • no! • for_BinaryExpr is never called • it’s a method associated only with the abstract class, which has no objects • a flawed solution • default implementation of for_PlusExpr calls for_BinaryExpr • can now override for_BinaryExpr and get intended behaviour for this PrintBinExprV • but cannot write PrintLiteralV by overriding for_Literal alone • for_PlusExpr calls for_BinaryExpr and not left.accept!

More Related