定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
1. 实例描述
给客户开发一款模拟鸭子游戏,游戏中会出现各种鸭子,所有的鸭子都会都会游泳,但不同鸭子外观不一样,并且有的鸭子不会叫,有的会叫且叫声不同,有的鸭子不会飞有的会飞且飞的方式不一样。在这个过程中会增加新的鸭子种类,同一种鸭子叫的方式和飞行方式可能发生改变。
2. 分析思路
首先创建所有的鸭子的基类(Duck),不同的鸭子(MallarDuck,RedHeadDuck,RubberDuch,DecoyDuck,ModelDuck)都是该基类的实现类。因所有鸭子都会游泳,在基类就定义并实现游泳方法(swin)。每个鸭子都有外观(display),外观不会改变,所以将外观方法定义为抽象方法,在具体子类里面去实现。不同鸭子的叫声(Quack)和飞行方式(Fly)不一样,而且可能发生改变,所以将这两种行为都抽象为两个接口(QuackBehavior,FlyBehavior),并且每个接口有不同的实现方法(Quack,Squeak,MuteQuack,FakeQuack;FlyNoWay,FlyWithWings,FlyRocketPowered)。在鸭子基类里面定义有以这两个接口为成员变量的属性(FlyBehavior flyBehavior;QuackBehavior quackBehavior;)且提供更改方式(setFlyBehavior (FlyBehavior fb);setQuackBehavior(QuackBehavior qb)),不同鸭子在创建时(构造方法里)可以定义这两个字段的具体实现类,并且可以改变该属性。
3.类图实现:
客户:可以使用下面封装好的算法族
算法族1:封装飞行行为
算法族2:封装呱呱叫行为
4. 代码实现:
Duck:所有鸭子的基类
package headFirst.designPatterns.day01_strategy;
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public void setFlyBehavior (FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
MallardDuck:鸭子实现类1
package headFirst.designPatterns.day01_strategy;
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");
}
}
RedHeadDuck:鸭子实现类2
package headFirst.designPatterns.day01_strategy;
public class RedHeadDuck extends Duck {
public RedHeadDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a real Red Headed duck");
}
}
RubberDuck:鸭子实现类3
package headFirst.designPatterns.day01_strategy;
public class RubberDuck extends Duck {
public RubberDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Squeak();
}
public void display() {
System.out.println("I'm a rubber duckie");
}
}
DecoyDuck:鸭子实现类4
package headFirst.designPatterns.day01_strategy;
public class DecoyDuck extends Duck {
public DecoyDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new MuteQuack());
}
public void display() {
System.out.println("I'm a duck Decoy");
}
}
ModelDuck:鸭子实现类5
package headFirst.designPatterns.day01_strategy;
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
FlyBehavior:封装飞行行为的接口
package headFirst.designPatterns.day01_strategy;
public interface FlyBehavior {
public void fly();
}
FlyNoWay:飞行方式1
package headFirst.designPatterns.day01_strategy;
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
FlyWithWings:飞行方式2
package headFirst.designPatterns.day01_strategy;
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
FlyRocketPowered:飞行方式3
package headFirst.designPatterns.day01_strategy;
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
QuackBehavior:封装呱呱叫的接口
package headFirst.designPatterns.day01_strategy;
public interface QuackBehavior {
public void quack();
}
Quack:呱呱叫方式1
package headFirst.designPatterns.day01_strategy;
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
Squeak:呱呱叫方式2
package headFirst.designPatterns.day01_strategy;
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}
MuteQuack:呱呱叫方式3
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence >>");
}
}
FakeQuack:呱呱叫方式4
package headFirst.designPatterns.day01_strategy;
public class FakeQuack implements QuackBehavior {
public void quack() {
System.out.println("Qwak");
}
}
5.模拟运行
MiniDuckSimulator:
package headFirst.designPatterns.day01_strategy;
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
RubberDuck rubberDuckie = new RubberDuck();
DecoyDuck decoy = new DecoyDuck();
ModelDuck model = new ModelDuck();
mallard.performQuack();
rubberDuckie.performQuack();
decoy.performQuack();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
Result:
Quack
Squeak
<< Silence >>
I can't fly
I'm flying with a rocket
MiniDuckSimulator1:
package headFirst.designPatterns.day01_strategy;
public class MiniDuckSimulator1 {
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();
}
}
Result:
Quack
I'm flying!!
I can't fly
I'm flying with a rocket