第1章:策略模式

1 策略模式

策略模式定义了算法族分别封装起来,让他们之间可以相互替换(实现接口),此模式让算法的变化独立于使用算法的客户(组合+委托)

1.1 应用场景

需要方法的实现独立于客户端代码,即保证客户端代码不变前提下,方法具体执行内容可以任意更换

Duck mallardDuck = new MallardDuck();
//下方代码后,该语句的调用产生不同的结果,即算法间的相互替换
mallardDuck.setFlyBehavior(new FlyNoWay());
mallardDuck.performFly();

1.2 错误解决方案

1.2.1 父类中直接增加方法
package strategy.pattern;

public abstract class Duck1 {
    //组合解决的问题
    //1.所有Duck1中,不会飞或不是quack这么叫的鸭子,都需要重写下面方法,这样重复代码太多,不利于维护
    
    //策略模式解决的问题
    //2.客户端调用同一个类型的子类对象的该方法结果是固定的,例如创建一个Duck1子类,该对象无法完成一会可以飞,一会不能飞
    public void fly(){
        System.out.println("I can fly");
    }
    public void quack(){
        System.out.println("quack");
    }
}
1.2.2 不同子类实现不同包含方法的接口,并重写该方法

FlyBehavior接口中定义抽象方法fly,所有鸭子实现该接口,并重写fly方法,与上面缺点相同

1.3 解决思路

1.3.1 分开变化和不会变化的部分

==设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起==

  1. 分析该问题中,fly与quack对于不同的鸭子子类,行为是不同的,因此应该将该方法的具体实现与鸭子类本身分离开
  2. Duck2
package strategy.pattern;

public abstract class Duck2 {
    Quack quack = new Quack();
    FlyWithWings flyWithWings = new FlyWithWings();
    public void fly(){
        //具体的实现在Quack和FlyWithWings中定义,达到了和Duck2及其子类的分离
        flyWithWings.fly();
    }
    public void quack(){
        quack.quack();
    }
}
1.3.2 面向接口编程

==设计原则:针对接口编程,而不是针对实现编程==

==设计原则:多用组合少用继承==

  1. 之前无法动态地指定鸭子子类的行为,也无法为特定鸭子子类指定特定行为
  2. Duck3
package strategy.pattern;

public abstract class Duck3 {
    //1.QuackBehavior、FlyBehavior为接口,此处为面向接口编程
    //使用组合解决了继承带来的代码重复问题
    QuackBehavior quack;
    FlyBehavior flyWithWings;
    public void fly(){
        //执行的是flyWithWings变量指向的真正的对象的fly方法
        flyWithWings.fly();
    }
    public void quack(){
        quack.quack();
    }
    //2.可以指定具体行为对应类,可以动态的指定鸭子子类的行为,也可以为特定鸭子子类指定特定行为
    public void setQuack(QuackBehavior quack) {
        this.quack = quack;
    }
    public void setFlyWithWings(FlyBehavior flyWithWings) {
        this.flyWithWings = flyWithWings;
    }
}

1.4 类图

image

1.5 代码

  1. FlyBehavior:接口
package strategy.pattern;

public interface FlyBehavior {
    void fly();
}
  1. FlyNoWay:实现类
package strategy.pattern;

public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I cant fly");
    }
}
  1. FlyWithWings:实现类
package strategy.pattern;

public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I'm flying");
    }
}
  1. QuackBehavior:接口
package strategy.pattern;

public interface QuackBehavior {
    void quack();
}
  1. Quack:实现类
package strategy.pattern;

public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Quack");
    }
}
  1. Squeak:实现类
package strategy.pattern;

public class Squeak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Squeak");
    }
}
  1. MuteQuack:实现类
package strategy.pattern;

public class MuteQuack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Silence");
    }
}
  1. Duck
package strategy.pattern;

public abstract class Duck {
    //使用策略模式实现鸭子的各种行为,即鸭子的行为封装在一组类中,可以轻易的扩充与改变
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public abstract void display();
    public void swim(){
        System.out.println("All ducks float,even decoys");
    }
    public void performFly(){
        flyBehavior.fly();
    }
    public void performQuack(){
        quackBehavior.quack();
    }
    //提供两个set方法,可以动态修改鸭子的行为
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}
  1. MallardDuck:绿头鸭,Duck的一个实现类
package strategy.pattern;

public class MallardDuck extends Duck{
    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
    //初始化时,顺便初始化绿头鸭的所有行为
    public MallardDuck(){
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }
}
  1. MallarDuckSimulator:测试类
package strategy.pattern;

public class MallarDuckSimulator {
    public static void main(String[] args) {
        Duck mallardDuck = new MallardDuck();
        mallardDuck.performFly();
        mallardDuck.performQuack();
        mallardDuck.setFlyBehavior(new FlyNoWay());
        //前后同一个对象mallardDuck调用同一个方法performFly,打印的内容不同,即可以在运行时改变行为
        mallardDuck.performFly();
    }
}

猜你喜欢

转载自www.cnblogs.com/handidiao/p/10838024.html
今日推荐