Strategy pattern—SimUDuck

What’s Design patterns:

Help us structure our own applictions in ways that are easier to

understand, more maintainable and flexible.

SCENE: 

Design a duck pond simulation game, SimUDuck. 
The game can show a large variety of duck 
species swimming and making quacking sounds 
and so on. Some ducks can fly or do other 
behaviors, some not. And the executives want
to update the product every six months.

When you have to change code in your applications:

1.My customers or users decide they want something else, or they want

new functionality.

2.My company decided it is going with another database vendor and it is

also purchasing its data from another supplier that uses a different data

format. Argh! …

Design Principle:

1.Take what varies and “encapsulate” it so it won’t affect the rest of your

code. In this case, quark or not, fly or not and different ways of quacking

or flying are variable, maybe we’ll got more in future, encapsulate them

from Duck class.

2.Program to an interface, not an implementation. So we got interface

FlyBehavior and interface QuackBehavior (Maybe more).

3.Favor composition over inheritance. Creating systems using

composition gives you a lot more flexibility. Not only does it let you

encapsulate a family of algorithms into their own set of classes, but it

also lets you change behavior at runtime as long as the object

you’re composing with implements the correct behavior interface.

The Class diagram:

Code:

1. The interface (QuackBehavior.java) and the three behavior

implementation classes (Quack.java, MuteQuack.java, and Sqeak.java).

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");
    }
}

2.The  interface (FlyBehavior.java) and the two behavior

implementation classes (FlyWithWings.java and FlyNoWay.java).

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");
    }
}

3.The class Duck.java and MallardDuck.java

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {
    }

    public abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("All ducks float,even decoys !");
    }
}
public class MallardDuck extends Duck {

    public MallardDuck() {
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    public void display() {
        System.out.println("I’m a real Mallard duck");
    }
}

4.The test class MiniDuckSimulator.java.

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

5.Output:

Quack
I’m flying!!

Setting behavior dynamically

1. Add two new methods to the Duck class:

public void setFlyBehavior(FlyBehavior fb) {
    flyBehavior = fb;
}

public void setQuackBehavior(QuackBehavior qb) {
    quackBehavior = qb;
}

2.Make a new Duck type (ModelDuck.java).

public class ModelDuck extends Duck {
    public ModelDuck() {
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }

    public void display() {
        System.out.println("I'm a model duck");
    }

}

3.Make a new FlyBehavior type (FlyRocketPowered.java).

public class FlyRocketPowered implements FlyBehavior {
    public void fly() {
        System.out.println("I’m flying with a rocket!");
    }
}

4.Change the test class (MiniDuckSimulator.java), add the

ModelDuck, and make the ModelDuck rocket-enabled.

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

        Duck model = new ModelDuck();
        model.performFly();
        model.setFlyBehavior(new FlyRocketPowered());
        model.performFly();
    }
}

5.Output:

Quack
I’m flying!!
I can’t fly
I’m flying with a rocket!

Conclusion:

The Strategy Pattern defines a family of algorithms, encapsulates each

one,  and makes them interchangeable.  Strategy lets the algorithm vary

independently from clients that use it.

Leave a Reply

Your email address will not be published. Required fields are marked *