Behavioral patterns prescribe the way objects interact with each other. They help make complex behavior manageable by specifying the responsibilities of objects and the ways they communicate with each other.
The Observer Pattern:
Observer is a very common pattern. You typically use this pattern when you're implementing an application with a Model/View/Controller architecture. The Model/View part of this design is intended to decouple the presentation of data from the data itself.
Consider, for example, a case where data is kept in a database and can be displayed in multiple formats, as a table or a graph. The Observer pattern suggests that the display classes register themselves with the class responsible for maintaining the data, so they can be notified when the data changes, and so they can update their displays.
The Java API uses this pattern in the event model of its AWT/Swing classes. It also provides direct support so this pattern can be implemented for other purposes.
The Java API provides an Observable
class that can be subclassed by objects that want to be observed. Among the methodsObservable
provides are:
addObserver(Observer o)
is called by Observable
objects to register themselves.setChanged()
marks the Observable
object as having changed.hasChanged()
tests if the Observable
object has changed.notifyObservers()
notifies all observers if the Observable
object has changed, according to hasChanged()
. To go along with this, an Observer
interface is provided, containing a single method that is called by an Observable
object when it changes (providing the Observer
has registered itself with the Observable
class, of course):
public void update(Observable o, Object arg) |
The following example demonstrates how an Observer pattern can be used to notify a display class for a sensor such as temperature has detected a change:
import java.util.*; class Sensor extends Observable { private int temp = 68; void takeReading() { double d; d =Math.random(); if(d>0.75) { temp++; setChanged(); } else if (d<0.25) { temp--; setChanged(); } System.out.print("[Temp: " + temp + "]"); } public int getReading() { return temp; } } public class Display implements Observer { public void update(Observable o, Object arg) { System.out.print("New Temp: " + ((Sensor) o).getReading()); } public static void main(String []ac) { Sensor sensor = new Sensor(); Display display = new Display(); // register observer with observable class sensor.addObserver(display); // Simulate measuring temp over time for(int i=0; i < 20; i++) { sensor.takeReading(); sensor.notifyObservers(); System.out.println(); } } } |
The Strategy and Template patterns:
Strategy and Template patterns are similar in that they allow different implementations for a fixed set of behaviors. Their intents are different, however.
Strategy is used to allow different implementations of an algorithm, or operation, to be selected dynamically at run time. Typically, any common behavior is implemented in an abstract class and concrete subclasses provide the behavior that differs. The client is generally aware of the different strategies that are available and can choose between them.
For example, an abstract class, Sensor
, could define taking measurements and concrete subclasses would be required to implement different techniques: one might provide a running average, another might provide an instantaneous measurement, and yet another might hold a peak (or low) value for some period of time.
The intention of the Template pattern is not to allow behavior to be implemented in different ways, as in Strategy, but rather to ensure that certain behaviors are implemented. In other words, where the focus of Strategy is to allow variety, the focus of Template is to enforce consistency.
The Template pattern is implemented as an abstract class and it is often used to provide a blueprint or an outline for concrete subclasses. Sometimes this is used to implement hooks in a system, such as an application framework.