Download presentation
Presentation is loading. Please wait.
1
Design Patterns II 1
2
Behavioral Pattern Visitor: intent and structure Represent an operation to be performed on the elements of an object structure. 2
3
Visitor: structure 3
4
Visitor: participants Visitor (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
5
Visitor: collaborations 5
6
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
7
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
8
Visitor: consequences Consequences: 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
9
Structural Pattern Decorator: intent and structure Decorators provide a flexible alternative to subclassing for extending functionality. 9
10
Decorator: participants Component (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
11
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
12
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
13
Decorator: consequences Consequences: 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
14
Structural Pattern Adapter: intent and structure Convert the interface of a class into another interface clients expect. 14
15
Adapter: participants Target (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
16
Class Adapter: implementation /* Target */ interface Stack { void push (T o); T pop (); T top (); } /* Adaptee */ public class DList { 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 extends DList implements Stack { public void push (T o) { insertTail (o); } public T pop () { return removeTail (); } public T top () { return getTail (); } } /* Target */ interface Stack { void push (T o); T pop (); T top (); } /* Adaptee */ public class DList { 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 extends DList implements Stack { public void push (T o) { insertTail (o); } public T pop () { return removeTail (); } public T top () { return getTail (); } } 16
17
Adapter: consequences Consequences: 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
18
Behavioral Pattern Command: 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. 18
19
Command: participants Command (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
20
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
21
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
22
Command: consequences Consequences: 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
23
Behavioral Pattern Observer: 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. 23
24
Observer: participants Subject 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
25
Observer: implementation /* Concrete Subject */ public class PowerVector { private ArrayList items = new ArrayList (); private ArrayList observers = new ArrayList (); 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 items = new ArrayList (); private ArrayList observers = new ArrayList (); 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
26
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
27
Observer: consequences Consequences: Abstract coupling between Subject and Observer. Support for broadcast communication. Unexpected updates. 27
28
Behavioral Pattern Chain-of-Responsibility: intent and structure Chain the receiving objects and pass the request along the chain until an object handles it. 28
29
Chain-of-Responsibility: participants Handler (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
30
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
31
Chain-of-Responsibility: implementation (cont.) /* Client */ public class Client { private ArrayList l = new ArrayList (); 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 l = new ArrayList (); 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
32
Chain-of-Responsibility: consequences Consequences: Reduced coupling. Added flexibility in assigning responsibilities to objects. Receipt isn't guaranteed. 32
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.