Tuesday, April 01, 2014

Design Patterns - Behavioral

Behavioral

1.       Chain of Responsibility - delegates commands to a chain of processing objects.
interface Chain {

       public abstract void setNext(Chain nextInChain);

       public abstract void process(Number request);
}

class Number {
       private int number;

       public Number(int number) {
              this.number = number;
       }

       public int getNumber() {
              return number;
       }

}

class NegativeProcessor implements Chain {

       private Chain nextInChain;

       public void setNext(Chain c) {
              nextInChain = c;
       }

       public void process(Number request) {
              if (request.getNumber() < 0) {
                     System.out.println("NegativeProcessor : " + request.getNumber());
              } else {
                     nextInChain.process(request);
              }
       }
}

class ZeroProcessor implements Chain {

       private Chain nextInChain;

       public void setNext(Chain c) {
              nextInChain = c;
       }

       public void process(Number request) {
              if (request.getNumber() == 0) {
                     System.out.println("ZeroProcessor : " + request.getNumber());
              } else {
                     nextInChain.process(request);
              }
       }
}

class PositiveProcessor implements Chain {

       private Chain nextInChain;

       public void setNext(Chain c) {
              nextInChain = c;
       }

       public void process(Number request) {
              if (request.getNumber() > 0) {
                     System.out.println("PositiveProcessor : " + request.getNumber());
              } else {
                     nextInChain.process(request);
              }
       }
}

public class ChainOfResponsibilityExample {
       public static void main(String[] args) {
              // configure Chain of Responsibility
              Chain c1 = new NegativeProcessor();
              Chain c2 = new ZeroProcessor();
              Chain c3 = new PositiveProcessor();
              c1.setNext(c2);
              c2.setNext(c3);

              // calling chain of responsibility
              c1.process(new Number(99));
              c1.process(new Number(-30));
              c1.process(new Number(0));
              c1.process(new Number(100));
       }
}

Chain of responsibility (recognizeable by behavioral methods which (indirectly) invokes the same method in another implementation of same abstract/interface type in a queue)

2.       Command - creates objects which encapsulate actions and parameters.
import java.util.ArrayList;
import java.util.List;

interface ConsumerElectronics {
          public abstract void on();

          public abstract void mute();
}

class Television implements ConsumerElectronics {

          public void on() {
                   System.out.println("Television is on!");
          }

          @Override
          public void mute() {
                   System.out.println("Television is muted!");

          }
}

class SoundSystem implements ConsumerElectronics {

          public void on() {
                   System.out.println("Sound system is on!");
          }

          @Override
          public void mute() {
                   System.out.println("Sound system is muted!");

          }
}

interface Command {

          public abstract void execute();

}

class OnCommand implements Command {

          private ConsumerElectronics ce;

          public OnCommand(ConsumerElectronics ce) {
                   this.ce = ce;
          }

          public void execute() {
                   ce.on();
          }
}

class MuteAllCommand implements Command {
          List ceList;

          public MuteAllCommand(List ceList) {
                   this.ceList = ceList;
          }

          @Override
          public void execute() {

                   for (ConsumerElectronics ce : ceList) {
                             ce.mute();
                   }

          }
}

class Button {
          Command c;

          public Button(Command c) {
                   this.c = c;
          }

          public void click() {
                   c.execute();
          }
}

class UniversalRemote {

          public static ConsumerElectronics getActiveDevice() {
                   // here we will have a complex electronic circuit :-)
                   // that will maintain current device
                   Television tv = new Television();
                   return tv;
          }
}

Command (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of adifferent abstract/interface type which has been encapsulated by the command implementation during its creation)

·      All implementations of java.lang.Runnable
·      All implementations of javax.swing.Action
3.       Interpreter - implements a specialized language.

import java.util.Stack;

interface IExpression {
          public int interpret();
}
/** Terminal Expression */
class NumberExpression implements IExpression {
          int number;

          public NumberExpression(int i) {
                   number = i;
          }

          public NumberExpression(String s) {
                   number = Integer.parseInt(s);
          }

          @Override
          public int interpret() {
                   return number;
          }

}
/** Non-terminal expression */
class MultiplyExpression implements IExpression {

          IExpression leftExpression;
          IExpression rightExpresion;

          public MultiplyExpression(IExpression leftExpression,
                             IExpression rightExpresion) {
                   this.leftExpression = leftExpression;
                   this.rightExpresion = rightExpresion;
          }

          @Override
          public int interpret() {

                   return leftExpression.interpret() * rightExpresion.interpret();
          }

}

class PlusExpression implements IExpression {
          IExpression leftExpression;
          IExpression rightExpresion;

          public PlusExpression(IExpression leftExpression, IExpression rightExpresion) {
                   this.leftExpression = leftExpression;
                   this.rightExpresion = rightExpresion;
          }

          @Override
          public int interpret() {
                   return leftExpression.interpret() + rightExpresion.interpret();
          }

}

class MinusExpression implements IExpression {

          IExpression leftExpression;
          IExpression rightExpresion;

          public MinusExpression(IExpression leftExpression,
                             IExpression rightExpresion) {
                   this.leftExpression = leftExpression;
                   this.rightExpresion = rightExpresion;
          }

          @Override
          public int interpret() {

                   return leftExpression.interpret() - rightExpresion.interpret();
          }

}

/*-
 * Postfix calculator.
 *
 * Algorithm for postfix expression parser implementation is simpler than for
 * infix.
 *
 * Read token one by one and loop till end of expression
 * Is read element a number
 * 1. true then, push it to a stack
 * 2. false then,
 *    1. pop two elements from stack
 *    2. apply the operator
 *    3. push the result to stack
 *
 */
public class InterpreterExample {
          public static void main(String args[]) {
                   String tokenString = "4 3 2 - 1 + *";
                   Stack stack = new Stack();

                   String[] tokenList = tokenString.split(" ");
                   for (String s : tokenList) {
                             if (isOperator(s)) {
                                      IExpression rightExpression = stack.pop();
                                      IExpression leftExpression = stack.pop();
                                      IExpression operator = getOperatorInstance(s, leftExpression,
                                                          rightExpression);
                                      int result = operator.interpret();
                                      stack.push(new NumberExpression(result));
                             } else {
                                      IExpression i = new NumberExpression(s);
                                      stack.push(i);
                             }
                   }
                   System.out.println("Result: " + stack.pop().interpret());
          }

          public static boolean isOperator(String s) {
                   if (s.equals("+") || s.equals("-") || s.equals("*"))
                             return true;
                   else
                             return false;
          }

          public static IExpression getOperatorInstance(String s, IExpression left,
                             IExpression right) {
                   switch (s) {
                   case "+":
                             return new PlusExpression(left, right);
                   case "-":
                             return new MinusExpression(left, right);
                   case "*":
                             return new MultiplyExpression(left, right);
                   }
                   return null;
          }
}

Interpreter (recognizeable by behavioral methods returning a structurally different instance/type of the given instance/type; note that parsing/formatting is not part of the pattern, determining the pattern and how to apply it is)

·      java.util.Pattern
·      java.text.Normalizer
·      All subclasses of java.text.Format
·      All subclasses of javax.el.ELResolver

4.       Iterator - accesses the elements of an object sequentially without exposing its underlying representation.
import java.util.ArrayList;
import java.util.List;

class Animal {
          private String animalName;
          private String animalType;

          public Animal(String animalName, String animalType) {
                   this.animalName = animalName;
                   this.animalType = animalType;
          }

          public String getAnimalName() {
                   return animalName;
          }

          public void setAnimalName(String animalName) {
                   this.animalName = animalName;
          }

          public String getAnimalType() {
                   return animalType;
          }

          public void setAnimalType(String animalType) {
                   this.animalType = animalType;
          }
}

interface Iterator {
          public Animal nextAnimal();

          public boolean isLastAnimal();

          public Animal currentAnimal();
}

class WildIterator implements Iterator {

          public List animalList;
          private int position;

          public WildIterator(List animalList) {
                   this.animalList = animalList;
          }

          @Override
          public Animal nextAnimal() {
                   Animal animal = null;
                   for (; position < animalList.size(); position++) {
                             if ("Wild".equals((animalList.get(position)).getAnimalType())) {
                                      animal = animalList.get(position);
                                      position++;
                                      break;
                             }
                   }
                   return animal;
          }

          @Override
          public boolean isLastAnimal() {
                   for (int i = position; i < animalList.size(); i++) {
                             if ("Wild".equals((animalList.get(i)).getAnimalType())) {
                                      return false;
                             }
                   }
                   return true;
          }

          @Override
          public Animal currentAnimal() {
                   if (position < animalList.size()) {
                             return animalList.get(position);
                   }
                   return null;
          }

}

class DomesticIterator implements Iterator {

          List animalList;
          private int position;

          public DomesticIterator(List animalList) {
                   this.animalList = animalList;
          }

          @Override
          public Animal nextAnimal() {
                   Animal animal = null;
                   for (; position < animalList.size(); position++) {
                             if ("Domestic".equals((animalList.get(position)).getAnimalType())) {
                                      animal = animalList.get(position);
                                      position++;
                                      break;
                             }
                   }
                   return animal;
          }

          @Override
          public boolean isLastAnimal() {
                   for (int i = position; i < animalList.size(); i++) {
                             if ("Domestic".equals((animalList.get(i)).getAnimalType())) {
                                      return false;
                             }
                   }
                   return true;
          }

          @Override
          public Animal currentAnimal() {
                   if (position < animalList.size()) {
                             return animalList.get(position);
                   }
                   return null;
          }

}

interface IZoo {

          public List getAnimals();

          public void addAnimal(Animal animal);

          public void removeAnimal(Animal animal);

          public Iterator createIterator(String iteratorType);
}

class ZooImpl implements IZoo {

          List animalList;

          public ZooImpl() {
                   animalList = new ArrayList();
          }

          @Override
          public List getAnimals() {

                   return animalList;
          }

          @Override
          public void addAnimal(Animal animal) {
                   animalList.add(animal);

          }

          @Override
          public void removeAnimal(Animal animal) {
                   animalList.remove(animal);

          }

          @Override
          public Iterator createIterator(String iteratorType) {
                   if ("Wild".equals(iteratorType)) {
                             return new WildIterator(animalList);
                   } else {
                             return new DomesticIterator(animalList);
                   }
          }
}

public class IteratorExample {
          public static void main(String args[]) {
                   ZooImpl zoo = new ZooImpl();
                   zoo.addAnimal(new Animal("Tiger", "Wild"));
                   zoo.addAnimal(new Animal("Lion", "Wild"));
                   zoo.addAnimal(new Animal("Tom Cat", "Domestic"));
                   zoo.addAnimal(new Animal("Raging Bull", "Wild"));
                   zoo.addAnimal(new Animal("Scooby Doo", "Domestic"));

                   Iterator wildIterator = zoo.createIterator("Wild");
                   while (!wildIterator.isLastAnimal()) {
                             System.out.println("Wild Animal: "
                                                + wildIterator.nextAnimal().getAnimalName());
                   }

                   Iterator domesticIterator = zoo.createIterator("Domestic");
                   while (!domesticIterator.isLastAnimal()) {
                             System.out.println("Domestic Animal: "
                                                + domesticIterator.nextAnimal().getAnimalName());
                   }
          }
}

Iterator (recognizeable by behavioral methods sequentially returning instances of a different type from a queue)

·      All implementations of java.util.Iterator (thus among others also java.util.Scanner!).
·      All implementations of java.util.Enumeration

As of Java 5, objects implementing the Iterable interface, which returns an Iterator from its only method, can be traversed using theenhanced for loop syntax.[2] The Collection interface from the Java collections framework extends Iterable.
5.       Mediator - allows loose coupling between classes by being the only class that has detailed knowledge of their methods.
interface IATCMediator {

          public void registerRunway(Runway runway);

          public void registerFlight(Flight flight);

          public boolean isLandingOk();

          public void setLandingStatus(boolean status);
}

interface ICommand {
          void land();
}

class Flight implements ICommand {
          private IATCMediator atcMediator;

          public Flight(IATCMediator atcMediator) {
                   this.atcMediator = atcMediator;
          }

          public void land() {
                   if (atcMediator.isLandingOk()) {
                             System.out.println("Landing done....");
                             atcMediator.setLandingStatus(true);
                   } else
                             System.out.println("Will wait to land....");
          }

          public void getReady() {
                   System.out.println("Getting ready...");
          }

}

class Runway implements ICommand {
          private IATCMediator atcMediator;

          public Runway(IATCMediator atcMediator) {
                   this.atcMediator = atcMediator;
                   atcMediator.setLandingStatus(true);
          }

          @Override
          public void land() {
                   System.out.println("Landing permission granted...");
                   atcMediator.setLandingStatus(true);
          }

}

class ATCMediator implements IATCMediator {
          private Flight flight;
          private Runway runway;
          public boolean land;

          public void registerRunway(Runway runway) {
                   this.runway = runway;
          }

          public void registerFlight(Flight flight) {
                   this.flight = flight;
          }

          public boolean isLandingOk() {
                   return land;
          }

          @Override
          public void setLandingStatus(boolean status) {
                   land = status;

          }
}

public class MediatorExample {
          public static void main(String args[]) {

                   IATCMediator atcMediator = new ATCMediator();
                   Flight sparrow101 = new Flight(atcMediator);
                   Runway mainRunway = new Runway(atcMediator);
                   atcMediator.registerFlight(sparrow101);
                   atcMediator.registerRunway(mainRunway);
                   sparrow101.getReady();
                   mainRunway.land();
                   sparrow101.land();
          }
}

Mediator (recognizeable by behavioral methods taking an instance of different abstract/interface type (usually using the command pattern) which delegates/uses the given instance)

·      java.util.Timer (all scheduleXXX() methods)
·      java.util.concurrent.ExecutorService (the invokeXXX() and submit() methods)
·      java.util.concurrent.ScheduledExecutorService (all scheduleXXX() methods)
6.       Memento - provides the ability to restore an object to its previous state (undo).
import java.util.ArrayList;
import java.util.List;

class Memento {
          private String state;

          public Memento(String state) {
                   this.state = state;
          }

          public String getState() {
                   return state;
          }
}

class Originator {

          // this String is just for example
          // in real world application this
          // will be a java class - the object
          // for which the state to be stored
          private String state;

          public void setState(String state) {
                   this.state = state;
          }

          public String getState() {
                   return state;
          }

          public Memento createMemento() {
                   return new Memento(state);
          }

          public void setMemento(Memento memento) {
                   state = memento.getState();
          }
}

class Caretaker {
          private List statesList = new ArrayList();

          public void addMemento(Memento m) {
                   statesList.add(m);
          }

          public Memento getMemento(int index) {
                    return statesList.get(index);
          }
}

public class MementoExample {
          public static void main(String[] args) {
                   Originator originator = new Originator();
                   originator.setState("Lion");
                   Memento memento = originator.createMemento();
                   Caretaker caretaker = new Caretaker();
                   caretaker.addMemento(memento);

                   originator.setState("Tiger");
                   originator.setState("Horse");
                   memento = originator.createMemento();
                   caretaker.addMemento(memento);
                   originator.setState("Elephant");
                   System.out
                                      .println("Originator Current State: " + originator.getState());
                   System.out.println("Originator restoring to previous state...");
                   memento = caretaker.getMemento(1);
                   originator.setMemento(memento);
                   System.out
                                      .println("Originator Current State: " + originator.getState());
                   System.out.println("Again restoring to previous state...");
                   memento = caretaker.getMemento(0);
                   originator.setMemento(memento);
                   System.out
                                      .println("Originator Current State: " + originator.getState());
          }
}
7.       Observer - is a publish/subscribe pattern which allows a number of observer objects to see an event.

import java.util.ArrayList;
import java.util.List;

/*
 * Same as Observable.
 */
interface Subject {

          public void registerObserver(Observer observer);

          public void notifyObserver();

          public void unRegisterObserver(Observer observer);

          public Object getUpdate();

}

class Blog implements Subject {

          List observersList;
          private boolean stateChange;

          public Blog() {
                   this.observersList = new ArrayList();
                    stateChange = false;
          }

          public void registerObserver(Observer observer) {
                   observersList.add(observer);
          }

          public void unRegisterObserver(Observer observer) {
                   observersList.remove(observer);
          }

          public void notifyObserver() {

                   if (stateChange) {
                             for (Observer observer : observersList) {
                                      observer.update();
                             }
                   }
          }

          public Object getUpdate() {
                   Object changedState = null;
                   // should have logic to send the
                   // state change to querying observer
                   if (stateChange) {
                             changedState = "Observer Design Pattern";
                   }
                   return changedState;
          }

          public void postNewArticle() {
                   stateChange = true;
                   notifyObserver();
          }

}

interface Observer {

          public void update();

          public void setSubject(Subject subject);
}

class User implements Observer {

          private String article;
          private Subject blog;

          public void setSubject(Subject blog) {
                   this.blog = blog;
                   article = "No New Article!";
          }

          @Override
          public void update() {
                   System.out.println("State change reported by Subject.");
                   article = (String) blog.getUpdate();
          }

          public String getArticle() {
                   return article;
          }
}

public class ObserverExample {
          public static void main(String args[]) {
                   Blog blog = new Blog();
                   User user1 = new User();
                   User user2 = new User();
                   blog.registerObserver(user1);
                   blog.registerObserver(user2);
                   user1.setSubject(blog);
                   user2.setSubject(blog);

                   System.out.println(user1.getArticle());
                   blog.postNewArticle();
                   System.out.println(user1.getArticle());
          }
}

Observer (or Publish/Subscribe) (recognizeable by behavioral methods which invokes a method on an instance of anotherabstract/interface type, depending on own state)

·      java.util.Observer/java.util.Observable (rarely used in real world though)
·      All implementations of java.util.EventListener (practically all over Swing thus)

8.       State - allows an object to alter its behavior when it’s internal state changes.

/**
 * State interface.
 */
interface MobileAlertState {
          public void alert(AlertStateContext ctx);
}

class Vibration implements MobileAlertState {

          @Override
          public void alert(AlertStateContext ctx) {
                   System.out.println("vibration...");
          }
}

class Silent implements MobileAlertState {

          @Override
          public void alert(AlertStateContext ctx) {
                   System.out.println("silent...");
          }

}

/**
 * This class maintains the current state and is the core of the state design
 * pattern. A client should access / run the whole setup through this class.
 */
class AlertStateContext {
          private MobileAlertState currentState;

          public AlertStateContext() {
                   currentState = new Vibration();
          }

          public void setState(MobileAlertState state) {
                   currentState = state;
          }

          public void alert() {
                   currentState.alert(this);
          }
}

public class StateExample {
          public static void main(String[] args) {
                   AlertStateContext stateContext = new AlertStateContext();
                   stateContext.alert();
                   stateContext.alert();
                   stateContext.setState(new Silent());
                   stateContext.alert();
                   stateContext.alert();
                   stateContext.alert();
          }
}

State (recognizeable by behavioral methods which changes its behaviour depending on the instance's state which can be controlled externally)

·      javax.faces.lifecycle.LifeCycle#execute() (controlled by FacesServlet, the behaviour is dependent on current phase (state) of JSF lifecycle)

9.       Strategy - allows one of a family of algorithms to be selected on-the-fly at runtime.

/**
 * The classes that implement a concrete strategy should implement this. The
 * Context class uses this to call the concrete strategy.
 */
interface Strategy {
          int execute(int a, int b);
};

/** Implements the algorithm using the strategy interface */
class Add implements Strategy {
          public int execute(int a, int b) {
                   System.out.println("Called Add's execute()");
                   return a + b; // Do an addition with a and b
          }
};

class Subtract implements Strategy {
          public int execute(int a, int b) {
                   System.out.println("Called Subtract's execute()");
                   return a - b; // Do a subtraction with a and b
          }
};

class Multiply implements Strategy {
          public int execute(int a, int b) {
                   System.out.println("Called Multiply's execute()");
                   return a * b; // Do a multiplication with a and b
          }
};

// Configured with a ConcreteStrategy object and maintains
// a reference to a Strategy object
class Context {
          private Strategy strategy;

          public Context(Strategy strategy) {
                   this.strategy = strategy;
          }

          public int executeStrategy(int a, int b) {
                   return this.strategy.execute(a, b);
          }
};

/** Tests the pattern */
class StrategyExample {
          public static void main(String[] args) {
                   Context context;
                   // Three contexts following different strategies
                   context = new Context(new Add());
                   int resultA = context.executeStrategy(3, 4);

                   context = new Context(new Subtract());
                   int resultB = context.executeStrategy(3, 4);

                   context = new Context(new Multiply());
                   int resultC = context.executeStrategy(3, 4);

                   System.out.println("Result A : " + resultA);
                   System.out.println("Result B : " + resultB);
                   System.out.println("Result C : " + resultC);
          }
}

Strategy and open/closed principle[edit]


According to the strategy pattern, the behaviors of a class should not be inherited. Instead they should be encapsulated using interfaces. As an example, consider a car class. Two possible functionalities for car are brake and accelerate.
Since accelerate and brake behaviors change frequently between models, a common approach is to implement these behaviors in subclasses. This approach has significant drawbacks: accelerate and brake behaviors must be declared in each new Car model. The work of managing these behaviors increases greatly as the number of models increases, and requires code to be duplicated across models. Additionally, it is not easy to determine the exact nature of the behavior for each model without investigating the code in each.
The strategy pattern uses aggregation instead of inheritance. In the strategy pattern, behaviors are defined as separate interfaces and specific classes that implement these interfaces. Specific classes encapsulate these interfaces. This allows better decoupling between the behavior and the class that uses the behavior. The behavior can be changed without breaking the classes that use it, and the classes can switch between behaviors by changing the specific implementation used without requiring any significant code changes. Behaviors can also be changed at run-time as well as at design-time. For instance, a car object’s brake behavior can be changed from BrakeWithABS() to Brake() by changing the brakeBehavior member to:
brakeBehavior = new Brake();
This gives greater flexibility in design and is in harmony with the Open/closed principle (OCP) that states that classes should be open for extension but closed for modification.

Strategy (recognizeable by behavioral methods in an abstract/interface type which invokes a method in an implementation of adifferent abstract/interface type which has been passed-in as method argument into the strategy implementation)

·      java.util.Comparator#compare(), executed by among others Collections#sort().
·      javax.servlet.http.HttpServlet, the service() and all doXXX() methods takeHttpServletRequest and HttpServletResponse and the implementor has to process them (and not to get hold of them as instance variables!).

10.   Template Method - defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior.
The template method is used in frameworks, where each implements the invariant parts of a domain's architecture, leaving "placeholders" for customisation options. This is an example for inversion of control, also called the Hollywood principle. Reasons to use the template method are to:[4]
·         Let subclasses implement (through method overriding) behavior that can vary.
·         Avoid duplication in the code: the general workflow structure is implemented once in the abstract class's algorithm, and necessary variations are implemented in each of the subclasses.
·         Control at what point(s) subclassing is allowed. As opposed to a simple polymorphic override, where the base method would be entirely rewritten allowing radical change to the workflow, only the specific details of the workflow are allowed to change.
The control structure (inversion of control) that is the result of the application of a template pattern is often referred to as the Hollywood Principle: "Don't call us, we'll call you." Using this principle, the template method in a parent class controls the overall process by calling subclass methods as required.

import java.util.Random;

/**
 * An abstract class that is common to several games in which players play
 * against the others, but only one is playing at a given time.
 */

abstract class Game {

          protected int playersCount;

          abstract void initializeGame();

          abstract void makePlay(int player);

          abstract boolean endOfGame();

          abstract void printWinner();

          /* A template method : */
          public final void playOneGame(int playersCount) {
                   this.playersCount = playersCount;
                   initializeGame();
                   int j = 0;
                   while (!endOfGame()) {
                             makePlay(j);
                             j = (j + 1) % playersCount;
                   }
                   printWinner();
          }
}

// Now we can extend this class in order
// to implement actual games:

class Monopoly extends Game {
          private int currentPlayer;

          /* Implementation of necessary concrete methods */
          void initializeGame() {
                   // Initialize players
                   // Initialize money
          }

          void makePlay(int player) {
                   // Process one turn of player
                   System.out.println("Playing player: " + player);
                   this.currentPlayer = player;
          }

          boolean endOfGame() {
                   // Return true if game is over
                   // according to Monopoly rules
                   Random rand = new Random();
                   return rand.nextInt(100) < 5 ? true : false;
          }

          void printWinner() {
                   // Display who won
                   System.out.println("Winner of Monopoly game is player: "
                                      + currentPlayer);
          }
          /* Specific declarations for the Monopoly game. */

          // ...
}

class Chess extends Game {
          private int currentPlayer;

          /* Implementation of necessary concrete methods */
          void initializeGame() {
                   // Initialize players
                   // Put the pieces on the board
          }

          void makePlay(int player) {
                   // Process a turn for the player
                   System.out.println("Playing player: " + player);
                   this.currentPlayer = player;
          }

          boolean endOfGame() {
                   // Return true if in Checkmate or
                   // Stalemate has been reached
                   Random rand = new Random();
                   return rand.nextInt(100) < 10 ? true : false;
          }

          void printWinner() {
                   System.out.println("Winner of Chess game is player: " + currentPlayer);
          }
          /* Specific declarations for the chess game. */

          // ...
}

public class TemplateMethodExample {
          public static void main(String[] args) {
                   Game g1 = new Chess();
                   g1.playOneGame(2);
                  
                   Monopoly m1 = new Monopoly();
                   m1.playOneGame(4);
          }
}

Template method (recognizeable by behavioral methods which already have a "default" behaviour definied by an abstract type)

·      All non-abstract methods of java.io.InputStreamjava.io.OutputStreamjava.io.Readerand java.io.Writer.
·      All non-abstract methods of java.util.AbstractListjava.util.AbstractSet andjava.util.AbstractMap.
·      javax.servlet.http.HttpServlet, all the doXXX() methods by default sends a HTTP 405 "Method Not Allowed" error to the response. You're free to implement none or any of them.

11.   Visitor - separates an algorithm from an object structure by moving the hierarchy of methods into one object.

In the example below, every car element has to do perform same algorithm (print and do, but in their own way) so we can take out the algorithms into their own classes and invoke them when the corresponding visit method is called. In future more algorithms may be added to all car elements as a new class extending CarElementVisitor.

interface ICarElementVisitor {
          void visit(Wheel wheel);

          void visit(Engine engine);

          void visit(Body body);

          void visit(Car car);
}

interface ICarElement {
          void accept(ICarElementVisitor visitor); // CarElements have to provide
                                                                                                                   // accept().
}

class Wheel implements ICarElement {
          private String name;

          public Wheel(String name) {
                   this.name = name;
          }

          public String getName() {
                   return this.name;
          }

          public void accept(ICarElementVisitor visitor) {
                   /*
                    * accept(ICarElementVisitor) in Wheel implements
                    * accept(ICarElementVisitor) in ICarElement, so the call to accept is
                    * bound at run time. This can be considered the first dispatch.
                    * However, the decision to call visit(Wheel) (as opposed to
                    * visit(Engine) etc.) can be made during compile time since 'this' is
                    * known at compile time to be a Wheel. Moreover, each implementation of
                    * ICarElementVisitor implements the visit(Wheel), which is another
                    * decision that is made at run time. This can be considered the second
                    * dispatch.
                    */
                   visitor.visit(this);
          }
}

class Engine implements ICarElement {
          public void accept(ICarElementVisitor visitor) {
                   visitor.visit(this);
          }
}

class Body implements ICarElement {
          public void accept(ICarElementVisitor visitor) {
                   visitor.visit(this);
          }
}

class Car implements ICarElement {
          ICarElement[] elements;

          public Car() {
                   // create new Array of elements
                   this.elements = new ICarElement[] { new Wheel("front left"),
                                      new Wheel("front right"), new Wheel("back left"),
                                      new Wheel("back right"), new Body(), new Engine() };
          }

          public void accept(ICarElementVisitor visitor) {
                   for (ICarElement elem : elements) {
                             elem.accept(visitor);
                   }
                   visitor.visit(this);
          }
}

class CarElementPrintVisitor implements ICarElementVisitor {
          public void visit(Wheel wheel) {
                   System.out.println("Visiting " + wheel.getName() + " wheel");
          }

          public void visit(Engine engine) {
                   System.out.println("Visiting engine");
          }

          public void visit(Body body) {
                   System.out.println("Visiting body");
          }

          public void visit(Car car) {
                   System.out.println("Visiting car");
          }
}

class CarElementDoVisitor implements ICarElementVisitor {
          public void visit(Wheel wheel) {
                   System.out.println("Kicking my " + wheel.getName() + " wheel");
          }

          public void visit(Engine engine) {
                   System.out.println("Starting my engine");
          }

          public void visit(Body body) {
                   System.out.println("Moving my body");
          }

          public void visit(Car car) {
                   System.out.println("Starting my car");
          }
}

public class VisitorExample {
          public static void main(String[] args) {
                   ICarElement car = new Car();
                   car.accept(new CarElementPrintVisitor());
                   car.accept(new CarElementDoVisitor());
          }
}

Visitor (recognizeable by two different abstract/interface types which has methods definied which takes each the other abstract/interface type; the one actually calls the method of the other and the other executes the desired strategy on it)


No comments: