Design Patterns II

Preview:

DESCRIPTION

Design Patterns II. Behavioral Pattern Visitor: intent and structure. Represent an operation to be performed on the elements of an object structure. Visitor: structure. Visitor: participants. Visitor (IChef) - PowerPoint PPT Presentation

Citation preview

Design PatternsII

1

Behavioral PatternVisitor: intent and structure

Represent an operation to be performed on the elements of an object structure.

Represent an operation to be performed on the elements of an object structure.

2

Visitor: structure

3

Visitor: participantsVisitor (IChef)

declares a Visit operation for each class of ConcreteElement in the object structure. The operation's name and signature identifies the class that sends the Visit request to the visitor.

ConcreteVisitor (ChefWong, ChefZung) implements each operation declared by Visitor.

Element (AEater) defines an Accept operation that takes a visitor as an argument.

ConcreteElement (Vegetarian, Carnivore ) implements an Accept operation that takes a visitor as an argument.

ObjectStructure may provide a high-level interface to allow the visitor to visit its elements

4

Visitor: collaborations

5

Visitor: implementation/* Visitor */interface IChef  {   String cookVeggie(Vegetarian h, Integer n);   String cookMeat(Carnivore h, Integer n);}/* Concrete Visitor 1 */class ChefWong implements IChef { public String cookVeggie(Vegetarian h, Integer n) {       return  n + ":" + h.getBroccoli() + ", " + h.getSalt();   }   public String cookMeat(Carnivore h, Integer n) {       return  n + ":" + h.getMeat() + ", " + h.getPepper();   }}/* Concrete Visitor 2 */class ChefZung implements IChef { public String cookVeggie(Vegetarian h, Integer n) {       return  n + ":" + h.getCorn() + ", " + h.getSalt();   }   public String cookMeat(Carnivore h, Integer n) {       return  n + ":" + h.getChicken() + ", " + h.getPepper();   }}

/* Visitor */interface IChef  {   String cookVeggie(Vegetarian h, Integer n);   String cookMeat(Carnivore h, Integer n);}/* Concrete Visitor 1 */class ChefWong implements IChef { public String cookVeggie(Vegetarian h, Integer n) {       return  n + ":" + h.getBroccoli() + ", " + h.getSalt();   }   public String cookMeat(Carnivore h, Integer n) {       return  n + ":" + h.getMeat() + ", " + h.getPepper();   }}/* Concrete Visitor 2 */class ChefZung implements IChef { public String cookVeggie(Vegetarian h, Integer n) {       return  n + ":" + h.getCorn() + ", " + h.getSalt();   }   public String cookMeat(Carnivore h, Integer n) {       return  n + ":" + h.getChicken() + ", " + h.getPepper();   }}

6

Visitor: implementation (cont.)/* Element */abstract class AEater {  String getSalt() { return "salt"; }   String getPepper() { return "pepper"; }    abstract String order(IChef c, Integer n);  }/* Concrete Element 1 */class Vegetarian extends AEater {  String getBroccoli() { return "broccoli"; }    String getCorn() { return "corn"; }  String order(IChef c, Integer n) { return c.cookVeggie(this, n); }}/* Concrete Element 2 */class Carnivore extends AEater {  String getMeat() { return "steak"; }    String getChicken() { return "cornish hen"; }   String order(IChef c, Integer n) { return c.cookMeat(this, n); }}/* Client */AEater John = new Carnivore(); AEater Mary = new Vegetarian();Mary.order(new ChefWong(), 2); John.order(new ChefZung(), 3);

/* Element */abstract class AEater {  String getSalt() { return "salt"; }   String getPepper() { return "pepper"; }    abstract String order(IChef c, Integer n);  }/* Concrete Element 1 */class Vegetarian extends AEater {  String getBroccoli() { return "broccoli"; }    String getCorn() { return "corn"; }  String order(IChef c, Integer n) { return c.cookVeggie(this, n); }}/* Concrete Element 2 */class Carnivore extends AEater {  String getMeat() { return "steak"; }    String getChicken() { return "cornish hen"; }   String order(IChef c, Integer n) { return c.cookMeat(this, n); }}/* Client */AEater John = new Carnivore(); AEater Mary = new Vegetarian();Mary.order(new ChefWong(), 2); John.order(new ChefZung(), 3);

7

Visitor: consequencesConsequences:• Visitor lets you define a new operation without changing the

classes of the elements on which it operates.

• A visitor gathers related operations and separates unrelated ones.

• Adding new ConcreteElement classes is hard.

• Visiting across class hierarchies.

• Accumulating state.

• Breaking encapsulation. 8

Structural PatternDecorator: intent and structure

Decorators provide a flexible alternative to subclassing for extending functionality.

Decorators provide a flexible alternative to subclassing for extending functionality.

9

Decorator: participantsComponent (Window)

defines the interface for objects that can have responsibilities added to them dynamically.

ConcreteComponent (SimpleWindow) defines an object to which additional responsibilities can be attached.

Decorator (WindowDecorator) maintains a reference to a Component object and defines an interface

that conforms to Component's interface.

ConcreteDecorator (ScrollBarDecorator, BorderDecorator) adds responsibilities to the component.

10

Decorator: implementation/* Component */public interface Window { public void draw();}/* Concrete Component */public class SimpleWindow implements Window { public void draw() {…} public String toString() { return "Simple window"; }}/* Decorator */abstract class WindowDecorator implements Window { protected Window w; public WindowDecorator (Window w) { this.w = w; }}/* Concrete Decorator 1 */class ScrollBarDecorator extends WindowDecorator { public ScrollBarDecorator(Window w) { super(w); } public void draw() { drawScrollBar(); w.draw(); } private void drawScrollBar() {…} public String toString() { return w + " including scroll bar"; }}

/* Component */public interface Window { public void draw();}/* Concrete Component */public class SimpleWindow implements Window { public void draw() {…} public String toString() { return "Simple window"; }}/* Decorator */abstract class WindowDecorator implements Window { protected Window w; public WindowDecorator (Window w) { this.w = w; }}/* Concrete Decorator 1 */class ScrollBarDecorator extends WindowDecorator { public ScrollBarDecorator(Window w) { super(w); } public void draw() { drawScrollBar(); w.draw(); } private void drawScrollBar() {…} public String toString() { return w + " including scroll bar"; }}

11

Decorator: implementation (cont.)/* Concrete Decorator 2 */public class BorderDecorator extends WindowDecorator { public BorderDecorator(Window w) { super(w); } public void draw() { drawBorder(); w.draw(); } private void drawBorder() {…} public String getDescription(){ return w + " including border"; }}

/* Client */public class Client { public void run() { Window decoratedWindow = new ScrollBarDecorator(

new BorderDecorator(new SimpleWindow()));

System.out.println(decoratedWindow); }}

/* Concrete Decorator 2 */public class BorderDecorator extends WindowDecorator { public BorderDecorator(Window w) { super(w); } public void draw() { drawBorder(); w.draw(); } private void drawBorder() {…} public String getDescription(){ return w + " including border"; }}

/* Client */public class Client { public void run() { Window decoratedWindow = new ScrollBarDecorator(

new BorderDecorator(new SimpleWindow()));

System.out.println(decoratedWindow); }}

12

Decorator: consequencesConsequences:

• More flexibility than static inheritance.

• Avoids feature-laden classes high up in the hierarchy.

• A decorator and its component aren't identical.

• Lots of little objects.

13

Structural PatternAdapter: intent and structure

Convert the interface of a class into another interface clients expect.

Convert the interface of a class into another interface clients expect.

14

Adapter: participantsTarget (Stack)

defines the domain-specific interface that Client uses.

Client collaborates with objects conforming to the Target interface.

Adaptee (DList) defines an existing interface that needs adapting.

Adapter (DListImpStack) adapts the interface of Adaptee to the Target interface.

15

Class Adapter: implementation/* Target */interface Stack<T> { void push (T o); T pop (); T top ();}

/* Adaptee */public class DList<T> { public void insertHead (T o) {…} public void insertTail (T o) {…} public T removeHead () {…} public T removeTail () {…} public T getHead () {…} public T getTail () {…}}

/* Adapter */public class DListImpStack<T> extends DList<T> implements Stack<T> { public void push (T o) { insertTail (o); } public T pop () { return removeTail (); } public T top () { return getTail (); } }

/* Target */interface Stack<T> { void push (T o); T pop (); T top ();}

/* Adaptee */public class DList<T> { public void insertHead (T o) {…} public void insertTail (T o) {…} public T removeHead () {…} public T removeTail () {…} public T getHead () {…} public T getTail () {…}}

/* Adapter */public class DListImpStack<T> extends DList<T> implements Stack<T> { public void push (T o) { insertTail (o); } public T pop () { return removeTail (); } public T top () { return getTail (); } }

16

Adapter: consequencesConsequences:

• A class adapter• a class adapter won't work when we want to adapt a class

and all its subclasses.• lets Adapter override some of Adaptee's behavior• no additional pointer indirection is needed to get to the

adaptee.

• An object adapter• lets a single Adapter work with many Adaptees• makes it harder to override Adaptee behavior.

17

Behavioral PatternCommand: intent and structure

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.

18

Command: participantsCommand (Command)

declares an interface for executing an operation.

ConcreteCommand (MoveUpCommand, MoveRightCommand) defines a binding between a Receiver object and an action. implements Execute by invoking the corresponding operation(s) on Receiver.

Client (Game) creates a ConcreteCommand object and sets its receiver.

Invoker (Game) asks the command to carry out the request.

Receiver (GameBoard) knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.

19

Command: implementation/* Receiver */public class GameBoard { public int x = 0; public int y = 0; public static final int XMAX = 10; public static final int YMAX = 10; public void incX() { if (x < GameBoard.XMAX) ++x; } public void decX() { if (x > 0) --x; } public void incY() { if (y < GameBoard.YMAX) ++y; } public void decY() { if (y > 0) --y; }}

/* Command */public interface Command { void execute(); void undo();}

/* Concrete Command 1 */public class MoveUpCommand implements Command { private GameBoard gb; public MoveUpCommand(GameBoard gb) { this.gb = gb; } public void execute() { gb.incY(); } public void undo() { gb.decY(); }}

/* Receiver */public class GameBoard { public int x = 0; public int y = 0; public static final int XMAX = 10; public static final int YMAX = 10; public void incX() { if (x < GameBoard.XMAX) ++x; } public void decX() { if (x > 0) --x; } public void incY() { if (y < GameBoard.YMAX) ++y; } public void decY() { if (y > 0) --y; }}

/* Command */public interface Command { void execute(); void undo();}

/* Concrete Command 1 */public class MoveUpCommand implements Command { private GameBoard gb; public MoveUpCommand(GameBoard gb) { this.gb = gb; } public void execute() { gb.incY(); } public void undo() { gb.decY(); }}

20

Command: implementation (cont.)/* Concrete Command 2 */public class MoveRightCommand implements Command { private GameBoard gb; public MoveRightCommand (GameBoard gb) { this.gb = gb; } public void execute() { gb.incX(); } public void undo() { gb.decX();}}

/* Invoker */public class Game { private GameBoard gb = new GameBoard(); private Command moveUpCommand; private Command moveLeftCommand; public Game() { moveUpCommand = new MoveUpCommand(gb); moveLeftCommand = new MoveRightCommand(gb); } public void action() { moveUpCommand.execute(); moveLeftCommand.execute(); }}

/* Concrete Command 2 */public class MoveRightCommand implements Command { private GameBoard gb; public MoveRightCommand (GameBoard gb) { this.gb = gb; } public void execute() { gb.incX(); } public void undo() { gb.decX();}}

/* Invoker */public class Game { private GameBoard gb = new GameBoard(); private Command moveUpCommand; private Command moveLeftCommand; public Game() { moveUpCommand = new MoveUpCommand(gb); moveLeftCommand = new MoveRightCommand(gb); } public void action() { moveUpCommand.execute(); moveLeftCommand.execute(); }}

21

Command: consequencesConsequences:

• Command decouples the object that invokes the operation from the one that knows how to perform it.

• Commands are first-class objects. They can be manipulated and extended like any other object.

• You can assemble commands into a composite command.

• It's easy to add new Commands, because you don't have to change existing classes.

22

Behavioral PatternObserver: intent and structure

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.

23

Observer: participantsSubject

knows its observers. Any number of Observer objects may observe a subject.

provides an interface for attaching and detaching Observer objects.

ConcreteSubject (PowerVector) stores state of interest to ConcreteObserver objects. sends a notification to its observers when its state changes.

Observer (IObserver) defines an updating interface for objects that should be notified of changes in a subject.

ConcreteObserver (SizeKeeper) maintains a reference to a ConcreteSubject object. stores state that should stay consistent with the subject's. implements the Observer updating interface to keep its state consistent

with the subject's.

24

Observer: implementation/* Concrete Subject */public class PowerVector { private ArrayList<Object> items = new ArrayList<Object>(); private ArrayList<IObserver> observers =

new ArrayList<IObserver>(); public int size() { return items.size(); } public void addObserver(IObserver ob) { observers.add(ob); } public void add(Object o) { items.add(o); notifyObservers(); } public void remove(Object o) { items.remove(o); notifyObservers(); } public void notifyObservers() { for (IObserver ob: observers) ob.update(this); }}

/* Concrete Subject */public class PowerVector { private ArrayList<Object> items = new ArrayList<Object>(); private ArrayList<IObserver> observers =

new ArrayList<IObserver>(); public int size() { return items.size(); } public void addObserver(IObserver ob) { observers.add(ob); } public void add(Object o) { items.add(o); notifyObservers(); } public void remove(Object o) { items.remove(o); notifyObservers(); } public void notifyObservers() { for (IObserver ob: observers) ob.update(this); }}

25

Observer: implementation (cont.)/* Observer */public interface IObserver { public void update(PowerVector subject);}/* Concrete Observer */public class SizeKeeper implements IObserver { private int size; public void update(PowerVector subject) { size = subject.size(); } public int size() { return size; }}/* Client */public class Client { private PowerVector v = new PowerVector(); public void run(){ v.addObserver(new SizeKeeper()); v.add(1); v.add(2); System.out.println(v.size()); }}

/* Observer */public interface IObserver { public void update(PowerVector subject);}/* Concrete Observer */public class SizeKeeper implements IObserver { private int size; public void update(PowerVector subject) { size = subject.size(); } public int size() { return size; }}/* Client */public class Client { private PowerVector v = new PowerVector(); public void run(){ v.addObserver(new SizeKeeper()); v.add(1); v.add(2); System.out.println(v.size()); }}

26

Observer: consequencesConsequences:

• Abstract coupling between Subject and Observer.

• Support for broadcast communication.

• Unexpected updates.

27

Behavioral PatternChain-of-Responsibility: intent and structure

Chain the receiving objects and pass the request along the chain until an object handles it.

Chain the receiving objects and pass the request along the chain until an object handles it.

28

Chain-of-Responsibility: participantsHandler (Filter)

defines an interface for handling requests. (optional) implements the successor link.

ConcreteHandler (EvenFilter, PrimeFilter) handles requests it is responsible for. can access its successor. if the ConcreteHandler can handle the request, it does so; otherwise it

forwards the request to its successor.

Client (Client) initiates the request to a ConcreteHandler object on the chain.

29

Chain-of-Responsibility: implementation/* Handler */public class Filter { private Filter next = null; public void attach(Filter other) { other.next = this.next; this.next = other; } public final void invoke(int v) { if (this.handle(v)) return; if (next != null) next.invoke(v); } public boolean handle(int v) { return false;}}/* Concrete Handler 1 */public class EvenFilter extends Filter { public boolean handle(int v) { return (v % 2 == 0);}}/* Concrete Handler 2 */public class PrimeFilter extends Filter { public boolean handle(int v) { for (int i = 2; i * i <= v; ++i) if (v % i == 0) return false; return true; }}

/* Handler */public class Filter { private Filter next = null; public void attach(Filter other) { other.next = this.next; this.next = other; } public final void invoke(int v) { if (this.handle(v)) return; if (next != null) next.invoke(v); } public boolean handle(int v) { return false;}}/* Concrete Handler 1 */public class EvenFilter extends Filter { public boolean handle(int v) { return (v % 2 == 0);}}/* Concrete Handler 2 */public class PrimeFilter extends Filter { public boolean handle(int v) { for (int i = 2; i * i <= v; ++i) if (v % i == 0) return false; return true; }}

30

Chain-of-Responsibility: implementation (cont.)

/* Client */public class Client { private ArrayList<Integer> l = new ArrayList<Integer>(); private Filter chain = new Filter();

public Client() { chain.attach(new Filter() {

public boolean handle(int v) { l.add(v); return true;}

}); chain.attach(new EvenFilter()); chain.attach(new PrimeFilter()); } public void run() { for (int i = 0; i < 10; ++i)

chain.invoke(i); System.out.println("Size = " + l.size()); }}

/* Client */public class Client { private ArrayList<Integer> l = new ArrayList<Integer>(); private Filter chain = new Filter();

public Client() { chain.attach(new Filter() {

public boolean handle(int v) { l.add(v); return true;}

}); chain.attach(new EvenFilter()); chain.attach(new PrimeFilter()); } public void run() { for (int i = 0; i < 10; ++i)

chain.invoke(i); System.out.println("Size = " + l.size()); }}

31

Chain-of-Responsibility: consequencesConsequences:

• Reduced coupling.

• Added flexibility in assigning responsibilities to objects.

• Receipt isn't guaranteed.

32

Recommended