1 / 32

Design Patterns II

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)

trung
Télécharger la présentation

Design Patterns II

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Design PatternsII

  2. Behavioral PatternVisitor: intent and structure Represent an operation to be performed on the elements of an object structure.

  3. Visitor: structure

  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

  5. Visitor: collaborations

  6. Visitor: implementation /* Visitor */ interfaceIChef  {   String cookVeggie(Vegetarian h, Integer n);   String cookMeat(Carnivore h, Integer n);} /* Concrete Visitor 1 */ classChefWongimplementsIChef { publicString cookVeggie(Vegetarian h, Integer n) {return  n + ":" + h.getBroccoli() + ", " + h.getSalt();   }publicString cookMeat(Carnivore h, Integer n) {return  n + ":" + h.getMeat() + ", " + h.getPepper();   }} /* Concrete Visitor 2 */ classChefZungimplementsIChef { publicString cookVeggie(Vegetarian h, Integer n) {return  n + ":" + h.getCorn() + ", " + h.getSalt();   }publicString cookMeat(Carnivore h, Integer n) {return  n + ":" + h.getChicken() + ", " + h.getPepper();   }}

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

  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.

  9. Structural PatternDecorator: intent and structure Decorators provide a flexible alternative to subclassing for extending functionality.

  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.

  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 classWindowDecoratorimplements Window { protected Window w; publicWindowDecorator (Window w) { this.w = w; } } /* Concrete Decorator 1 */ classScrollBarDecoratorextendsWindowDecorator { publicScrollBarDecorator(Window w) { super(w); } public void draw() { drawScrollBar(); w.draw(); } private voiddrawScrollBar() {…} public String toString() { return w + " including scroll bar"; } }

  12. Decorator: implementation (cont.) /* Concrete Decorator 2 */ public classBorderDecoratorextendsWindowDecorator { publicBorderDecorator(Window w) { super(w); } publicvoid draw() { drawBorder(); w.draw(); } private voiddrawBorder() {…} public String getDescription(){ return w + " including border"; } } /* Client */ public class Client { public void run() { Window decoratedWindow = newScrollBarDecorator( newBorderDecorator( newSimpleWindow())); System.out.println(decoratedWindow); } }

  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.

  14. Structural PatternAdapter: intent and structure Convert the interface of a class into another interface clients expect.

  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.

  16. Class Adapter: implementation /* Target */ interfaceStack<T> { voidpush (T o); T pop (); T top (); } /* Adaptee */ public classDList<T> { public voidinsertHead (T o) {…} public voidinsertTail (T o) {…} public T removeHead () {…} publicT removeTail () {…} public T getHead () {…} public T getTail(){…} } /* Adapter */ public classDListImpStack<T> extendsDList<T> implements Stack<T> { public void push (T o) { insertTail(o); } public T pop () { returnremoveTail (); } public T top () { returngetTail (); } }

  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.

  18. 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.

  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.

  20. Command: implementation /* Receiver */ public class GameBoard { public int x = 0; publicint y = 0; publicstaticfinalint XMAX = 10; publicstaticfinalint 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 GameBoardgb; public MoveUpCommand(GameBoardgb) { this.gb = gb; } public void execute() { gb.incY(); } public void undo() { gb.decY(); } }

  21. Command: implementation (cont.) /* Concrete Command 2 */ public class MoveRightCommandimplements Command { private GameBoardgb; public MoveRightCommand(GameBoardgb) { this.gb = gb; } public void execute() { gb.incX(); } public void undo() { gb.decX();} } /* Invoker */ public class Game { privateGameBoardgb = newGameBoard(); private Command moveUpCommand; private Command moveLeftCommand; public Game() { moveUpCommand = newMoveUpCommand(gb); moveLeftCommand = newMoveRightCommand(gb); } public void action() { moveUpCommand.execute(); moveLeftCommand.execute(); } }

  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.

  23. 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.

  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.

  25. Observer: implementation /* Concrete Subject */ public class PowerVector { privateArrayList<Object> items = newArrayList<Object>(); privateArrayList<IObserver> observers = newArrayList<IObserver>(); public intsize() { return items.size(); } public voidaddObserver(IObserver ob) { observers.add(ob); } public void add(Object o) { items.add(o); notifyObservers(); } public void remove(Object o) { items.remove(o); notifyObservers(); } public voidnotifyObservers() { for (IObserver ob: observers) ob.update(this); } }

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

  27. Observer: consequences • Consequences: • Abstract coupling between Subject and Observer. • Support for broadcast communication. • Unexpected updates.

  28. Behavioral PatternChain-of-Responsibility: intent and structure Chain the receiving objects and pass the request along the chain until an object handles it.

  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.

  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(intv) { 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(intv) { return (v % 2 == 0);} } /* Concrete Handler 2 */ public class PrimeFilter extends Filter { public boolean handle(intv) { for (int i = 2; i * i <= v; ++i) if (v % i == 0) return false; return true; } }

  31. 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(intv) { 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()); } }

  32. Chain-of-Responsibility: consequences • Consequences: • Reduced coupling. • Added flexibility in assigning responsibilities to objects. • Receipt isn't guaranteed.

More Related