【设计模式】-05策略模式

1.什么是策略模式?

策略模式是将可变的部分从程序中抽象成算法接口,在该结构下分别封装一系列算法实现.

比较典型的,可以拿大家都用过的美团来说,当大家在美团上开房进入到支付页面时,可以选择各种方式支付,比如美团支付,银联支付,支付宝支付,微信等…这里其实美团就把支付页面抽象成一个接口,具体的银联支付,支付宝支付,微信支付…交给对应的产商去实现其支付算法,美团在这里仅提供一个抽象的接口,不提供实现,这样做可以避免以后每接入一种新的支付方式就去改一遍代码…

2.为什么使用策略模式?

提到策略模式,我们先讲一下继承,在传统的做法中,当遇到一个类中的方法被多个类调用时,我们可能会考虑通过继承来实现,在父类中实现该方法,然后在子类直接继承父类即可拥有该方法,但这么做有何弊端?

①不够灵活,当某个子类需要修改父类中方法时还需要去覆盖父类的方法,万一有个子类忘了修改呢?编译器这时候又不报错或提示;

②一旦父类中的方法发生改变,所有继承它的子类都会受到牵连,有种株连九族的感觉.

有人会说,那我可以抽象父类中的方法,让子类去实现啊,的确这样做确实解决了上面提到的2个弊端,但又引入了新的弊端:

①每个子类都要强制重写父类中的方法,那么多子类,每个都要去写实现,多累啊.

②如果其中有几个子类的实现功能都相同,那又重新引入了代码重复问题.

有没有什么办法可以避免上面这两种方式啊?答案就是策略模式,策略模式可以很灵活的解决这些弊端,同时符合开闭原则,使代码具有很高的可扩展性复用性,可以消除代码中大量的条件语句,提高代码的可读性和质量所以推荐使用策略模式.

3.适用场景

①在代码中出现很多类具有相同的共性,可以考虑将其抽出来.

②运行时需要选取不同的算法变体.

③代码中有条件语句去选取其中一个分支时.

当出现以上三种情况下,可以考虑使用策略模式,让你的代码更优雅.

4.实现

由于我是一个车迷,所以这里拿车子来写代码,虽然我在现实中没车,但代码里可以有啊…

我现在有3辆车,一辆陆地跑的,一辆可以水上漂的,一辆更牛逼,可以上天飞的劳斯莱斯…

这些车子无论是天上飞的还是地上跑的都具有一个共性就是都可以Run,于是我决定把这个Run的算法抽出来作为接口,然后用不同的类分别去实现它们背后的算法,比如给水上漂的装上气垫,给天上飞的装上螺旋桨…对我抽象出来的Run接口而言,我再无需关心背后的实现.即便是以后再入手一辆可以在太空中翱翔的车,我也不用改来改去的,只需要再创个类去实现它即可.

①创建抽象接口和抽象方法

/**
 * 策略模式-抽象接口
 */
public interface RunStrategy {
    void run();//所有车子都能跑
}

②创建抽象的父类-车,将抽象接口私有化并修改默认构造方法.

/**
 * 父类-车
 */
public abstract class Car {
    private RunStrategy runStrategy;

    public Car(RunStrategy runStrategy) {
        this.runStrategy = runStrategy;
    }
    public void init(){
        runStrategy.run();
    }
}

③创建抽象接口的各种实现类:

public class RunOnRoald implements RunStrategy {
    @Override
    public void run() {
        System.out.println("在陆地上疾驰...");
    }
}

public class RunOnWater implements RunStrategy {
    @Override
    public void run() {
        System.out.println("在水面上疾驰...");
    }
}

public class RunOnAir implements RunStrategy {
    @Override
    public void run() {
        System.out.println("在空气上疾驰...");
    }
}

④创建对应的各种类型的车子,并继承它们的爸爸-Car:

/**
 * 陆地suv汽车
 */
public class Suv extends Car{
    public Suv(RunStrategy runStrategy) {
        super(runStrategy);
    }
}

/**
 * 超牛的多功能汽车
 */
public class Mpv extends Car {
    public Mpv(RunStrategy runStrategy) {
        super(runStrategy);
    }
}

/**
 * 会飞的汽车
 */
public class Skr extends Car{
    public Skr(RunStrategy runStrategy) {
        super(runStrategy);
    }
}

⑤测试一下:

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        //创建各种车子并调用其父类的初始化方法
        Car suv = new Suv(new RunOnRoald());
        suv.init();
        Car mpv = new Mpv(new RunOnWater());
        mpv.init();
        Car skr = new Skr(new RunOnAir());
        skr.init();
    }
}

测试结果:

《【设计模式】-05策略模式》

测试结果完全符合预期效果,如果你不喜欢车子,喜欢接近实际点的业务场景,那么我这里还有个现成的,你可以模拟去体验一把:

有个电商商城,类似于淘宝这种,然后商城有会员制度,不同等级的会员享受不同力度的折扣,非会员无折扣,具体的打折情况如下表:

《【设计模式】-05策略模式》

你可以抽象一个计算价格的父类,父类中拥有一个计算折扣的抽象接口,不同的用户身份应不同的折扣算法,这些折扣算法分别去实现计算折扣的抽象接口,最后让所有用到计算价格的类去继承这个父类. 这个场景就比较贴合实际业务,加入某一天老板突然说要加入个什么白金会员,黑卡会员之类的,你要改动的代码会很少,这个我就不写了,感兴趣的自己去实现.

    原文作者:设计模式
    原文地址: https://blog.csdn.net/lovexiaotaozi/article/details/84062227
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞