Download presentation
Presentation is loading. Please wait.
1
1 Pattern Games CS 236700: Software Design Winter 2004-2005/T9
2
2 Overview 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
3 Participating 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
4 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
5 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
6 1 st 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
7 Command: intent Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
8
8 SizeKeeper 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
9 ICommand, 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
10 PowerVector 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
11 Client 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
12 2 nd 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
13 Observer: intent Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
14
14 IObserver, 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
15 PowerVector 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
16 Client 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
17 3 rd 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
18 Chain-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.
19
19 RequestHandler 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
20 EvenFilter, 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
21 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 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
22 Client 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
23 Summary 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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.