1. 设计模式之策略模式:替换掉屎一样的if else语句

1.1. 介绍

在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式

在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。

  • 要点1:必须将if else的代码,封装到不同的策略类中。

  • 要点2:将选择哪种策略的逻辑给放到一个工厂类中去,选择策略的代码务必很简洁。

  • 要点3:context可有可无,具体是看你的策略执行这块如果就一行代码调用,不需要context。如果策略执行逻辑较复杂,可以用context来封装执行逻辑。

设计模式的重点是思想,大部分业务场景不会只有一种设计模式,很多情况都是多种设计模式相结合。例如策略模式,往往需要结合工厂模式来使用。

应用实例

  1. 支付方式选择: 支付宝、微信支付、银行卡等策略动态切换。

  2. 游戏角色技能: 不同武器对应不同的攻击策略。

  3. 数据压缩/加密: 支持多种压缩算法(ZIP、RAR)或加密方式(AES、DES)。

  4. 优惠券计价: 计算价格时,不同优惠券计价逻辑不同。

优缺点及建议

优点
1.避免多重条件语句,代码更清晰。
2.易于扩展新算法(开闭原则)。
3.算法可复用和单元测试。

缺点
1.客户端需了解所有策略类(需权衡)。可以配合工厂模式来避免。
2.策略类数量可能增多(需合理设计)。

使用建议
1.当系统中有多种算法或行为,且它们之间可以相互替换时,使用策略模式。
2.当系统需要动态选择算法时,策略模式是一个合适的选择。

注意事项
1.如果系统中策略类数量过多,考虑使用其他模式或设计技巧来解决类膨胀问题。

1.2. 实现及相关代码

假设某业务需要优惠券计价,根据类型不同,选择不同优惠券进行计价。

1.2.1. 没使用设计模式方式

调用方法

public static void main(String[] args) {
    // 优惠券类型
    int discountStyle = 1;
    if(discountStyle == 1) {
        System.out.println("执行优惠计价方式1的复杂业务逻辑");
    } else if(discountStyle == 2) {
        System.out.println("执行优惠计价方式2的复杂业务逻辑");
    } else if(discountStyle == 3) {
        System.out.println("执行优惠计价方式3的复杂业务逻辑");
    } else {
        System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
    }
}

可能会遇到的问题

在实际的业务代码中,常见的结构是上面这样的,但是每个ifif else之间的代码行数,可能多达几十行,甚至几百行。造成整个计价方法会很庞大。

若干年后如果要调整逻辑或者修改 bug,需要整体阅读一下代码,阅读大量if else及代码块内的逻辑,调整起来很麻烦。

1.2.2. 使用设计模式方式

使用策略模式,可以使逻辑清晰,将if else中的逻辑封装到一个个策略中,集中管理,方便阅读及调整;也会简化整体方法及if else

接口及数据对象

public interface DiscountCalculateStrategy {
    void calculate();
}

public static class DiscountCalculateStrategyA implements DiscountCalculateStrategy {
    public void calculate() {
        System.out.println("执行优惠计价方式1的复杂业务逻辑");
    }
}

public static class DiscountCalculateStrategyB implements DiscountCalculateStrategy {
    public void calculate() {
        System.out.println("执行优惠计价方式2的复杂业务逻辑");
    }
}

public static class DiscountCalculateStrategyC implements DiscountCalculateStrategy {
    public void calculate() {
        System.out.println("执行优惠计价方式3的复杂业务逻辑");
    }
}

public static class DiscountCalculateStrategyDefault implements DiscountCalculateStrategy {
    public void calculate() {
        System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
    }
}

/** 获取计价策略的核心工厂 */
public static class DiscountCalculateStrategyFactory {
    public static DiscountCalculateStrategy getDiscountCalculateStrategy(int discountStyle) {
        if(discountStyle == 1) {
            return new DiscountCalculateStrategyA();
        } else if(discountStyle == 2) {
            return new DiscountCalculateStrategyB();
        } else if(discountStyle == 3) {
            return new DiscountCalculateStrategyC();
        } else {
            return new DiscountCalculateStrategyDefault();
        }
    }
}

public static class Context {
    private DiscountCalculateStrategy strategy;

    public DiscountCalculateStrategy getStrategy() {
        return strategy;
    }

    public void setStrategy(DiscountCalculateStrategy strategy) {
        this.strategy = strategy;
    }

    public void calculate() {
        strategy.calculate();
    }
}

调用方法

public static void main(String[] args) {
    // 优惠券类型
    int discountStyle = 1;
    // 配合工厂模式,屏蔽大量 if else
    DiscountCalculateStrategy strategy = DiscountCalculateStrategryFactory
            .getDiscountCalculateStrategy(discountStyle);
    // 执行对应的计价策略
    Context context = new Context();
    context.setStrategy(strategy);
    context.calculate();
}

results matching ""

    No results matching ""