Monday 24 May 2010

Strategy Pattern



The Strategy Pattern defines a family of algorithms, encapsulates each one and makes the interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Design Principles
1.Identify the aspects of your application that vary and separate them from what stays the same.
2. Program to an interface, not an implementation.
3. Favor composition over inheritance (HAS-A can be better than IS-A).

Requirements:
SimUDuck Application: This is a duck pond simulation game. The game can show a large variety of duck species swimming and making quacking sounds.

Design:
The initial designers of the system used slandered OO techniques and created one Duck super class from which all other duck types inherit.

Problem faced:
It is becoming hard to manage the code when some new spec added. Client change or add new types of duck to the app. But to manage that we need to change all code from super class to sub class. There are some methods which does not have any effect of some class that also inherit to other class because of inheritance. Look at the figure 2. So here we go for Strategy Pattern.

Strategy Pattern:
According to design principle one describe above:
Take the parts that vary and encapsulate them, so that later you can alter or extend the parts that vary without affecting those don't.

We know that fly() and quack() are the parts of the Duck class that vary across ducks. To separate these behaviors from the Duck class, we'll pull both methods out of the Duck class and create a new set of classes to represent behavior. With our new design the duck subclass will will use a behavior represent by an interface (FlyBehavior and QuackBehavior) so the actual implementation of the behavior won't be locked into the Duck subclass.

According to design principle 2 describe above.
Programming to an implementation:

Dog d = new Dog();
d.bark();

Declaring the variable d as type Dog (a concrete implementation of animal) forces us to code to a concrete implementation.

Programming to an interface/supertype:

Animal animal = new Dog();
animal.makesound();

We know its a Dog but we can use the animal reference polymorphically. Look at the figure 1

FlyBehavior and QuackBehavior will change as per spec change so we have encapsulate them. If any new behavior comes we can just add that without editing the existing code. According to class diagram we can now write down the code as below:

// Duck super class.
public abstract class Duck
{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck()
{
}
public abstract void display();
public void performFly()
{
flyBehavior.fly(); // Delegates to the behavior class.
}
public void performQuack()
{
quackBehavior.fly(); // Delegates to the behavior class.
}
public void swim()
{
System.out.println("All ducks float, even decoys!");
}
}

// Giving one subclass example here.
public class MallardDuck extends Duck
{
public MarllardDuck()
{
quackBehavior = new Quack(); // It use Quack class to handle its quack, so when performQuack is called, the responsibility for the quack is delegated to the Quack object and we get a real quack.

flyBehavior = new FlyWithWings();
}
public void display()
{
System.out.println("I'm a real Mallard duck");
}
}

// Interface and its implemented class.

public interface FlyBehavior
{
public void fly();
}
public class FlyWithWings implements FlyBehavior
{
public void fly()
{
System.out.println("I'm flying");
}
}
public class FlyNoWay implements FlyBehavior
{
public void fly()
{
System.out.println("I can't fly");
}
}

// Interface and its implemented class.

public interface QuackBehavior
{
public void quack();
}
public class Quack implements QuackBehavior
{
public void quack()
{
System.out.println("Quack");
}
}
public class MuteQuack implements QuackBehavior
{
public void quack()
{
System.out.println("Silence");
}
}
public class Squeak implements QuackBehavior
{
public void quack()
{
System.out.println("Squeak");
}
}

// Main method declaration

public class MiniDuckSimulator
{
public static void main(String[] args)
{
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard .performFly();
}
}

No comments:

Post a Comment