10/21/2011

Prototype pattern

 Every object is itself a factory  Each class contains a clone method that creates a copy of the receiver object class Bicyle { Bicycle clone() { ... } }  Often, Object is the return type of clone CSE 331  clone is declared in Object  Design flaw in Java 1.4 and earlier: the return type may SOFTWARE DESIGN & IMPLEMENTATION not change covariantly in an overridden method II  That is, the return type could not be made more restrictive  This is a problem for achieving true subtyping

Autumn 2011

Using prototypes

class Race {  Change the factory without changing the code with external Bicycle bproto; dependency injection // constructor BicycleFactory f = ((BicycleFactory) DependencyManager.get("BicycleFactory")); Race(Bicycle bproto) { this.bproto = bproto; } Race r = new TourDeFrance(f); Race createRace() {  Plus an external file Bicycle bike1 = (Bicycle) bproto.clone(); Bicycle bike2 = (Bicycle) bproto.clone(); ... } Tricycle }

+ Change the factory without recompiling  Again, we can specify the race and the bicycle separately - Harder to understand (for example, new TourDeFrance(new Tricycle()) without changing any Java code the program might call a different factory)

A brief aside: call graphs Precision

 A call graph is a set of pairs describing, for a given program, which units  Of course, there’s an easy algorithm to create a not-very-useful static call (usually methods) call other units (usually methods) graph   for (m : method)  Eclipse, for example, has a Call Hierarchy view (where the Callee for (n : method) Hierarchy option is often best) that is at times useful in programming include in call graph {, ,  A question is precision – how many false positives are included ( that are …} included to be conservative but that cannot ever be executed)?  This is a static call graph – analyze the program and return a call graph  And inversion-of-control complicates this further – using the dependency representing all calls that could happen in any possible execution of the injection pattern, for example, creates a static connection between program that would require quite complex analysis to report  (A dynamic call graph is one built by executing the program one or more  In practice all or almost all inversion-of-control invocations are omitted in static call graphs times and returning all calls that did take place in those executions)  Even if a programmer is not using a static call graph, he or she is going through similar reasoning, and can also become confused or required to analyze in more detail in the  Static call graphs are generally expected to be “conservative” – face of inversion-of-control – so be thoughtful and careful about this issue! that is, there are no false negatives, meaning that every that  This fuzzy connection can make it harder to understand and to change a program, can ever be invoked over any execution is included in the call graph although it can also make it easier to change a program – that’s right, it can make it harder and easier to change at the same time

UW CSE331 Autumn 2011 UW CSE331 Autumn 2011

1 10/21/2011

Sharing Interning pattern

 Reuse existing objects instead of creating new ones  Interning: only one object with a particular (abstract) value exists at run-time  Less space  May compare with == instead of equals()

 Factory method returns an existing object, not a new  Permitted only for immutable objects

one 1-100 (Street- NumberSet)  Flyweight: separate intrinsic and extrinsic state, "Univ. Way" (Street- "Univ. Way" (String) represent them separately, and intern the intrinsic Segment) (String) StreetSegment with interning 1-100 "O2139" (Street- state (String) NumberSet) StreetSegment (Street- Segment) without interning 101-200  101-200 (Street- Implicit representation uses no space (Street- NumberSet) NumberSet) (Street- Segment) (Street- "Univ. Way" Segment) (String) "O2139" (String)

"O2139" (String)

java.lang.Boolean does not use Interning mechanism the Interning pattern

public class Boolean {  Maintain a collection of all objects private final boolean value;  If an object already appears, return that instead // construct a new Boolean value HashMap segnames; // why not public Boolean(boolean value) { // Set? this.value = value; String canonicalName(String n) { } if (segnames.containsKey(n)) { return segnames.get(n); public static Boolean FALSE = new Boolean(false); } else { public static Boolean TRUE = new Boolean(true); // factory method that uses interning segnames.put(n, n); public static valueOf(boolean value) { return n; if (value) { } return TRUE; } } else {  Java builds this in for strings: String.intern() return FALSE; } } }

Recognition of the problem Structural patterns: Wrappers

 Javadoc for Boolean constructor  A wrapper translates between incompatible interfaces  Allocates a Boolean object representing the value argument  Wrappers are a thin veneer over an encapsulated class  Note: It is rarely appropriate to use this constructor. Unless a new  modify the interface instance is required, the static factory valueOf(boolean) is generally a better choice. It is likely to yield significantly better  extend behavior space and time performance  restrict access

 Josh Bloch (JavaWorld, January 4, 2004)  The encapsulated class does most of the work  The Boolean type should not have had public constructors. Wrapper Functionality Interface There's really no great advantage to allow multiple trues or Pattern multiple falses, and I've seen programs that produce millions of trues and millions of falses, creating needless work for the Adapter same different garbage collector Decorator different same  So, in the case of immutables, I think factory methods are great Proxy same same

2 10/21/2011

Adapter Adapting via subclassing

interface Rectangle { class ScaleableRectangle1 extends NonScaleableRectangle  Change an interface without // grow or shrink by the given factor implements Rectangle { changing functionality void scale(float factor); ... void scale(float factor) {  rename a method float getWidth(); float area(); setWidth(factor * getWidth());  convert units } setHeight(factor * getHeight()); class myClass {  implement a method in } terms of another void myMethod(Rectangle r) { ... r.scale(2); ... } }  Example }  Have the Rectangle class on class NonScaleableRectangle { the top right void setWidth(float width) { ... } void setHeight(float height) { ... }  Want to be able to use the // no scale method NonScaleableRectangle ... class on the bottom right, which } is not a Rectangle

Adapting via delegation: Subclassing vs. delegation Forwarding requests to another object

class ScaleableRectangle2 implements Rectangle {  Subclassing NonScaleableRectangle r; ScaleableRectangle2(NonScaleableRectangle r) {  automatically gives access to all methods of superclass this.r = r;  built into the language (syntax, efficiency) }  Delegation void scale(float factor) {  permits cleaner removal of methods (compile-time checking) setWidth(factor * r.getWidth()); setHeight(factor * r.getHeight());  wrappers can be added and removed dynamically }  objects of arbitrary concrete classes can be wrapped

float getWidth() { return r.getWidth(); }  multiple wrappers can be composed float circumference() { return r.circumference(); }  Some wrappers have qualities of more than one of ... } adapter, decorator, and proxy

Decorator Decorator: Bordered windows

interface Window {  Add functionality without changing the interface // rectangle bounding the window  Add to existing methods to do something additional Rectangle bounds(); (while still preserving the previous specification) // draw this on the specified screen  Not all subclassing is decoration void draw(Screen s); ... }

class WindowImpl implements Window { ... }

3 10/21/2011

Bordered window implementations A decorator can remove functionality class BorderedWindow1 extends WindowImpl { void draw(Screen s) {  Remove functionality without changing the interface super.draw(s); Subclassing  Example: UnmodifiableList bounds().draw(s); }  What does it do about methods like add and put? } class BorderedWindow2 implements Window { Window innerWindow; BorderedWindow2(Window innerWindow) { this.innerWindow = innerWindow; } void draw(Screen s) { Delegation permits innerWindow.draw(s); innerWindow.bounds().draw(s); multiple borders, borders } and/or shading, etc. }

Proxy

 Visitor encodes a class Node {  Same interface and functionality as the wrapped class traversal of a void accept(Visitor v) {  Control access to other objects hierarchical data for each child of node { structure child.accept(v);  communication: manage network details when using a  Nodes – objects in the } remote object hierarchy – accept visitors; visitors visit v.visit(this);  locking: serialize access by multiple clients nodes } }  security: permit access only if proper credentials  n.accept(v) performs a depth-first  creation: object might not yet exist (creation is expensive) traversal of the class Visitor { void visit(Node n) {  hide latency when creating object structure rooted at n, performing v's // perform work on n  avoid work if object is never used operation on each } element of the } structure

Sequence of calls to accept and visit Implementing visitor

a.accept(v)  You must add definitions of visit and accept a b.accept(v)  visit might count nodes, perform typechecking, d.accept(v) v.visit(d) b c etc. e.accept(v)  It is easy to add operations (visitors), hard to add v.visit(e) d e f v.visit(b) nodes (modify each existing visitor) c.accept(v)  Visitors are similar to iterators: each element of the f.accept(v) data structure is presented in turn to the visit v.visit(f) v.visit(c) method v.visit(a)  Visitors have knowledge of the structure, not just the

sequence  Sequence of calls to visit:

4 10/21/2011

Next steps

 Assignment 3: due Sunday October 30, 11:59PM

 Lectures

 M (Patterns III/GUI)  W (Midterm review, including example questions)

 Upcoming: Friday 10/28, in class midterm – open book, open note, closed neighbor, closed electronic devices

UW CSE331 Autumn 2011 UW CSE331 Autumn 2011

5