Tuesday, May 4, 2010

State Pattern

The state pattern is a behavioral object design pattern. The idea behind the state pattern is for an object to change its behavior depending on its state. In the state pattern, we have a Context class, and this class has a State reference to a Concrete State instance. The State interface declares particular methods that represent the behaviors of a particular state. Concrete States implement these behaviors. By changing a Context's Concrete State, we change its behavior. In essence, in the state pattern, a class (the Context) is supposed to behave like different classes depending on its state. The state pattern avoids the use of switch and if statements to change behavior.
Let's look at an example of the state pattern. First off, we'll define the EmotionalState interface. It declares two methods, sayHello() and sayGoodbye().

EmotionalState.java

package com.cakes;

// State
public interface EmotionalState {

 public String sayHello();

 public String sayGoodbye();

}
The HappyState class is a Concrete State that implements sayHello() and sayGoodbye() of EmotionalState. These messages are cheerful (representing a happy state).

HappyState.java

package com.cakes;

// Concrete State
public class HappyState implements EmotionalState {

 @Override
 public String sayGoodbye() {
  return "Bye, friend!";
 }

 @Override
 public String sayHello() {
  return "Hello, friend!";
 }

}
The SadState class also implements the EmotionalState interface. The messages are sad (representing a sad state).

SadState.java

package com.cakes;

//Concrete State
public class SadState implements EmotionalState {

 @Override
 public String sayGoodbye() {
  return "Bye. Sniff, sniff.";
 }

 @Override
 public String sayHello() {
  return "Hello. Sniff, sniff.";
 }

}
The Person class is the Context class. It contains an EmotionalState reference to a concrete state. In this example, we have Person implement the EmotionalState reference, and we pass the calls to Person's sayHello() and sayGoodbye() methods on to the corresponding methods on the emotionalState reference. As a result of this, a Person object behaves differently depending on the state of Person (ie, the current EmotionalState reference).

Person.java

package com.cakes;

// Context
public class Person implements EmotionalState {

 EmotionalState emotionalState;

 public Person(EmotionalState emotionalState) {
  this.emotionalState = emotionalState;
 }

 public void setEmotionalState(EmotionalState emotionalState) {
  this.emotionalState = emotionalState;
 }

 @Override
 public String sayGoodbye() {
  return emotionalState.sayGoodbye();
 }

 @Override
 public String sayHello() {
  return emotionalState.sayHello();
 }

}
The Demo class demonstrates the state pattern. First, it creates a Person object with a HappyState object. We display the results of sayHello() and sayGoodbyte() when the person object is in the happy state. Next, we change the person object's state with a SadState object. We display the results of sayHello() and sayGoodbyte(), and we see that in the sad state, the person object's behavior is different.

Demo.java

package com.cakes; public class Demo { public static void main(String[] args) { Person person = new Person(new HappyState()); System.out.println("Hello in happy state: " + person.sayHello()); System.out.println("Goodbye in happy state: " + person.sayGoodbye()); person.setEmotionalState(new SadState()); System.out.println("Hello in sad state: " + person.sayHello()); System.out.println("Goodbye in sad state: " + person.sayGoodbye()); } } The console output of executing Demo is shown here.

Console Output

Hello in happy state: Hello, friend! Goodbye in happy state: Bye, friend! Hello in sad state: Hello. Sniff, sniff. Goodbye in sad state: Bye. Sniff, sniff. Note that we don't necessarily need to have the Context (ie, Person) implement the EmotionalState interface. The behavioral changes could have been internal to the Context rather than exposing EmotionalState's methods to the outside. However, having the Context class implement the State interface allows us to directly access the different behaviors that result from the different states of the Context.

Observer Pattern

The observer pattern is a behavioral object design pattern. In the observer pattern, an object called the subject maintains a collection of objects called observers. When the subject changes, it notifies the observers. Observers can be added or removed from the collection of observers in the subject. The changes in state of the subject can be passed to the observers so that the observers can change their own state to reflect this change.
The subject has an interface that defines methods for attaching and detaching observers from the subject's collection of observers. This interface also features a notification method. This method should be called when the state of the subject changes. This notifies the observers that the subject's state has changed. The observers have an interface with a method to update the observer. This update method is called for each observer in the subject's notification method. Since this communication occurs via an interface, any concrete observer implementing the observer interface can be updated by the subject. This results in loose coupling between the subject and the observer classes.
Now we'll look at an example of the observer pattern. We'll start by creating an interface for the subject called WeatherSubject. This will declare three methods: addObserver(), removeObserver(), and doNotify().

WeatherSubject.java

package com.cakes;

public interface WeatherSubject {

 public void addObserver(WeatherObserver weatherObserver);

 public void removeObserver(WeatherObserver weatherObserver);

 public void doNotify();

}
We'll also create an interface for the observers called WeatherObserver. It features one method, a doUpdate() method.

WeatherObserver.java

package com.cakes;

public interface WeatherObserver {

 public void doUpdate(int temperature);
 
}
The WeatherStation class implements WeatherSubject. It is our subject class. It maintains a set of WeatherObservers which are added via addObserver() and removed via removeObserver(). When WeatherSubject's state changes via setTemperature(), the doNotify() method is called, which contacts all the WeatherObservers with the temperature via their doUpdate() methods.

WeatherStation.java

package com.cakes;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class WeatherStation implements WeatherSubject {

 Set weatherObservers;
 int temperature;

 public WeatherStation(int temperature) {
  weatherObservers = new HashSet();
  this.temperature = temperature;
 }

 @Override
 public void addObserver(WeatherObserver weatherObserver) {
  weatherObservers.add(weatherObserver);
 }

 @Override
 public void removeObserver(WeatherObserver weatherObserver) {
  weatherObservers.remove(weatherObserver);
 }

 @Override
 public void doNotify() {
  Iterator it = weatherObservers.iterator();
  while (it.hasNext()) {
   WeatherObserver weatherObserver = it.next();
   weatherObserver.doUpdate(temperature);
  }
 }

 public void setTemperature(int newTemperature) {
  System.out.println("\nWeather station setting temperature to " + newTemperature);
  temperature = newTemperature;
  doNotify();
 }

}
WeatherCustomer1 is an observer that implements WeatherObserver. Its doUpdate() method gets the current temperature from the WeatherStation and displays it.

WeatherCustomer1.java

package com.cakes; public class WeatherCustomer1 implements WeatherObserver { @Override public void doUpdate(int temperature) { System.out.println("Weather customer 1 just found out the temperature is:" + temperature); } } WeatherCustomer2 performs similar functionality as WeatherCustomer1.

WeatherCustomer2.java

package com.cakes; public class WeatherCustomer2 implements WeatherObserver { @Override public void doUpdate(int temperature) { System.out.println("Weather customer 2 just found out the temperature is:" + temperature); } } The Demo class demonstrates the observer pattern. It creates a WeatherStation and then a WeatherCustomer1 and a WeatherCustomer2. The two customers are added as observers to the weather station. Then the setTemperature() method of the weather station is called. This changes the state of the weather station and the customers are notified of this temperature update. Next, the WeatherCustomer1 object is removed from the station's collection of observers. Then, the setTemperature() method is called again. This results in the notification of the WeatherCustomer2 object.

Demo.java

package com.cakes; public class Demo { public static void main(String[] args) { WeatherStation weatherStation = new WeatherStation(33); WeatherCustomer1 wc1 = new WeatherCustomer1(); WeatherCustomer2 wc2 = new WeatherCustomer2(); weatherStation.addObserver(wc1); weatherStation.addObserver(wc2); weatherStation.setTemperature(34); weatherStation.removeObserver(wc1); weatherStation.setTemperature(35); } } The console output of executing Demo is shown here.

Console Output

Weather station setting temperature to 34 Weather customer 2 just found out the temperature is:34 Weather customer 1 just found out the temperature is:34 Weather station setting temperature to 35 Weather customer 2 just found out the temperature is:35 In a more advanced case, we might have given each observer a reference to the weather station object. This could allow the observer the ability to compare the state of the subject in detail with its own state and make any necessary updates to its own state.

Momento Pattern

The memento pattern is a behavioral design pattern. The memento pattern is used to store an object's state so that this state can be restored at a later point. The saved state data in the memento object is not accessible outside of the object to be saved and restored. This protects the integrity of the saved state data.
In this pattern, an Originator class represents the object whose state we would like to save. A Memento class represents an object to store the state of the Originator. The Memento class is typically a private inner class of the Originator. As a result, the Originator has access to the fields of the memento, but outside classes do not have access to these fields. This means that state information can be transferred between the Memento and the Originator within the Originator class, but outside classes do not have access to the state data stored in the Memento.
The memento pattern also utilizes a Caretaker class. This is the object that is responsible for storing and restoring the Originator's state via a Memento object. Since the Memento is a private inner class, the Memento class type is not visible to the Caretaker. As a result, the Memento object needs to be stored as an Object within the Caretaker.

Now, let's look at an example. The DietInfo class is our Originator class. We'd like to be able to save and restore its state. It contains 3 fields: a dieter name field, the day number of the diet, and the weight of the dieter on the specified day of the diet.
This class contains a private inner class called Memento. This is our Memento class that is used to save the state of DietInfo. Memento has 3 fields representing the dieter name, the day number, and the weight of the dieter.
Notice the save() method of DietInfo. This creates and returns a Memento object. This returned Memento object gets stored by the caretaker. Note that DietInfo.Memento is not visible, so the caretaker can't reference DietInfo.Memento. Instead, it stores the reference as an Object.
The restore() method of DietInfo is used to restore the state of the DietInfo. The caretaker passes in the Memento (as an Object). The memento is cast to a Memento object and then the DietInfo object's state is restored by copying over the values from the memento.

DietInfo.java

package com.cakes;

// originator - object whose state we want to save
public class DietInfo {

 String personName;
 int dayNumber;
 int weight;

 public DietInfo(String personName, int dayNumber, int weight) {
  this.personName = personName;
  this.dayNumber = dayNumber;
  this.weight = weight;
 }

 public String toString() {
  return "Name: " + personName + ", day number: " + dayNumber + ", weight: " + weight;
 }

 public void setDayNumberAndWeight(int dayNumber, int weight) {
  this.dayNumber = dayNumber;
  this.weight = weight;
 }

 public Memento save() {
  return new Memento(personName, dayNumber, weight);
 }

 public void restore(Object objMemento) {
  Memento memento = (Memento) objMemento;
  personName = memento.mementoPersonName;
  dayNumber = memento.mementoDayNumber;
  weight = memento.mementoWeight;
 }

 // memento - object that stores the saved state of the originator
 private class Memento {
  String mementoPersonName;
  int mementoDayNumber;
  int mementoWeight;

  public Memento(String personName, int dayNumber, int weight) {
   mementoPersonName = personName;
   mementoDayNumber = dayNumber;
   mementoWeight = weight;
  }
 }
}
DietInfoCaretaker is the caretaker class that is used to store the state (ie, the memento) of a DietInfo object (ie, the originator). The memento is stored as an object since DietInfo.Memento is not visible to the caretaker. This protects the integrity of the data stored in the Memento object. The caretaker's saveState() method saves the state of the DietInfo object. The caretaker's restoreState() method restores the state of the DietInfo object.

DietInfoCaretaker.java

package com.cakes;

// caretaker - saves and restores a DietInfo object's state via a memento
// note that DietInfo.Memento isn't visible to the caretaker so we need to cast the memento to Object
public class DietInfoCaretaker {

 Object objMemento;

 public void saveState(DietInfo dietInfo) {
  objMemento = dietInfo.save();
 }

 public void restoreState(DietInfo dietInfo) {
  dietInfo.restore(objMemento);
 }

}
 
he MementoDemo class demonstrates the memento pattern. It creates a
caretaker and then a DietInfo object. The DietInfo object's state is
changed and displayed. At one point, the caretaker saves the state of
the DietInfo object. After this, the DietInfo object's state is further
changed and displayed. After this, the caretaker restores the state of
the DietInfo object. We verify this restoration by displaying the
DietInfo object's state. 

MementoDemo.java

package com.cakes; public class MementoDemo { public static void main(String[] args) { // caretaker DietInfoCaretaker dietInfoCaretaker = new DietInfoCaretaker(); // originator DietInfo dietInfo = new DietInfo("Fred", 1, 100); System.out.println(dietInfo); dietInfo.setDayNumberAndWeight(2, 99); System.out.println(dietInfo); System.out.println("Saving state."); dietInfoCaretaker.saveState(dietInfo); dietInfo.setDayNumberAndWeight(3, 98); System.out.println(dietInfo); dietInfo.setDayNumberAndWeight(4, 97); System.out.println(dietInfo); System.out.println("Restoring saved state."); dietInfoCaretaker.restoreState(dietInfo); System.out.println(dietInfo); } } The console output of the execution of MementoDemo is shown here. Notice how the state changes, and how we are able to save and restore the state of the originator via the caretaker's reference to the memento.

Console Output

Name: Fred, day number: 1, weight: 100 Name: Fred, day number: 2, weight: 99 Saving state. Name: Fred, day number: 3, weight: 98 Name: Fred, day number: 4, weight: 97 Restoring saved state. Name: Fred, day number: 2, weight: 99
 

Mediator Pattern-1

The mediator pattern is a behavioral object design pattern. The mediator pattern centralizes communication between objects into a mediator object. This centralization is useful since it localizes in one place the interactions between objects, which can increase code maintainability, especially as the number of classes in an application increases. Since communication occurs with the mediator rather than directly with other objects, the mediator pattern results in a loose coupling of objects.
The classes that communicate with the mediator are known as Colleagues. The mediator implementation is known as the Concrete Mediator. The mediator can have an interface that spells out the communication with Colleages. Colleagues know their mediator, and the mediator knows its colleagues.
Now, let's look at an example of this pattern. We'll create a Mediator class (without implementing a mediator interface in this example). This mediator will mediate the communication between two buyers (a Swedish buyer and a French buyer), an American seller, and a currency converter.
The Mediator has references to the two buyers, the seller, and the converter. It has methods so that objects of these types can be registered. It also has a placeBid() method. This method takes a bid amount and a unit of currency as parameters. It converts this amount to a dollar amount via communication with the dollarConverter. It then asks the seller if the bid has been accepted, and it returns the answer.

Mediator.java

package com.cakes;

public class Mediator {

 Buyer swedishBuyer;
 Buyer frenchBuyer;
 AmericanSeller americanSeller;
 DollarConverter dollarConverter;

 public Mediator() {
 }

 public void registerSwedishBuyer(SwedishBuyer swedishBuyer) {
  this.swedishBuyer = swedishBuyer;
 }

 public void registerFrenchBuyer(FrenchBuyer frenchBuyer) {
  this.frenchBuyer = frenchBuyer;
 }

 public void registerAmericanSeller(AmericanSeller americanSeller) {
  this.americanSeller = americanSeller;
 }

 public void registerDollarConverter(DollarConverter dollarConverter) {
  this.dollarConverter = dollarConverter;
 }

 public boolean placeBid(float bid, String unitOfCurrency) {
  float dollarAmount = dollarConverter.convertCurrencyToDollars(bid, unitOfCurrency);
  return americanSeller.isBidAccepted(dollarAmount);
 }
}
Here is the Buyer class. The SwedishBuyer and FrenchBuyer classes are subclasses of Buyer. The buyer has a unit of currency as a field, and it also has a reference to the mediator. The Buyer class has a attemptToPurchase() method. This method submits a bid to the mediator's placeBid() method. It returns the mediator's response.

Buyer.java

package com.cakes;

public class Buyer {

 Mediator mediator;
 String unitOfCurrency;

 public Buyer(Mediator mediator, String unitOfCurrency) {
  this.mediator = mediator;
  this.unitOfCurrency = unitOfCurrency;
 }

 public boolean attemptToPurchase(float bid) {
  System.out.println("Buyer attempting a bid of " + bid + " " + unitOfCurrency);
  return mediator.placeBid(bid, unitOfCurrency);
 }
}
The SwedishBuyer class is a subclass of Buyer. In the constructor, we set the unitOfCurrency to be "krona". We also register the SwedishBuyer with the mediator so that the mediator knows about the SwedishBuyer object.

SwedishBuyer.java

package com.cakes;

public class SwedishBuyer extends Buyer {

 public SwedishBuyer(Mediator mediator) {
  super(mediator, "krona");
  this.mediator.registerSwedishBuyer(this);
 }
}
The FrenchBuyer class is similar to the SwedishBuyer class, except the unitOfCurrency is "euro", and it registers with the mediator as the FrenchBuyer.

FrenchBuyer.java

package com.cakes;

public class FrenchBuyer extends Buyer {

 public FrenchBuyer(Mediator mediator) {
  super(mediator, "euro");
  this.mediator.registerFrenchBuyer(this);
 }
}

In the constructor of the AmericanSeller class, the class gets a reference to the mediator and the priceInDollars gets set. This is the price of some good being sold. The seller registers with the mediator as the AmericanSeller. The seller's isBidAccepted() method takes a bid (in dollars). If the bid is over the price (in dollars), the bid is accepted and true is returned. Otherwise, false is returned.

AmericanSeller.java

package com.cakes;

public class AmericanSeller {

 Mediator mediator;
 float priceInDollars;

 public AmericanSeller(Mediator mediator, float priceInDollars) {
  this.mediator = mediator;
  this.priceInDollars = priceInDollars;
  this.mediator.registerAmericanSeller(this);
 }

 public boolean isBidAccepted(float bidInDollars) {
  if (bidInDollars >= priceInDollars) {
   System.out.println("Seller accepts the bid of " + bidInDollars + " dollars\n");
   return true;
  } else {
   System.out.println("Seller rejects the bid of " + bidInDollars + " dollars\n");
   return false;
  }
 }

}
The DollarConverter class is another colleague class. When created, it gets a reference to the mediator and registers itself with the mediator as the DollarConverter. This class has methods to convert amounts in euros and kronor to dollars.

DollarConverter.java

package com.cakes;

public class DollarConverter {

 Mediator mediator;

 public static final float DOLLAR_UNIT = 1.0f;
 public static final float EURO_UNIT = 0.7f;
 public static final float KRONA_UNIT = 8.0f;

 public DollarConverter(Mediator mediator) {
  this.mediator = mediator;
  mediator.registerDollarConverter(this);
 }

 private float convertEurosToDollars(float euros) {
  float dollars = euros * (DOLLAR_UNIT / EURO_UNIT);
  System.out.println("Converting " + euros + " euros to " + dollars + " dollars");
  return dollars;
 }

 private float convertKronorToDollars(float kronor) {
  float dollars = kronor * (DOLLAR_UNIT / KRONA_UNIT);
  System.out.println("Converting " + kronor + " kronor to " + dollars + " dollars");
  return dollars;
 }

 public float convertCurrencyToDollars(float amount, String unitOfCurrency) {
  if ("krona".equalsIgnoreCase(unitOfCurrency)) {
   return convertKronorToDollars(amount);
  } else {
   return convertEurosToDollars(amount);
  }
 }
}
The Demo class demonstrates our mediator pattern. It creates a SwedishBuyer object and a FrenchBuyer object. It creates an AmericanSeller object with a selling price set to 10 dollars. It then creates a DollarConverter. All of these objects register themselves with the mediator in their constructors. The Swedish buyer starts with a bid of 55 kronor and keeps bidding up in increments of 15 kronor until the bid is accepted. The French buyer starts bidding at 3 euros and keeps bidding in increments of 1.50 euros until the bid is accepted.

Demo.java

package com.cakes;

public class Demo {

 public static void main(String[] args) {

  Mediator mediator = new Mediator();

  Buyer swedishBuyer = new SwedishBuyer(mediator);
  Buyer frenchBuyer = new FrenchBuyer(mediator);
  float sellingPriceInDollars = 10.0f;
  AmericanSeller americanSeller = new AmericanSeller(mediator, sellingPriceInDollars);
  DollarConverter dollarConverter = new DollarConverter(mediator);

  float swedishBidInKronor = 55.0f;
  while (!swedishBuyer.attemptToPurchase(swedishBidInKronor)) {
   swedishBidInKronor += 15.0f;
  }

  float frenchBidInEuros = 3.0f;
  while (!frenchBuyer.attemptToPurchase(frenchBidInEuros)) {
   frenchBidInEuros += 1.5f;
  }

 }

}
The console output of the execution of Demo is shown here.

Console Output

Buyer attempting a bid of 55.0 krona
Converting 55.0 kronor to 6.875 dollars
Seller rejects the bid of 6.875 dollars

Buyer attempting a bid of 70.0 krona
Converting 70.0 kronor to 8.75 dollars
Seller rejects the bid of 8.75 dollars

Buyer attempting a bid of 85.0 krona
Converting 85.0 kronor to 10.625 dollars
Seller accepts the bid of 10.625 dollars

Buyer attempting a bid of 3.0 euro
Converting 3.0 euros to 4.285714 dollars
Seller rejects the bid of 4.285714 dollars

Buyer attempting a bid of 4.5 euro
Converting 4.5 euros to 6.4285717 dollars
Seller rejects the bid of 6.4285717 dollars

Buyer attempting a bid of 6.0 euro
Converting 6.0 euros to 8.571428 dollars
Seller rejects the bid of 8.571428 dollars

Buyer attempting a bid of 7.5 euro
Converting 7.5 euros to 10.714286 dollars
Seller accepts the bid of 10.714286 dollars
In this example of the mediator pattern, notice that all communication between our objects (buyers, seller, and converter) occurs via the mediator. The mediator pattern helps reduce the number of object references needed (via composition) as classes proliferate in a project as a project grows.

Monday, May 3, 2010

Mediator Pattern

With the mediator pattern communication between objects is encapsulated with a mediator object. Objects no longer communicate directly with each other, but instead communicate through the mediator. This reduces the dependencies between communicating objects, thereby lowering the coupling.
Mediator Pattern

Intent


  • Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
  • Design an intermediary to decouple many peers.
  • Promote the many-to-many relationships between interacting peers to “full object status”.

Problem


We want to design reusable components, but dependencies between the potentially reusable pieces demonstrates the “spaghetti code” phenomenon (trying to scoop a single serving results in an “all or nothing clump”).

Discussion


In Unix, permission to access system resources is managed at three levels of granularity: world, group, and owner. A group is a collection of users intended to model some functional affiliation. Each user on the system can be a member of one or more groups, and each group can have zero or more users assigned to it. Next figure shows three users that are assigned to all three groups.
Mediator example

If we were to model this in software, we could decide to have User objects coupled to Group objects, and Group objects coupled to User objects. Then when changes occur, both classes and all their instances would be affected.

An alternate approach would be to introduce “an additional level of indirection” - take the mapping of users to groups and groups to users, and make it an abstraction unto itself. This offers several advantages: Users and Groups are decoupled from one another, many mappings can easily be maintained and manipulated simultaneously, and the mapping abstraction can be extended in the future by defining derived classes.
Mediator example

Partitioning a system into many objects generally enhances reusability, but proliferating interconnections between those objects tend to reduce it again. The mediator object: encapsulates all interconnections, acts as the hub of communication, is responsible for controlling and coordinating the interactions of its clients, and promotes loose coupling by keeping objects from referring to each other explicitly.

The Mediator pattern promotes a “many-to-many relationship network” to “full object status”. Modelling the inter-relationships with an object enhances encapsulation, and allows the behavior of those inter-relationships to be modified or extended through subclassing.

An example where Mediator is useful is the design of a user and group capability in an operating system. A group can have zero or more users, and, a user can be a member of zero or more groups. The Mediator pattern provides a flexible and non-invasive way to associate and manage users and groups.

Structure

Mediator scheme


Colleagues (or peers) are not coupled to one another. Each talks to the Mediator, which in turn knows and conducts the orchestration of the others. The “many to many” mapping between colleagues that would otherwise exist, has been “promoted to full object status”. This new abstraction provides a locus of indirection where additional leverage can be hosted.

Mediator scheme

Example


The Mediator defines an object that controls how a set of objects interact. Loose coupling between colleague objects is achieved by having colleagues communicate with the Mediator, rather than with each other. The control tower at a controlled airport demonstrates this pattern very well. The pilots of the planes approaching or departing the terminal area communicate with the tower rather than explicitly communicating with one another. The constraints on who can take off or land are enforced by the tower. It is important to note that the tower does not control the whole flight. It exists only to enforce constraints in the terminal area.
Mediator example

Check list


  1. Identify a collection of interacting objects that would benefit from mutual decoupling.
  2. Encapsulate those interactions in the abstraction of a new class.
  3. Create an instance of that new class and rework all “peer” objects to interact with the Mediator only.
  4. Balance the principle of decoupling with the principle of distributing responsibility evenly.
  5. Be careful not to create a “controller” or “god” object.

Rules of thumb


  • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.
  • Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing “observer” and “subject” objects, whereas a Mediator object encapsulates the communication between other objects. We’ve found it easier to make reusable Observers and Subjects than to make reusable Mediators.
  • On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.
  • Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely “adds value”, and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it doesn’t add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa).

Iterator Pattern


Definition

Provide a way to move through a list of collection or aggregated objects without knowing its internal representations.

Where to use & benefits

  • Use a standard interface to represent data objects.
  • Use s standard iterator built in each standard collection, like List, Sort, or Map.
  • Need to distinguish variations in the traversal of an aggregate.
  • Similar to Enumeration class, but more effective.
  • Need to filter out some info from an aggregated collection.

Example

Employee is an interface, Manager, PieceWorker, HourlyWorker and CommissionWorker are implementation classes of interface Employee. EmployeeTest class will create a list and use a built-in iterator of ArrayList class to traverse the members of the list.
import java.util.*;
interface Employee {   
    public abstract double earnings();
}
class Manager implements Employee {
    private double weeklySalary;
    private String name;
    public Manager(String name, double s) {
        this.name = name;
        setWeeklySalary(s);
    }
    
    void setWeeklySalary(double s) {
        if (s > 0) {
          weeklySalary = s;
        } else
          weeklySalary = 0;
    }
    
    public double earnings() {
        return weeklySalary;
    }
    public String getName() {
     return name;
 }
    public String toString() {
        return "Manager: " + getName();
    }
}

class PieceWorker implements Employee {
    private double wagePerPiece;
    private int quantity;
    private String name;
    public PieceWorker(String name, double w, int q) {
        this.name = name;
        setWagePerPiece(w);
        setQuantity(q);
    }
    
    void setWagePerPiece(double w) {
        if (w > 0) 
          wagePerPiece = w;
        else
          wagePerPiece = 0;
    }
    
    void setQuantity(int q) {
        if ( q > 0)
           quantity = q;
        else
           quantity = 0;
    }
    public String getName() {
     return name;
 }    
    public double earnings() {
        return quantity * wagePerPiece;
    }
    
    public String toString() {
        return "Piece worker: " + getName();
    }
}

class HourlyWorker implements Employee {
    private double hourlyWage;
    private double hours;
    private String name;
    public HourlyWorker(String name, double w, double h) {
        this.name = name;
        setHourlyWage(w);
        setHours(h);
    }
    
    void setHourlyWage(double w) {
        if (w > 0)
            hourlyWage = w;
        else
            hourlyWage = 0;
    }
    
    void setHours(double h) {
        if ( 0 <= h && h < 168)
            hours = h;
        else
            hours = 0;
    }
    public String getName() {
     return name;
 }    
    public double earnings() {
        return hourlyWage * hours;
    }
    public String toString() {
        return "Hourly worker: " + getName();
    }
}

class CommissionWorker implements Employee {
    private double salary;
    private double commission;
    private double totalSales;
    private String name;
    public CommissionWorker(String name, 
            double salary, double commission, double totalSales) {  
        this.name = name;
        setSalary(salary);
        setCommission(commission);
        setTotalSales(totalSales);
    }
    void setSalary(double s) {
        if( s > 0)
            salary = s;
        else
            salary = 0;
    }  
    void setCommission(double c) {
        if ( c > 0)
            commission = c;
        else
            commission = 0;
    }
    void setTotalSales(double ts) {
        if (ts > 0 )
            totalSales = ts;
        else
            totalSales = 0;
    }
    public String getName() {
     return name;
 }
    public double earnings() {
        return salary + commission/100*totalSales;
    }  
    public String toString() {
        return "Commission worker:"
            + getName();
    }
}

class EmployeeTest {
    public static void main(String[] args) {
        java.util.List list = new ArrayList();
        list.add(new Manager("Bill", 800.00));
        list.add(new CommissionWorker("Newt", 400.0, 3.75, 159.99));
        list.add(new PieceWorker("Al", 2.5, 200));
        list.add(new HourlyWorker("Babara", 13.75, 40));
        list.add(new Manager("Peter", 1200.00));
        list.add(new CommissionWorker("Margret", 600.0,5.5, 200.25));
        list.add(new PieceWorker("Mark", 4.5, 333));
        list.add(new HourlyWorker("William", 31.25, 50));
    
  System.out.println("Use built-in iterator:");
  Iterator iterator = list.iterator();
  while(iterator.hasNext()) {
      Employee em = (Employee)iterator.next();
      System.out.print(em + " earns $");
   System.out.println(em.earnings());
  }
 }
}
%java EmployeeTest
Use built-in iterator:
Manager: Bill earns $800.0
Commission worker:Newt earns $405.999625
Piece worker: Al earns $500.0
Hourly worker: Babara earns $550.0
Manager: Peter earns $1200.0
Commission worker:Margret earns $611.01375
Piece worker: Mark earns $1498.5
Hourly worker: William earns $1562.5
The above example also shows a dynamic binding feature which is popular in Object-Oriented realm.
If you want to pick up a specific object from the aggregated list, you may use the following code.
while(iterator.hasNext()) {
 Employee em = (Employee)iterator.next();
 if (em instanceof Manager) {
    System.out.print(em + " earns $");
    System.out.println(em.earnings());
 }
}
The above list can also be replaced by an array and achieve the same result.

Interpreter Pattern

The Interpreter Pattern is a design pattern that defines a grammatical representation for a language along with an interpreter to interpret sentences in the language. The best example of an interpreted language is Java itself, which converts the English-written code to a byte code format, so that all the operating systems can understand it.
The UML class diagram of Interpreter design pattern can be shown as:

UML Class Diagram


In the given diagram, An abstract base class specifies the method interpret(). Each concrete subclass implements interpret() by accepting (as an argument) the current state of the language stream, and adding its contribution to the problem solving process. To make this thing clear, let’s take an example that can take the Sa, Re, Ga, Ma etc and produce the sounds for the frequencies. The “musical notes” is an Interpreted Language. The musicians read the notes, interpret them according to “Sa, Re, Ga, Ma…” or “Do, Re, Me… “, etc. For Sa, the frequency is 256 Hz, similarly, for Re, it is 288Hz and for Ga, it is 320 Hz and so on. In this case, we need these values set somewhere, so that when the system encounters any one of these messages, the related frequency can be sent to the instrument for playing the frequency. We can have it at one of the two places, one is a constants file, “token=value” and the other one being in a properties file. The properties file can give us more flexibility to change it later if required. This is how a properties file will look like: MusicalNotes.properties Sa=256
Re=288
Ga=320
Ma=352 . . . . .
After that we make a class NotesInterpreter.java to take an input from the key pressed by user and set those value as a global value. Then we make a method getFrequency for getting the frequency for the note input by the user e.g. if user enter Re, it will return 288.
NotesInterpreter.java

package bahavioral.interpreter; public class NotesInterpreter {

Private Note note;

public void getNoteFromKeys(Note note) {
Frequency freq = getFrequency(note);
sendNote(freq);
}
private Frequency getFrequency(Note note) {
return freq;
}
private void sendNote(Frequency freq) {
NotesProducer producer = new NotesProducer(); producer.playSound(freq);
}
}
Here we need to make another class in which the method produces the sound wave of the frequency it gets.

NotesProducer.java
package bahavioral.interpreter;
public class NotesProducer {
Private Frequency freq;
public NotesProducer() {
this.freq = freq;
}
public void playSound(Frequency freq) {
}
}
 The above example is the simplest way to understand the concept of interpreter pattern and know how it works. In case of Interpreter pattern we need to check for grammatical mistakes, which makes it very complex. Also,
care should be taken to make the interpreter as flexible as possible, so that the implementation can be changed at later stages without having tight coupling.