策略模式看这篇就懂啦

策略模式(Strategy Pattern)


一、含义

抽象地来说:

策略模式定义了一个算法族,并对每个算法进行封装,使它们能够互换使用。

策略模式可以使算法独立于使用算法的客户端。

第一次看到这样定义难免会感到困惑,不急,让我们来通过一个案例来分析什么是策略模式。

二、案例分析

如果你要设计一个模仿各种汽车的类,那你可能会想到要先建立一个Car.java抽象类,后面再通过继承它来创建宝马、奔驰等汽车。

abstract class Car {
    public void run() {
    }
}

class Baoma extends Car {
    @Override
    public void run() {
        System.out.println("Baoma is running");
    }
}

//...

现在我假设你已经用这种方式创造出了几百种汽车。

但是汽车不仅仅只有run()这个方法,它还有很多种方法需要实现。

如果此时,让你给你创造的几百种汽车中添加添加能源这个功能,你会打算怎么做呢?

“让我想想”的图片搜索结果

一般情况下,你可能会想到在基类Car.class里加入fuel()方法,然后每个子类再重写一下这个方法就可以了。

你也可能想到可以创造一个接口Fuelable.class让每个子类继承它就好了。

上述两种方法都可以实现这个要求。

在这里插入图片描述

但是!!汽车能源方式最多只有几种,要么加油,要么充电等等等。

而你有几百种汽车,你真的要在每个汽车类中都重写一遍可能会重复的代码吗?

在这种情况下,策略模式应运而生~

对于添加能源的行为,我们可以给它创造一个接口FuelMethod.class,但接下来的事不同于直接用具体的汽车类去实现它,而是创造出很多FuelMethod.class的子类。

interface FuelMethod{
    void fuel();
}

// 汽油
class QiYou implements FuelMethod{
    @Override
    public void fuel() {
        System.out.println("这车加汽油的");
    }
}

// 充电
class Dian implements FuelMethod {
    @Override
    public void fuel() {
        System.out.println("这车充电的");
    }
}

//...

同时,我们需要在基类Car.class中添加一个FuelMethod类属性,然后提供一个添加能源的方法。

而在你之前写的几百个汽车类中,我们不需要添加很多代码,只需要在构造器中实现FuelMethod类就好,实现的具体类取决于车加的能源(这里的例子只有汽油或者电)。

abstract class Car {
    // 加入“添加能源”类的属性
    FuelMethod fuelMethod;

    public Car() {

    }

    // 表示添加能源方式的方法
    public void performFuel() {
        if (fuelMethod != null) {
            fuelMethod.fuel();
        }
    }

    public void run() {
        System.out.println("All cars can run");
    }
}

class BMW extends Car {
    public BMW() {
        // 表示用汽油的
        fuelMethod = new QiYou();
    }
    @Override
    public void run() {
        System.out.println("BMW is running");
    }
}

class Tesla extends Car{
    public Tesla() {
        // 表示用电的
        fuelMethod = new Dian();
    }
    @Override
    public void run() {
        System.out.println("Tesla is running");
    }
}

//...

到了这里,我们已经完成了对汽车“添加能源”功能的添加,相比用每个类都去实现接口来说,节省了不少代码量吧?

写一个测试类让我们看看效果如何

public class MainTest {
    public static void main(String[] args) {
        Car BMW3 = new BMW();
        BMW3.performFuel();
        Car Tesla3 = new Tesla();
        Tesla3.performFuel();
    }
}

输出

这车加汽油的
这车充电的

如果想要动态地更换汽车能源方式,我们可以给Car.class加个方法。这样所有的子类都可以用这个方法来更换添加能源的方式。

public void changeFuelMethod(FuelMethod method) {
    this.fuelMethod = method;
}

测试类如下

public class MainTest {
    public static void main(String[] args) {
        Car Tesla3 = new Tesla();
        Tesla3.performFuel();
        Tesla3.changeFuelMethod(new QiYou());
        Tesla3.performFuel();
    }
}

输出

这车充电的
这车加汽油的

到此我们就完成了对汽车类的修改,是不是很酷?

综合来看,我们只添加了一个接口并写了几个实现类,然后我们在父类Car中写入这个接口类把它作为属性,最后在每个子类的构造器中实现这个FuelMethod对象。


三、总结

这就是我所要讲的策略模式

在案例中,我们描述行为的方式发生了改变。我们不再将汽车添加燃料的事看作是个行为,而是把它看作是个算法族,不同的添加能源方式代表着不同的算法实现。

同时,我们是将汽车类和添加燃料类“组合”在了一起,注意这里是“组合”,与“继承”的方式是不同的,汽车的行为不是通过继承或实现接口来实现的,而是通过与适当的对象组合在一起实现的。

使用组合可以使我们的程序有更大的弹性,不仅在将算法族封装成类上,还是动态地改变行为,组合都将是一个很重要的技巧。

这个时候你再回顾一下开头的定义,是不是感到豁然开朗了?

策略模式定义了一个算法族,并对每个算法进行封装,使它们能够互换使用。

策略模式可以使算法独立于使用算法的客户端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值