poosd-02.ppt

Download Report

Transcript poosd-02.ppt

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, canonical
classes, 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 {
letter impl;
public envelope() {
impl = new letter();
}
envelope
public void message() {
impl.message();
}
};
public class letter {
public letter() { }
public void message() {
System.out.println("Message in a letter");
}
letter
public class factory {
public factory() { }
factory
letter letter() { return new letter(); }
envelope envelope() { return new envelope(); }
};
public class envelope {
letter impl;
public envelope() {
factory f = new factory();
impl = f.letter(); // obtained from factory
}
public void message() {
impl.message();
}
};
envelope
public class singleton extends letter {
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;
};
singleton
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
class shape { ... };
class circle : public shape { ... }
shape* s = new circle;
shape
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 ) {
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;
}
sqrt
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 {
...
void bind( handler h );
void bind( string action, handler h );
...
};
widget
event
interface event : handler {
operator();
};
event
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 {
public item(String x) { _name = x; _self = null; }
item
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 {
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) { }
};
actor
class student extends actor {
student
public void talk() { System.out.println("OOP"); }
public void think() { System.out.println("Z"); }
};
class employer extends actor {
public void talk() { System.out.println("money"); }
public void act() { System.out.println("business"); }
};
employer
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 {
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();
p.become(new adult()); p.talk();
p.become(actor.Student); p.talk();
p.become(p); p.talk();
p.become(actor.Person); p.talk();
}
};
example
money
interesting
OOP
old role: employer
// initial state
The art of hush programming
Invocation Context
Problem
Inheritance breaks with
handle/body
Background
Envelope/Letter, hiding
implementations
Realization
Explicit invocation contact in body
Usage
sessions, events, kits, widgets,
items
handle/body
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
design for change
• 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
• 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
object and class composition
Pattern
Composite
Flyweight
Adaptor
Bridge
Decorator
Facade
Proxy
Alias
Remarks
part/whole
collections of components
part/whole*
extrinsic state, many objects
wrapper
resolves inconsistencies
handle/body abstraction to implementation
wrapper
to introduce functionality
wrapper*
provides unified interface
surrogate
to defer ... remote, virtual,
protection
Behavioral Patterns
cooperation
algorithms and the assignment of responsibilities between objects
class
Template Method -- the skeleton of an algorithm
Interpreter -- to evaluate expressions
object
Mediator -- provides indirection
Chain of Responsibility -- connect objects to interact
Observer -- to handle dependencies
composition
Encapsulating behavior
objectify!
•
•
•
•
•
Command -- action + undo
Strategy -- choice of algorithms
Visitor -- decouple traversal and operations
Iterator -- access and traversal
State -- object state -> behavioral change
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 Communication
Software, 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 {
protected thermometer( float v ) { temp = v; }
public void set(float v) { temp = v; }
public float get() { return temp; }
protected float temp;
};
thermometer
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 {
public fahrenheit() { super(0); }
public void set(float v) { temp = (v - 32) * 5/9 + 273; }
public float get() { return temp * 9/5 + 32 - 273; }
};
fahrenheit
class displayer extends window {
displayer
public displayer() { ... }
public void put(String s) { ... }
public void put(float f) { ... }
};
class prompter extends window {
public prompter(String text) { ... }
public float get() { ... }
public String gets() { ... }
};
prompter
abstract class event {
pubic void dependent(event e) { ... }
pubic void process() { ... }
public void operator(); // abstract method
private event[] dep;
};
event
class update extends event {
public update(thermometer th, prompter p) {
_th =th; _p = p;
}
void operator()() {
_th.set( _p.get() );
process();
}
thermometer _th;
prompter _p;
};
update
class show extends event {
public show(thermometer th, displayer d) {
_th = th; _d = d;
}
public void operator() {
_d.put( _th.get() );
process();
}
thermometer _th;
displayer _d;
};
show
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
1
Polymorphism
•
•
•
•
inheritance and delegation in Java
polymorphism in C++
assertions in C++
canonical class idioms
2
Idioms in hush
•
•
•
•
the handle/body idiom
virtual self-reference
dynamic role switching
the art of hush programming
3
A catalogue of design patterns
• creational patterns
• structural patterns
• behavioral patterns
4
Event-driven computation
• the Reactor pattern
• abstract event systems
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 selfreference, 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].