1 pattern games cs 236700: software design winter 2004-2005/t9
Post on 20-Dec-2015
216 views
TRANSCRIPT
1
Pattern GamesPattern Games
CS 236700: Software Design
Winter 2004-2005/T9
2
Overview of the programsOverview of the programs
Three similar programs Each one is actually a single collaboration The main goal: manage a Vector of integer values The programs are similar but not identical The differences are in specific details of the required behavior
We will use Design Patterns to address the various needs: Command Observer Chain-of-Responsibility
3
Participating classesParticipating classes
Client – the “application”. Has a constructor and a run() method Role: Client
PowerVector – Maintains a list of Objects Role: Invoker, Concrete Subject, Concrete Handler
SizeKeeper – Notified when an add/remove request happens Allows the client to obtain the size of the PowerVector object Role: Receiver, Concrete Observer
Additional classes in each program SizeCommand, IObserver, …
4
Skeleton of class PowerVector Skeleton of class PowerVector
public class PowerVector { private Vector items_ = new Vector(); public PowerVector(...) { ... }
public Object get(int index) { return items_.get(index); } public void add(Object o) { items_.add(o); } public void remove() { items_.remove(items_.size() - 1); }}
public class PowerVector { private Vector items_ = new Vector(); public PowerVector(...) { ... }
public Object get(int index) { return items_.get(index); } public void add(Object o) { items_.add(o); } public void remove() { items_.remove(items_.size() - 1); }}
5
Skeleton of class Client Skeleton of class Client
public class Client { private PowerVector vec_; public Client() { ... }
public void run() { // add 25 integers to vec_ (how?) // print size (how?) for(int i = 0; i < 3; ++i) vec_.remove(); // print size (how?) } public static void main(String[] args) { Client c = new Client(); c.run(); }}
public class Client { private PowerVector vec_; public Client() { ... }
public void run() { // add 25 integers to vec_ (how?) // print size (how?) for(int i = 0; i < 3; ++i) vec_.remove(); // print size (how?) } public static void main(String[] args) { Client c = new Client(); c.run(); }}
6
11stst program program
In this program, class PowerVector has no getSize() method
A SizeKeeper object will monitor the size of the vector
We will use the Command pattern to notify the SizeKeeper object of add/remove operations
7
Command: intentCommand: intent
Encapsulate a request as an object, thereby letting you
parameterize clients with different requests, queue or log requests,
and support undoable operations.
Encapsulate a request as an object, thereby letting you
parameterize clients with different requests, queue or log requests,
and support undoable operations.
8
SizeKeeperSizeKeeper
public class SizeKeeper { private int size_ = 0; public void incSize(int diff) { size_ += diff; } public int getSize() { return size_; }}
public class SizeKeeper { private int size_ = 0; public void incSize(int diff) { size_ += diff; } public int getSize() { return size_; }}
9
ICommand, SizeCommandICommand, SizeCommand
public interface ICommand { public void execute();}
public class SizeCommand implements ICommand { private int diff_; private SizeKeeper keeper_; public SizeCommand(SizeKeeper keeper, int diff) { diff_ = diff; keeper_ = keeper; } public void execute() { keeper_.incSize(diff_); } }
public interface ICommand { public void execute();}
public class SizeCommand implements ICommand { private int diff_; private SizeKeeper keeper_; public SizeCommand(SizeKeeper keeper, int diff) { diff_ = diff; keeper_ = keeper; } public void execute() { keeper_.incSize(diff_); } }
10
PowerVectorPowerVector
public class PowerVector { private Vector items_ = new Vector(); private ICommand on_add_; private ICommand on_remove_; public PowerVector(ICommand on_add, ICommand on_remove) { on_add_ = on_add; on_remove_ = on_remove; } public void add(Object o) { items_.add(o); on_add_.execute(); // add notification } public void remove() { items_.remove(items_.size() - 1); on_remove_.execute(); // remove notification }}
public class PowerVector { private Vector items_ = new Vector(); private ICommand on_add_; private ICommand on_remove_; public PowerVector(ICommand on_add, ICommand on_remove) { on_add_ = on_add; on_remove_ = on_remove; } public void add(Object o) { items_.add(o); on_add_.execute(); // add notification } public void remove() { items_.remove(items_.size() - 1); on_remove_.execute(); // remove notification }}
11
ClientClient
public class Client { private PowerVector vec_; private SizeKeeper keeper_ = new SizeKeeper(); public Client() { ICommand onInc = new SizeCommand(keeper_, 1); ICommand onDec = new SizeCommand(keeper_, -1); vec_ = new PowerVector(onInc, onDec); } public void run() { for(int i = 0; i < 25; ++i) vec_.add(new Integer(i)); System.out.println("Size=" + keeper_.getSize()); for(int i = 0; i < 3; ++i) vec_.remove(); System.out.println("Size=" + keeper_.getSize()); } // main() omitted}
public class Client { private PowerVector vec_; private SizeKeeper keeper_ = new SizeKeeper(); public Client() { ICommand onInc = new SizeCommand(keeper_, 1); ICommand onDec = new SizeCommand(keeper_, -1); vec_ = new PowerVector(onInc, onDec); } public void run() { for(int i = 0; i < 25; ++i) vec_.add(new Integer(i)); System.out.println("Size=" + keeper_.getSize()); for(int i = 0; i < 3; ++i) vec_.remove(); System.out.println("Size=" + keeper_.getSize()); } // main() omitted}
12
22ndnd program program
Now, class PowerVector provides a getSize() method SizeKeeper will use this method => Tight-coupling between SizeKeepr and PowerVector
SizeKeeper is an observer of PowerVector
13
Observer: intentObserver: intent
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are
notified and updated automatically.
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are
notified and updated automatically.
14
IObserver, SizeKeeperIObserver, SizeKeeper
public interface IObserver{ public void update(PowerVector subject);}
public class SizeKeeper implements IObserver { private int size_; public SizeKeeper() { } public void update(PowerVector subject) { size_ = subject.getSize(); } public int getSize() { return size_; } }
public interface IObserver{ public void update(PowerVector subject);}
public class SizeKeeper implements IObserver { private int size_; public SizeKeeper() { } public void update(PowerVector subject) { size_ = subject.getSize(); } public int getSize() { return size_; } }
15
PowerVectorPowerVector
public class PowerVector{ private Vector items_ = new Vector(); private LinkedList observers_ = new LinkedList(); public PowerVector() { }
public int getSize() { return items_.size(); }
public void addObserver(IObserver o) { observers_.add(o); }
public void add(Object o) { items_.add(o); for(Iterator i = observers_.iterator(); i.hasNext(); ) ((IObserver) i.next()).update(this); }
// remove() is similarly implemented }
public class PowerVector{ private Vector items_ = new Vector(); private LinkedList observers_ = new LinkedList(); public PowerVector() { }
public int getSize() { return items_.size(); }
public void addObserver(IObserver o) { observers_.add(o); }
public void add(Object o) { items_.add(o); for(Iterator i = observers_.iterator(); i.hasNext(); ) ((IObserver) i.next()).update(this); }
// remove() is similarly implemented }
16
ClientClient
public class Client { private PowerVector vec_ = new PowerVector(); private SizeKeeper keeper_ = new SizeKeeper(); public Client() { vec_.addObserver(keeper_); } public void run() { for(int i = 0; i < 25; ++i) vec_.add(new Integer(i)); System.out.println("Size=" + keeper_.getSize()); for(int i = 0; i < 3; ++i) vec_.remove(); System.out.println("Size=" + keeper_.getSize()); }
// main() omitted}
public class Client { private PowerVector vec_ = new PowerVector(); private SizeKeeper keeper_ = new SizeKeeper(); public Client() { vec_.addObserver(keeper_); } public void run() { for(int i = 0; i < 25; ++i) vec_.add(new Integer(i)); System.out.println("Size=" + keeper_.getSize()); for(int i = 0; i < 3; ++i) vec_.remove(); System.out.println("Size=" + keeper_.getSize()); }
// main() omitted}
17
33rdrd program program
At this stage, we would like to control the values added to the PowerVector object
The Chain-Of-Responsibility allows screening of requests
Client class will invoke an “add element” request The request will propagate through a chain of request
handlers The last handler is the PowerVector object itself
18
Chain-of-Reponsibility: intentChain-of-Reponsibility: intent
Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an
object handles it.
Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an
object handles it.
19
RequestHandlerRequestHandler
public class RequestHandler {
private RequestHandler next_ = null; public void attach(RequestHandler other) { other.next_ = this.next_; this.next_ = other; } public final void invoke(Integer val) { if(this.handle(val)) return; if(next_ != null) next_.invoke(val); } public boolean handle(Integer val) { return false; } }
public class RequestHandler {
private RequestHandler next_ = null; public void attach(RequestHandler other) { other.next_ = this.next_; this.next_ = other; } public final void invoke(Integer val) { if(this.handle(val)) return; if(next_ != null) next_.invoke(val); } public boolean handle(Integer val) { return false; } }
20
EvenFilter, PrimeFilterEvenFilter, PrimeFilter
public class EvenFilter extends RequestHandler { public boolean handle(Integer val) { return (val.intValue() % 2 == 0); }}
public class PrimeFilter extends RequestHandler { public boolean handle(Integer val) { int n = val.intValue(); for(int i = 2; i * i <= n; ++i) { if(n % i == 0) return false; } return true; }}
public class EvenFilter extends RequestHandler { public boolean handle(Integer val) { return (val.intValue() % 2 == 0); }}
public class PrimeFilter extends RequestHandler { public boolean handle(Integer val) { int n = val.intValue(); for(int i = 2; i * i <= n; ++i) { if(n % i == 0) return false; } return true; }}
21
PowerVectorPowerVector
public class PowerVector { private Vector items_ = new Vector(); public PowerVector() { }
public Object get(int index) { return items_.get(index); } public void add(Object o) { items_.add(o); } public void remove() { items_.remove(items_.size() - 1); } public int getSize() { return items_.size(); } }
public class PowerVector { private Vector items_ = new Vector(); public PowerVector() { }
public Object get(int index) { return items_.get(index); } public void add(Object o) { items_.add(o); } public void remove() { items_.remove(items_.size() - 1); } public int getSize() { return items_.size(); } }
High degree of coherency in PowerVector
Is not concerned with notification issues
22
ClientClient
public class Client { private PowerVector vec_ = new PowerVector(); private RequestHandler chain_ = new RequestHandler(); public Client() {
chain_.attach(new RequestHandler() { public boolean handle(Integer val) { vec_.add(val); return true; } }); chain_.attach(new EvenFilter()); chain_.attach(new PrimeFilter()); } public void run() { for(int i = 0; i < 25; ++i) chain_.invoke(new Integer(i)); System.out.println("Size=" + vec_.getSize()); for(int i = 0; i < 3; ++i) vec_.remove(); System.out.println("Size=" + vec_.getSize()); }
public class Client { private PowerVector vec_ = new PowerVector(); private RequestHandler chain_ = new RequestHandler(); public Client() {
chain_.attach(new RequestHandler() { public boolean handle(Integer val) { vec_.add(val); return true; } }); chain_.attach(new EvenFilter()); chain_.attach(new PrimeFilter()); } public void run() { for(int i = 0; i < 25; ++i) chain_.invoke(new Integer(i)); System.out.println("Size=" + vec_.getSize()); for(int i = 0; i < 3; ++i) vec_.remove(); System.out.println("Size=" + vec_.getSize()); }
23
SummarySummary The three patterns allow modeling of different situations
Obviously, they can be used together to get a combined effect
Command: An invoker does not know who is the actual receiver An invoker does not know which method should be called
Observer: Several observers are all interested in a single object
Chain-of-Responsibility Several handlers are all interested in a single request
The chain represents a single request A handler does not know who is the actual invoker