Date post: | 19-Dec-2015 |
Category: |
Documents |
View: | 228 times |
Download: | 1 times |
Principles of Object-Oriented Software Development
Idioms and Patterns
Idioms and Patterns
Introduction
Polymorphism Idioms in hush A catalogue of design patterns Event-driven computation
Summary Q/A Literature
Idioms and Patterns
• polymorphism -- inheritance and delegation
• idioms -- realizing concrete types
• patterns -- a catalogue of design patterns
• events -- the reactor pattern
Additional keywords and phrases:generic types, assertions, canonicalclasses, event-driven computation
Polymorphism
Subsections:
Inheritance and delegation in Java Polymorphism in C++ Assertions in C++ Canonical class idioms
Inheritance and delegation in Java
public class envelope { envelope
public envelope() { } public void message() { System.out.println("hello ... "); } };
Envelope/letter pattern Factory
public class envelop { envelope letter impl; public envelope() { impl = new letter(); } public void message() { impl.message(); } }; public class letter { letter public letter() { } public void message() { System.out.println("Message in a letter"); }
public class factory { factory public factory() { } letter letter() { return new letter(); } envelope envelope() { return new envelope(); } }; public class envelope { envelope letter impl; public envelope() { factory f = new factory(); impl = f.letter(); // obtained from factory }public void message() { impl.message(); } };
public class singleton extends letter { singleton static int number = 0; protected singleton() { } static letter instance() { if (number==0) { theletter = new letter(); number = 1; } return theletter; } public void message() { System.out.println("Message in a letter"); } static letter theletter; };
Polymorphism in C++Overloading print extern void print(int); extern void print(float); Generic class -- templates list< T >
template< class T > class list { ... } list<int>* alist;
Polymorphism by inheritance shape class shape { ... }; class circle : public shape { ... } shape* s = new circle;
Standard Template Library
• containters -- to hold objects
• algorithms -- act on containers
• iterators -- to traverse containers
• functions -- as objects
• adaptors -- to transform objects
• allocators -- for memory management
Assertions in C++
double sqrt( double arg ) { sqrt
require ( arg >= 0 ); double r=arg, x=1, eps=0.0001; while( fabs(r - x) > eps ) { r=x; x=r-((r*r-arg)/(2*r)); } promise ( r - arg * arg <= eps ); return r; }
class counter { counter public: counter(int n = 0) : _n(n) { require( n >= 0 ); promise( invariant() ); check initial state } virtual void operator++() { require( true ); empty pre-condition hold(); save the previous state _n += 1; promise( _n == old_n + 1 && invariant() ); } int value() const { return _n; } no side effects virtual bool invariant() { return value() >= 0; } protected: int _n; int old_n; virtual void hold() { old_n = n; } };
class bounded : public counter { bounded
public: bounded(int b = MAXINT) : counter(0), max(b) {} void operator++() { require( value() < max ); to prevent overflow
counter::operator++(); } bool invariant() { return value() <= max && counter::invariant(); } private: int max;};
Canonical class idioms
Canonical class in C++
• default constructor
• copy constructor
• destructor
• assignment
• operators
Abstract data types must be indistinguishable from built-in types
Idioms in hush
Subsections
The handle/body idiom Virtual self-reference Dynamic role switching The art of hush programming
The hush framework
basic concepts
Basic hush classes
• session -- to manage (parts of) the application
• kit -- to provide access to the underlying system and interpreter
• handler -- to bind C++ functionality to events
• event -- stores information concerning user actions or system events
• widget -- to display information on a screen
• item -- represents an element of a widget
kit
interface kit { kit
void eval(string cmd); string result(); void bind(string name, handler h); };
handler
interface handler { handler
int dispatch( event e ); // to dispatch events
int operator(); };
widget
interface widget : handler { widget
... void bind( handler h ); void bind( string action, handler h ); ... };
event
interface event : handler { event
operator(); };
The Handle/Body Idiom
class A { A -- naive
public A() { } public void f1() { System.out.println("A.f1"); f2(); } public void f2() { System.out.println("A.f2"); } };
class A { A
public A() { body = new BodyOfA(this); } protected A(int x) { } public void f1() { body.f1(); } public void f2() { body.f2(); } public void f3() { System.out.println("A.f3"); } private A body; }; Interface: A
class BodyOfA extends A { BodyOfA -- naive
public BodyOfA() { super(911); } public void f1() { System.out.println("A.f1"); f2(); } public void f2() { System.out.println("A.f2"); } }; class C extends A { C
public void f2() { System.out.println("C.f2"); } }; slide: Usage: C
C c = new C; c.f1(); // instantiate
class BodyOfA extends A { BodyOfA
public BodyOfA(A h) { super(911); handle = h; } public void f1() { System.out.println("A.f1"); handle.f2(); } public void f2() { System.out.println("A.f2"); } A handle; reference to invocation context
};
Virtual self-reference
class item { item public item(String x) { _name = x; _self = null; } String name() { return exists()?self().name():_name; } public void redirect(item x) { _self = x; } boolean exists() { return _self != null; } public item self() { return exists()?_self.self():this; } item _self; String _name; };
public class go { public static void main(String[] args) { item a = new item("a"); item b = new item("b"); a.redirect(b); System.out.println(a.name()); indeed, b
}};
Dynamic role-switching
class actor { actor public static final int Person = 0; public static final int Student = 1; public static final int Employer = 2; public static final int Final = 3; public void walk() { if (exists()) self().walk(); } public void talk() { if (exists()) self().talk(); } public void think() { if (exists()) self().think(); } public void act() { if (exists()) self().act(); } public boolean exists() { return false; } public actor self() { return this; } public void become(actor A) { } public void become(int R) { } };
class student extends actor { student
public void talk() { System.out.println("OOP"); } public void think() { System.out.println("Z"); } };
class employer extends actor { employer
public void talk() { System.out.println("money"); } public void act() { System.out.println("business"); } };
class person extends actor { person
public person() { role = new actor[ Final+1 ]; for( int i = Person; i <= Final; i++ ) role[i]=this; become(Person); } public boolean exists() { return role[_role] != this; } public actor self() { if ( role[ Person ] != this ) return role[ Person ].self(); else return role[_role]; }
...
public void become(actor p) { role[ Person ] = p; } public void become(int R) { if (role[ Person ] != this) self().become(R); else { _role = R; if ( role[_role] == this ) { switch(_role) { case Person: break; // nothing changes case Student: role[_role] = new student(); break; case Employer: role[_role] = new employer(); break; case Final: role[_role] = new actor(); break; default: break; // nothing happens }}} } int _role; actor role[]; };
class adult extends person { adult
public void talk() { System.out.println("interesting"); } };
public class go { example public static void main(String[] args) {
person p = new person(); p.talk(); empty
p.become(actor.Student); p.talk(); OOP
p.become(actor.Employer); p.talk(); money
p.become(new adult()); p.talk(); interesting
p.become(actor.Student); p.talk(); OOP
p.become(p); p.talk(); old role: employer
p.become(actor.Person); p.talk(); // initial state } };
The art of hush programming
Invocation Context handle/body
Problem Inheritance breaks with handle/body Background Envelope/Letter, hiding implementations Realization Explicit invocation contact in bodyUsage sessions, events, kits, widgets, items
Nested Components virtual self-reference
Problem Realizing composites with single inheritance Background Decorators, Prototypes Realization Smart delegation Usage Composite widgets, Embedded logic
Actor Pattern dynamic role switching
Problem Static type hiearchies may be too limited Background State transitions, self-reference Realization Dynamic instantiation and delegation Usage Web viewer, kit -- embedded logic
A catalogue of design patterns
Subsections:
Creational Patterns Structural Patterns Behavioral Patterns
A Catalogue of Design Patterns
• a common design vocabulary
• documentation and learning aid
• an adjunct to existing methods
• a target for redesign
The Pattern Schema Name - handle
increases design vocabulary
Problem - when to apply
explains the problem and the conflict
Solution - general arrangement
design, responsibilities, collaborations
Consequences - tradeoffs
to understand the costs and benefits
Causes for Redesign
• creating an object by specifying a class explicitly -- Abstract Factory, Factory Method, Prototype
• dependence on specific operations -- Chain of Responsibilty, Command
• dependence on hardware & software platforms -- Abstract Factory, Bridge
• dependence on object implementation or representation --Abstract Factory, Bridge, Memento, Proxy
design for change
• algorithm dependence -- Iterator, Strategy, Template Method, Visitor
• extending functionality by subclassing -- Bridge, Composite, Decorator, Observer
• tight coupling -- Abstract Factory, Bridge, Chain of Responsibilities, Command, Facade, Mediator, Observer
• inability to alter classes conveniently -- Adaptor, Decorator,
Creational Patterns
Creational Patterns
• Factory -- hide concrete classes
• Factory Method -- virtual constructors
• Prototype -- dynamic creation by cloning
• Singleton -- one instance only
Structural Patterns
Pattern Alias Remarks
Composite part/whole collections of components Flyweight part/whole* extrinsic state, many objects Adaptor wrapper resolves inconsistenciesBridge handle/body abstraction to implementationDecorator wrapper to introduce functionalityFacade wrapper* provides unified interfaceProxy surrogate to defer ... remote, virtual, protection
object and class composition
Behavioral Patterns
cooperation
algorithms and the assignment of responsibilities between objects
class
Template Method -- the skeleton of an algorithm Interpreter -- to evaluate expressions
object composition
Mediator -- provides indirection Chain of Responsibility -- connect objects to interact Observer -- to handle dependencies
Encapsulating behavior
• Command -- action + undo
• Strategy -- choice of algorithms
• Visitor -- decouple traversal and operations
• Iterator -- access and traversal
• State -- object state -> behavioral change
objectify!
The Observer Pattern
Observer
one-to-many dependencies and notification
Consequences
abstract coupling between subject and observer constraint propagation deals with unexpected updates
Event-driven computation
Subsections:
The Reactor Pattern Abstract event systems
The Reactor Pattern
• activate handlers when events occur
• allow events from multiple sources
• in single threaded process
See D.C. Schmidt, Using Design Patterns to Develop Reusable Object-oriented CommunicationSoftware, CACM October '95, 38(10): 65-74
Abstract event systems
th = new centigrade(); th = new fahrenheit(); th.set(f); f = th.get();
For thermometer th, th1; float f;
Abstract system -- thermometers
class thermometer { thermometer
protected thermometer( float v ) { temp = v; } public void set(float v) { temp = v; } public float get() { return temp; } protected float temp; };
class centigrade extends thermometer { centigrade public centigrade() { super(0); } public void set(float v) { temp = v + 273; } public float get() { return temp - 273; } };
class fahrenheit extends thermometer { fahrenheit
public fahrenheit() { super(0); } public void set(float v) { temp = (v - 32) * 5/9 + 273; } public float get() { return temp * 9/5 + 32 - 273; } };
class displayer extends window { displayer
public displayer() { ... } public void put(String s) { ... } public void put(float f) { ... } };
class prompter extends window { prompter
public prompter(String text) { ... } public float get() { ... } public String gets() { ... } };
abstract class event { event
pubic void dependent(event e) { ... } pubic void process() { ... } public void operator(); // abstract method private event[] dep; };
class update extends event { update
public update(thermometer th, prompter p) { _th =th; _p = p; } void operator()() { _th.set( _p.get() ); process(); } thermometer _th; prompter _p; };
class show extends event { show
public show(thermometer th, displayer d) { _th = th; _d = d; } public void operator() { _d.put( _th.get() ); process(); } thermometer _th; displayer _d; };
thermometer c = new centigrade(); thermometer f = new fahrenheit(); displayer cd = new displayer("centigrade"); displayer fd = new displayer("fahrenheit"); prompter cp = new prompter("enter centigrade value"); prompter fp = new prompter("enter fahrenheit value"); show sc = new show(c,cd); show sf = new show(f,fd); update uc = new update(c,cp); update uf = new update(f,fp);
Installing the objects
uc.dependent(sc); uc.dependent(sf); uf.dependent(sc); uf.dependent(sf);
Assigning dependencies
Summary
Polymorphism
• inheritance and delegation in Java
• polymorphism in C++
• assertions in C++
• canonical class idioms
1
Idioms in hush
• the handle/body idiom
• virtual self-reference
• dynamic role switching
• the art of hush programming
2
A catalogue of design patterns
• creational patterns
• structural patterns
• behavioral patterns
3
Event-driven computation
• the Reactor pattern
• abstract event systems
4
Questions
1.How would you explain the letter/envelope idiom? 2.Characterize the notion of polymorphism. Give some examples. 3.What is a canonical class? Characterize its ingredients and give an example. 4.Give a brief description of the handle/body idiom, virtual self-reference, and dynamic role switching. 5.What kinds of patterns can you distinguish? Why do you consider patterns to be of relevance. 6.Give a detailed description of the Factory pattern. And also of the Observer pattern. 7.Describe the Reactor pattern. Why is it useful? 8.Give an example of a system based on event-driven computation.
Further reading
For an introduction to Java, there is ample choice. An excellent online tutorial can be found on http://java.sun.com/docs/books/tutorial As textbooks on C++ I recommend [Lippman91], and for the more advanced reader [Stroustrup98]. For an extensive introduction to STL, read [STL]. [Coplien92] is the original introduction to idioms in C++. The by now classical book for patterns is [GOF94]. Well worth reading are the many articles in the POPL proceedings, [POPL1], [POPL2], [POPL3].