当前位置: 主页 > JAVA语言

策略模式java-策略模式与状态模式

发布时间:2023-04-19 11:05   浏览次数:次   作者:佚名

一、了解策略模式

1.1 什么是策略模式

策略模式 (Strategy Pattern) 是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。此模式让算法的变化独立于使用算法的客户。

1.2 策略模式组成结构

1.3 策略模式 UML 图解

这里写图片描述

1.4 策略模式应用场景

二、策略模式具体应用

2.1 问题描述

模拟鸭子游戏:游戏中会出现各种鸭子,一边游泳戏水、一边呱呱叫,为了提高游戏的乐趣,加入了让鸭子飞的功能。但是考虑到并不是所有的鸭子都会飞,比如像小孩子游泳时玩的橡皮鸭。现在让你利用 OO 技术,设计鸭子相关的类。

2.2 使用继承

策略模式java_java中的策略模式_策略模式与状态模式

这里写图片描述

我们可能想到使用继承,在超类Duck中定义鸭子的相关方法,并实现其对应的动作,这样就能让所有鸭子都可以对应其fly()的动作。在定义橡皮鸭时,只需要覆盖其父类 (Duck) 中的fly()方法即可。

如果我们还想加入诱饵鸭,这种鸭子既不会叫,也不会飞,那么我们就要继承Duck类,重写其中的quack()、display()和fly()方法。

策略模式java_策略模式与状态模式_java中的策略模式

这种通过继承的方法是可以解决问题,但是有很多的局限

2.3 使用接口

这里写图片描述

认识到上面继承的不足,我们可能想到了另一种方式去解决这种问题,通过接口的方式去实现某些动作。把fly()和quack()方法从Duck类中抽取抽取出来策略模式java,分别放在Flyable和Quackable接口中。

通过接口的方式是可以完成任务,但是这也确实是一个很笨的方式。因为对于很多种鸭子来说,它们大部分都会飞与呱呱叫,但是我们在定义它们类的时候都要去实现Flyable和Quackable接口,这样一来重复的代码更多了。

策略模式java_java中的策略模式_策略模式与状态模式

2.4 问题归零

到这里我们知道使用继承并不能很好的解决问题,因为鸭子的行为在子类中是不断变化的,并且让所有的鸭子都具有这些行为是不恰当的,比如橡皮鸭不具有飞的行为。通过接口的方式似乎还不错,但是 Java 接口并不具备实现代码,所以继承接口并不能达到代码复用的目的,一不小心,就可能造成新的错误!

幸运的是,有一个设计原则,恰好适用于这种状况:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。这样以来,代码变化引起的后果变少策略模式java,系统将更有弹性。

2.5 策略模式登场

除了fly()和quack()方法之外,Duck中的其他方法还算一切正常,没有什么需要经常需要变化或修改的地方。所以除了fly()和quack()方法,我们不打算对Duck中的其他方法做太多处理。我们希望一切具有弹性,正是因为没有弹性,上面两种方法都被我们淘汰掉了。

比如说,我们要产生一个绿头鸭的实例,并制定特定“类型”的飞行行为给它。我们可以在鸭子类中包含设定行为的方法,这样就可以在“运行时”动态地“改变”绿头鸭的飞行行为。

有了这些实现目标,于是就有了第二个设计原则:针对接口编程,而不是针对实现编程。

这里我们使用接口代表每个行为,比如说,FlyBehavior与QuackBehavior,而行为的每个实现都将实现其中一个接口。所以这次鸭子类不会去实现Flyable和Quackable接口,反而是由我们制造一组其他类专门实现FlyBehavior与QuackBehavior,这就称为“行为”类。由行为类而不是Duck类来实现该接口。

(1)策略模式设计图

策略模式与状态模式_策略模式java_java中的策略模式

这里写图片描述

改造原来的鸭子类

这里写图片描述

(2) 代码实现

这里我们将Duck类定义成抽象类,并把display()方法定义成抽象方法。

接口QuackBehavior

package com.jas.strategy;
public interface QuackBehavior {
    void quack();
}

接口QuackBehavior实现类Quack(实现鸭子呱呱叫)

​
package com.jas.strategy;
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Quack!");
    }
}
​

java中的策略模式_策略模式与状态模式_策略模式java

接口QuackBehavior实现类SQuack(实现鸭子橡皮吱吱叫)

​package com.jas.strategy;
public class SQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("SQuack!");
    }
}

接口QuackBehavior实现类MuteQuack(实现鸭子不会叫)

​
​
​package com.jas.strategy;
public class MuteQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Silence!");
    }
}

接口FlyBehavior

package com.jas.strategy;
public interface FlyBehavior {
    void fly();
}

接口FlyBehavior实现类FlyWithWings(实现鸭子飞)

​
package com.jas.strategy;
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I'm flying!");
    }
}

接口FlyBehavior实现类FlyNoWay(实现鸭子不会飞)

策略模式java_策略模式与状态模式_java中的策略模式

package com.jas.strategy;
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I can't fly!");
    }
}

Duck类

​
package com.jas.strategy;
public abstract class Duck {
    private QuackBehavior quackBehavior;
    private FlyBehavior flyBehavior;
    
    public void swim(){
        System.out.println("All ducks float.");
    }
    
    public abstract void display();
    
    public void performQuack(){
        quackBehavior.quack();
    }
    public void performFly(){
        flyBehavior.fly();
    }
    
    public void setQuackBehavior(QuackBehavior quackBehavior){
        this.quackBehavior = quackBehavior;
    }
    
    public void setFlyBehavior(FlyBehavior flyBehavior){
        this.flyBehavior = flyBehavior;
    }
    
}
​

测试类RubberDuck

package com.jas.strategy;
public class RubberDuck extends Duck {
    @Override
    public void display() {
        System.out.println("Rubber Duck");
    }
    
    public static void main(String[] args) {
        
        Duck rubberDuck = new RubberDuck();    //橡皮鸭实例
        
        rubberDuck.setQuackBehavior(new SQuack());    //橡皮鸭吱吱叫
        rubberDuck.setFlyBehavior(new FlyNoWay());    //橡皮鸭不会飞
        
        rubberDuck.performQuack();
        rubberDuck.performFly();
    }
}
//输出
//SQuack!
//I can't fly!

2.6 从策略模式组成结构对问题进行总结

这里写图片描述

三、策略模式总结

3.1 策略模式的优缺点

优点

缺点