Saturday, October 31, 2009

Chapter 8: Behavioral Patterns




















Chapter 8 -
Behavioral Patterns
Patterns in Java, Volume 1: A Catalog of Reusable Design Patterns Illustrated with UML, Second Edition
by Mark Grand
John Wiley & Sons � 2002


























Chapter 8: Behavioral Patterns



The patterns in this chapter are used to organize, manage, and combine behavior.




Chain of Responsibility



This pattern was previously described in [GoF95].




Synopsis


The Chain of Responsibility pattern allows an object to send a command without knowing what object or objects will receive it. It accomplishes this by passing the command to a chain of objects that is typically part of a larger structure. Each object in the chain may handle the command, pass the command on to the next object in the chain, or do both.






Context


Suppose that you are writing software to monitor a security system. Physically, the security system consists of sensing devices (motion detectors, smoke detectors, etc.) that transmit status information to a computer. The computer’s job is to log all status information, maintain a display showing current status information, and transmit alarms in the event of an emergency.


One of the goals for the monitoring software is that it should be highly scalable. It should be able to work for a small retail store, an office building, a warehouse, or a multi-building complex. That goal has implications for the way that you design the monitoring software.


To keep things simple, your monitoring program should instantiate an object for every sensor it is to monitor. This provides a simple way to model each sensor’s state. To ensure scalability, an object responsible for an individual sensor should not assume anything about its environment, except that it is at the bottom level of a hierarchical organization.


The organization will include objects corresponding to real-world things such as rooms, areas, floors, and buildings. Directly modeling the real world provides a straightforward way to display the status of different parts of buildings. It also allows the interpretation of a sensor’s state to be based on its environment. For example, if the temperature of a closed room exceeds 180°F, then you may want the fire sprinklers in just that room to turn on. If the temperature in an open area of a warehouse exceeds 150°F, you may want to turn on the fire sprinklers over that area and the adjacent areas. On the other hand, if the temperature in a freezer exceeds 30°F, you may want to sound an alarm to let people know that that freezer is getting too warm.


In all these cases, the object that models a sensor does not decide what to do with the state of the sensor. Instead, it delegates that decision to an object at a higher level of the hierarchy that has more contextual knowledge. Such objects either decide what to do about a notification or pass it on to the object that is organizationally above it.



Figure 8.1 shows an example of objects organized in this hierarchical way.






Figure 8.1: Physical security object organization

For example, when a TemperatureSensor object contained in an area of a warehouse receives a notification of the current temperature from the physical sensor, it passes that notification to the Area object that contains it. Rather than decide the significance of the temperature, it passes the notification to the Warehouse object that contains the Area object. The Warehouse object determines the meaning of the temperature. If the temperature is above 150°F, the Warehouse object decides that there is a fire. It turns on the sprinklers in the area that notified it and the surrounding areas. The Warehouse object does not pass on the temperature notification.







Forces




















J



You want an object to be able to send a command to another object without specifying the receiver. The sending object does not care which object handles the command, only that an object will receive the command and handle it.




J



You want the receivers of a command to be able to handle the command without having to know anything about the object that sent the command.




J



More than one object may be able to receive and handle a command, so you need a way to prioritize among the receivers without the sending object knowing anything about them.




J



The objects you may want to potentially handle commands are organized into a structure that can serve to prioritize among the potential handlers of a command.








Solution



Figure 8.2 presents a class diagram that shows the organization of the Chain of Responsibility pattern. Following are explanations of the roles these classes play in the Chain of Responsibility pattern:






Figure 8.2: Chain of Responsibility pattern.


CommandSender.  Instances of a class in this role send commands to the first object in a chain of objects that may handle the command. They send a command by calling the first CommandHandlerIF object’s postCommand method.



CommandHandlerIF.  All objects in a chain of objects that may handle a command must implement an interface in this role. It defines two methods.




  1. It defines a handleCommand method to handle whatever commands an implementing class is expected to handle. The handleCommand method returns true if it handled a command or false if it did not.




2. It defines a postCommand method that calls the handleCommand method. If the handleCommand method returns false and there is a next object in the chain, it calls the object’s postCommand method. If the handleCommand method returns true, it means there is no need to pass the command on to the next object in the chain.



AbstractCommandHandler.  Classes in this role are abstract classes that implement the postCommand method. The purpose of this is to provide the convenience of a common implementation of postCommand for classes in the ConcreteCommandHandler role. It is very unusual for classes to want anything other than the default logic for the postCommand method. Classes in the CommandSender role should refer to objects in a chain of responsibility only through the CommandHandlerIF interface and not as instances of the AbstractCommandHandler class. The AbstractCommandHandler class is an implementation detail. Though unusual, it is possible to have classes that implement the CommandHandlerIF interface that are not subclasses of the AbstractCommandHandler class.



ConcreteCommandHandler1, ConcreteCommandHandler2, and so on.  Instances of classes in this role are objects in a chain of objects that can handle commands.


Typically, CommandHandler objects are part of a larger structure. This is the case in the example shown in Figure 8.1.






Implementation


In many cases, the objects that constitute a chain of responsibility are part of a larger structure, and the chain of responsibility is formed through some links of that larger structure. When links to form a chain of responsibility do not already exist, you must add instance variables and access methods to the classes to create links that form a chain of responsibility.


A decision to make, whenever implementing the Chain of Responsi bil ity pattern, is how you will pass commands to and through the chain of objects. There are two basic ways to do it. One way is to encapsulate each kind of command in a single object that can be passed to a single postCommand method. The other way is to have as many different types of postCommand and handleCommand methods as there are different types of information associated with commands.


Passing commands in a single object is often the better choice. It incurs the cost of object creation but minimizes the cost of passing parameters to the methods of the next object in the chain. That minimizes the cost of propagating a command through a chain of objects. Passing commands in a single object usually results in less code.


On the other hand, passing the information that constitutes a command through separate parameters saves the cost of object creation at the cost of additional parameter passing. If you know that the chain of objects will be short, passing a command as multiple parameters can be the better choice.






Consequences




















J



The Chain of Responsibility pattern reduces coupling between the object that sends a command and the object that handles the command. The sender of a command does not need to know what object will actually handle the command. It merely needs to be able to send the command to the object that is at the head of the chain of responsibility.




J



The Chain of Responsibility pattern allows flexibility in deciding how to handle commands. Decisions about which object will handle a command can be varied by changing which objects are in the chain of responsibility or changing the order of the objects in the chain of responsibility.




l



The Chain of Responsibility pattern does not guarantee that every command will be handled. Commands that are not handled are ignored.




J



If the number of objects in a chain becomes large, there can be efficiency concerns about the amount of time that it takes a command to propagate through the chain. A high percentage of commands that are not handled exacerbates the problem because commands that are not handled are propagated through the full length of the chain.








Java API Usage



Version 1.0 of Java used the Chain of Command pattern to handle user- interface events. That event-handling scheme used a user interface’s container hierarchy as a chain of responsibility. When an event was posted to a button or other GUI component, it would either handle the event or post it to its container. Though it was usable, there were enough problems that the creators of Java took the drastic step of changing Java’s event model. The two most serious problems related to efficiency and flexibility are as follows:














l



Some platforms generate many events that most GUIs do not handle or have any interest in. One such event is MOUSE_MOVE. It may be generated every time a mouse moves just one pixel. Some programs that were built using the original event model visibly slowed down whenever there was rapid mouse movement because they spent so much time passing MOUSE_MOVE events that were never handled through the container hierarchy.




l



The Chain of Responsibility pattern assumes that all the objects that can handle a command are instances of a common superclass or implement a common interface. This limits a program to posting commands to instances of that common superclass or interface. Java’s original event model required that every object that could handle an event was an instance of the common superclass Component. This meant that it was impossible to deliver events directly to non-GUI objects, since only GUI objects are instances of Component.




This second problem is actually an advantage for some applications. The Chain of Responsibility pattern makes it less convenient to deliver commands to objects that are not part of the chain of handlers. For some applications, delivering a command to an object outside the chain of handlers is most likely a bug. The physical security example discussed under the Context heading is an example of such an application. For applications such as this, using the Chain of Responsibility pattern will result in fewer opportunities to introduce bugs into the application than will be using the delegation event model.


Another advantage that the Chain of Responsibility has over the delegation event model is that it allows you to explicitly control the order in which commands are delivered to handlers.






Code Example


Continuing the physical security example, Figure 8.3 shows the classes used in the physical security example.








In Figure 8.3, the classes that extend the Sensor class call the notify method they inherit from it to report a measurement to the object that is responsible for handling its measurements. Classes that extend the AbstractSecurityZone class are responsible for handling measurements from the appropriate kind of Sensor object.






Figure 8.3: Physical security classes.


The following is some code for the classes shown in Figure 8.3. First, here is code for the TemperatureSensor class. Notice that the TemperatureSensor class does nothing with a reading from a temperature sensor but pass it on.




class TemperatureSensor extends Sensor {
    private SecurityZone zone;
...
/**
* When the temperature sensor associated with this object
* observes a different temperature this method is called.
*/
void notify(int measurement) {
zone.notify(measurement, this);
} // notify(int)
} // class TemperatureSensor


All of the classes that model security zones implement that SecurityZoneIF interface:




public interface SecurityZoneIF {
/**
* This method is called to notify this security zone of a
* change in a sensor measurement.
*/
    public void notify(int measurement, Sensor source) ;

/**
* This method is called by a child zone to report a fire.
*/
    public void fireAlarm(SecurityZone zone) ;
}  // interface SecurityZoneIF


Here is the code for the SecurityZone class, which is the superclass of all of the classes that form the chains of responsibility in this example:



abstract class SecurityZone implements SecurityZoneIF { 
    private SecurityZone parent;
...
/**
* Return this object's parent zone.
*/
    SecurityZone getParent() {
        return parent;
} // getParent()

/**
* Call this method to notify this zone of a new sensor
* measurement.
*/
    public void notify(int measurement, Sensor sensor) {
        if (!handleNotification(measurement, sensor)
              && parent != null) {
            parent.notify(measurement, sensor);
} // if
} // notify(int, Sensor)

/**
* This method is called by the notify method so that
* this object can have a chance to handle measurements.
*/
    protected
    abstract boolean handleNotification(int measurement,
                                        Sensor sensor);
/**
* This method is called by a child zone to report a fire.
* It is expected that the child zone has turned on
* sprinklers or taken other measures to control the fire
* within the child zone. The purpose of this method is to
* be overridden by subclasses so it can take any
* necessary actions outside of the child zone.
*/
    public void fireAlarm(SecurityZone zone) {
// Turn on sprinklers
...
        if (parent != null)
          parent.fireAlarm(zone);
} // fireAlarm(SecurityZone)
} // class SecurityZone


Here are the subclasses of SecurityZone that were discussed under the Context heading:




class Area extends SecurityZone {
...
/**
* This method is called by the notify method so that this
* object can have a chance to handle measurements.
*/
    boolean handleNotification(int measurement,Sensor sensor){
        if (sensor instanceof TemperatureSensor) {
            if (measurement > 150) {
                fireAlarm(this);
                return true;
            }  // if
} // if
...
        return false;
} // handleNotification(int, Sensor)
} // class Area

class Warehouse extends SecurityZone {
...
/**
* This method is called by the notify method so this
* object can have a chance to handle measurements.
*/
    protected
    boolean handleNotification(int measurement,Sensor sensor){
...
        return false;
} // handleNotification(int, Sensor)

public void fireAlarm(SecurityZone zone) {
        if (zone instanceof Area) {
// Turn on sprinklers in surrounding areas
...
// Don't call super.fireAlarm because that will
// turn on sprinklers for the whole warehouse.
            if (getParent() != null)
              getParent().fireAlarm(zone);
            return;
} // if
...
        super.fireAlarm(zone);
} // fireAlarm(SecurityZone)
}  // class Warehouse






Related Patterns



Composite.  When the chain of objects used by the Chain of Responsibility pattern is part of a larger structure, the larger structure is usually built using the Composite pattern.



Command.  The Chain of Responsibility pattern makes the particular object that executes a command indefinite. The Command pattern makes the object that executes a command explicit and specific.



Template Method.  When the objects that make up a chain of responsibility are part of a larger organization built using the Composite pattern, the Template Method pattern is often used to organize the behavior of individual objects.


















No comments: