Pattern Games

23
1 Pattern Games Pattern Games CS 236700: Software Design Winter 2004-2005/T9

description

Pattern Games. CS 236700: Software Design Winter 2004-2005/T9. 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 - PowerPoint PPT Presentation

Transcript of Pattern Games

Page 1: Pattern Games

1

Pattern GamesPattern Games

CS 236700: Software Design

Winter 2004-2005/T9

Page 2: Pattern Games

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

Page 3: Pattern Games

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, …

Page 4: Pattern Games

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); }}

Page 5: Pattern Games

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(); }}

Page 6: Pattern Games

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

Page 7: Pattern Games

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.

Page 8: Pattern Games

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_; }}

Page 9: Pattern Games

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_); } }

Page 10: Pattern Games

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 }}

Page 11: Pattern Games

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}

Page 12: Pattern Games

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

Page 13: Pattern Games

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.

Page 14: Pattern Games

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_; } }

Page 15: Pattern Games

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 }

Page 16: Pattern Games

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}

Page 17: Pattern Games

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

Page 18: Pattern Games

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.

Page 19: Pattern Games

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; } }

Page 20: Pattern Games

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; }}

Page 21: Pattern Games

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

Page 22: Pattern Games

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()); }

Page 23: Pattern Games

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