CSC/ECE 517 Fall 2012/ch1b 2w41 dc

From PG_Wiki
Jump to: navigation, search

State pattern and the related patterns

The State pattern allows an object to completely change its behavior and the change depends on its current internal state. Alternatively, a monolithic object's behavior is a function of its state, and it must change its behavior at run-time depending on that state. State pattern is closely related to Strategy pattern, Bridge pattern and Chain of Responsibility pattern. We shall discuss four patterns(State, Strategy, Bridge & Chain of Responsibility), their structures and differences between these patterns.

Contents


Description

In this section, all four patterns are discussed along with their structures and examples.

State Pattern

The state pattern is behavioral as it defines how communication between classes or entities is controlled. It is used in programming to define the state of an object. This pattern, also called as object for states pattern [1], allows the class of an object to change at runtime without changing the interface used to access the object or losing the current state. This change in class is abstracted with the use of a wrapper object or context.[2]

Creating object oriented state machines is one of the uses of the state pattern. In this, the functionality of the object changes fundamentally according to its state. Using multiple concrete classes, each class inheriting from the same base class is an alternative to multiple number of 'if' or 'switch' statements.

Structure

Following is the general structure of state pattern[3]:

State structure 1.jpg

Examples

Alarm state.PNG

package patterncraft.state {
    public interface IState {
        function engage():void;
    }
}
package patterncraft.state {

    public class FooState implements IState{
        private var main:Main;
        public function FooState(main:Main) {
            this.main = main;
        }
    
        public function engage():void{
            main.sayFoo()
            
        }
    }
}

package patterncraft.state {

    public class BarState implements IState{
        private var main:Main;
        public function BarState(main:Main) {
            this.main = main;
        }
    
        public function engage():void{
            main.sayBar();
        }
    }
}

package {
    
    import flash.display.Sprite;
    
    import patterncraft.state.IState
    import patterncraft.state.FooState;
    import patterncraft.state.BarState;
    
    public class Main extends Sprite {
        public function Main() {
            var state:IState = new FooState(this);
            state.engage();
            
            state = new BarState(this);
            state.engage();
        }
        
        public function sayFoo():void {
        trace("foo")
        }
        
        public function sayBar():void {
        trace("bar")
        }
    }
}

We see that the engage method is called for each of the instance of FooState and BarState. These instances have been created using the instance of the Main class which is calling these methods inside it. As from the example we see that this pattern allows an object to alter its behavior using a context (here ‘Main’ class) when its state (here ‘state’ object) changes.

Strategy Pattern

Strategy pattern allows a set of similar algorithms to be defined and encapsulated in their own classes. This pattern is used to create multiple interchangeable family of algorithms and a specific algorithm can be selected at run time according to the configuration details or user preferences. It increases flexibility as new algorithms can be added easily.

Structure

Following is the general structure of Strategy pattern:[5]

Strategy structure.PNG

Examples

package patterncraft.strategy {
    public interface IStrategy {
        function engage():void;
    }
}

package patterncraft.strategy {
    public class Container {
        public var engageBehavior:IStrategy;
        public function Container() {
        }
    
        public function engage():void {
            engageBehavior.engage();
        }
    }
}

package patterncraft.strategy {
    public class FooStrategy implements IStrategy {
        private var container:Container;
        public function FooStrategy(container:Container) {
            this.container = container;
        }
        
        public function engage():void {
            trace("foo")
        }
    }
}

package patterncraft.strategy {
    public class BarStrategy implements IStrategy {
        private var container:Container;
        public function BarStrategy(container:Container) {
            this.container = container;
        }
    
        public function engage():void {
            trace("bar")
        }
    }
}

package {
    import flash.display.Sprite;
    import patterncraft.strategy.Container;
    import patterncraft.strategy.IStrategy;
    import patterncraft.strategy.FooStrategy;
    import patterncraft.strategy.BarStrategy;

    public class Main extends Sprite {
        public function Main() {
            var container:Container = new Container();
            
            var strategy:IStrategy = new FooStrategy(container);
            container.engageBehavior = strategy;
            container.engage();
            
            container.engageBehavior = new BarStrategy(container);
            container.engage();
        }        
    }
}

The algorithm for each strategy is encapsulated in each of the two classes. Container is a context that switches between strategies FooStrategy and BarStrategy using the engageBehavior method. It is clear that State is similar to Strategy, just that the intent of each of these patterns is different as has been discussed already.

Bridge Pattern

Bridge pattern separates abstract elements of a class from its implementation. This can be used to achieve cleaner implementation of real world objects and it allows easy changes in implementation. For instance, business logic of an element can be the abstract elements of a class which can be created independent of the implementation details of their data access. This makes the business logic independent of databases etc.

Unlike State pattern, Bridge pattern is structural as it defines how relationships can be created between classes or entities.

Structure

Following is the general structure of Bridge pattern:[6]

Bridge structure.PNG

Examples

package patterncraft.bridge {
    public interface IBridge {
        function engage():void;
    }
}
package patterncraft.bridge {

    public class FooBridge implements IBridge{
        public function FooBridge() {
        }
    
        public function engage():void{
            trace("foo")
        }
    }
}

package patterncraft.bridge {

    public class BarBridge implements IBridge{
        public function BarBridge() {
        }
    
        public function engage():void{
            trace("bar")
        }
    }
}

package {
    import flash.display.Sprite;

    import patterncraft.bridge.IBridge;
    import patterncraft.bridge.FooBridge;
    import patterncraft.bridge.BarBridge;
    
    public class Main extends Sprite {
        public function Main() {
            var bridge:IBridge = new FooBridge();
            bridge.engage();
            
            bridge = new BarBridge();
            bridge.engage();
        }
    }
}

Each of these two classes implement the IBridge interface. engage() method is called on instances of both the objects and each of them has a different implementation of the method. We see that these method calls are independent to each other and the main method from which they are being called.

Chain of Responsibility Pattern

Chain of Responsibility pattern helps decouple the sender of a request and receiver of a request in a chain of multiple handler objects. When a system receives a request, only one handler object from its chain of handlers can process the request. If the object however cannot serve the request then it will determine the next handler object in the chain of responsibility and push the request forward in the chain. In the chain of handler objects, the responsibility of determining who to serve the request is left to the objects participating in the chain.[7]

Structure

Following is the general structure of Chain of Responsibility:[8]

Cor structure.JPG

Examples

Exception Handling in Java uses chain of responsibility in deciding how to handle an exception. A sequence of exceptions is listed in catch statements and when there is an exception thrown, this list is scanned one by one from top. If a catch statement can handle the exception then the job is done, otherwise it is passed to the next catch block and so on until it reaches the finally block.

Comparison

The State, Bridge and Strategy patterns provide similar solution structures. But the intent of each of these patterns is different and hence solve different problems. The major differences between each of the patterns have been discussed:

State Pattern and Bridge Pattern

The structure of State and Bridge is identical and the only difference lies in how they address these problems.

State Pattern and Strategy Pattern

Following are the differences between State and Strategy patterns:

Bridge Pattern and Strategy Pattern

Following are the differences between Bridge and Strategy patterns:

State Pattern and Chain of Responsibility Pattern

State pattern can be combined with Chain of Responsibility when one or the other has already been applied in a system. The two patterns can be used as larger building blocks in design, thus raising the abstraction level. The state design pattern can be organized in a chain of responsibility.

Cor state.JPG

Conclusion

The State, Strategy and Bridge patterns belong to different classes of design patterns. Bridge is a structural design pattern and State and Strategy are behavioral design patterns. Different design patterns can be combined for designing of important abstractions of the application domain. Since the three patterns primarily discussed here solve similar kinds of problems, understanding the complex relationships between them will help in applying a specific pattern or a combination of patterns. No pattern has advantages over using another, but the intent of the pattern should be capable of providing a fitting solution to the problem.

References

  1. http://en.wikipedia.org/wiki/State_pattern
  2. http://www.blackwasp.co.uk/State.aspx
  3. http://www.cs.umd.edu/class/fall2002/cmsc433-0101/Lectures/designPatterns2.pdf
  4. http://mypages.valdosta.edu/dgibson/courses/cs4322/Lessons/State/stateNotes.pdf
  5. http://www.blackwasp.co.uk/Strategy.aspx
  6. http://www.blackwasp.co.uk/Bridge.aspx
  7. http://tinyurl.com/brkg9py
  8. http://www.dofactory.com/Patterns/PatternChain.aspx

See Also

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox