概述
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变换独立于使用算法的客户。
涉及到的设计原则
- 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
- 针对接口编程,而不是针对实现编程。
- 多用组合,少用继承。
UML
- Context:上下文角色,负责封装,屏蔽策略。
- Strategy:抽象策略接口。
- ConcreteStrategy:实现具体算法。
类似代理模式,只是没有共同接口。
优劣简述
优点:
- 算法自由切换,避免封装类多重条件判断,由高层决定。
- 符合开闭原则,扩展性好
缺点:
- 策略类数量多,无法复用。
场景:
- 多个类只在算法或行为上稍有不同。
- 算法需要自由切换。
- 算法需要屏蔽。
代码实现
多种鸭子有多种行为。
接口类及其实现类
我们把鸭子的不同行为抽象出来,比如飞的行为,但是飞有很多种,我们使用多态来实现。同时鸭子会叫,不同鸭子叫的方式可能不同,我们将使用多态来实现不同的叫声。那么至少应该有FlyBehavior和QuackBehavior两个接口。
FlyBehavior.java
public interface FlyBehavior {
public void fly();
}
FlyNoWay.java
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly.");
}
}
FlyWithWings.java
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying...");
}
}
FlyRocketPowered.java
public class FlyRocketPowered implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I'm flying with a rocket...");
}
}
QuackBehavior.java
public interface QuackBehavior {
public void quack();
}
Quack.java
public class Quack implements QuackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Quack...");
}
}
Squeak.java
public class Squeak implements QuackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Squeak...");
}
}
MuteQuack.java
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("<< Silence >>");
}
}
抽象类及其子类
假设所有的鸭子会游泳,会不同的鸣叫和飞。假设它们游泳的方式都是一样的,只有鸣叫和飞的行为不一样,这样我们就可以在抽象类中实现一样的动作,不去实现不一样的行为。以后不同鸭子只需要继承这个父类鸭子即可。
Duck.java
public abstract class Duck {
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public abstract void disPlay();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void swim(){
System.out.println("Swimming...");
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
ModelDuck.java
public class ModelDuck extends Duck{
public ModelDuck(){
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public void disPlay() {
// TODO Auto-generated method stub
System.out.println("I'm a ModelDuck...");
}
}
MallardDuck.java
public class MallardDuck extends Duck{
public MallardDuck(){
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void disPlay() {
// TODO Auto-generated method stub
System.out.println("I'm a mallardDuck.");
}
}
Duck2.java
public class Duck2 extends Duck{
public Duck2(){
flyBehavior = new FlyNoWay();
quackBehavior = new Squeak();
}
@Override
public void disPlay() {
// TODO Auto-generated method stub
System.out.println("I'm duck2...");
}
}
使用
MiniDuckSimulator.java
public class MiniDuckSimulator {
public static void main(String[] args) {
Duck duck = new MallardDuck();
duck.performFly();
duck.performQuack();
Duck duck2 = new Duck2();
duck2.performFly();
duck2.performQuack();
Duck duck3 = new ModelDuck();
duck3.performFly();
duck3.performQuack();
duck3.setFlyBehavior(new FlyRocketPowered());
duck3.performFly();
}
}