目录
一、策略模式的定义
定义:策略模式定义了算法族,分别封装起来,让他们之间可以相互调换,此模式让算法的变化独立于使用算法的客户。UML结构图如下所示:
其中,Context是上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。
二、策略模式的特点及优缺点
策略模式体现了面向对象程序设计中非常重要的三个原则:
① 封装变化;②多用组合,少用继承;③针对接口编程,不针对实现编程。
优点:
1、提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点:
1、因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量
2、Strategy和Context之间的通信开销增大。根据算法的需要,Context必须向每个不同的具体Strategy类实例传递不同的参 数。导致Context会创建和传递一些永远用不到的参数。
三、策略模式的应用场景和实例
(1)应用场景:
- 多个类只有算法或行为上稍有不同的场景
- 算法需要自由切换的场景
- 需要屏蔽算法规则的场景
(2)实例:
- 出行方式,自行车、汽车等,每一种出行方式都是一个策略
- 商场促销方式,打折、满减等
- Java AWT中的LayoutManager,即布局管理器
四、策略模式的实现
下面就以模拟鸭子游戏为例使用策略模式实现模拟鸭子应用。UML结构图如下:
(1)鸭子抽象类
抽象类,抽象出display()方法让子类去实现。
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!");
}
}
(2)飞行行为接口
声明为接口类型,每个鸭子对象都会动态设置这些变量以便在运行时引用正确的飞行行为类型。
public interface FlyBehavior {
public void fly();
}
(3)鸣叫行为接口
声明为接口类型,每个鸭子对象都会动态设置这些变量以便在运行时引用正确的鸣叫行为类型。
public interface QuackBehavior {
public void quack();
}
(4)具体的鸭子子类
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");
}
}
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");
}
}
public class RubberDuck extends Duck {
public RubberDuck() {
flyBehavior = new FlyNoWay();
//quackBehavior = new Squeak();
quackBehavior = () -> System.out.println("Squeak");
}
public RubberDuck(FlyBehavior flyBehavior, QuackBehavior quackBehavior) {
this.flyBehavior = flyBehavior;
this.quackBehavior = quackBehavior;
}
public void display() {
System.out.println("I'm a rubber duckie");
}
}
public class DecoyDuck extends Duck {
public DecoyDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new MuteQuack());
}
public void display() {
System.out.println("I'm a duck Decoy");
}
}
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
(5)飞行行为实现类
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
(6)鸣叫行为实现类
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence >>");
}
}
public class FakeQuack implements QuackBehavior {
public void quack() {
System.out.println("Qwak");
}
}
(7)测试
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
FlyBehavior cantFly = () -> System.out.println("I can't fly");
QuackBehavior squeak = () -> System.out.println("Squeak");
RubberDuck rubberDuckie = new RubberDuck(cantFly, squeak);
DecoyDuck decoy = new DecoyDuck();
Duck model = new ModelDuck();
mallard.performQuack();
rubberDuckie.performQuack();
decoy.performQuack();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
运行结果:
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();
}
}
运行结果: