Skip to content

策略模式和工厂模式是"黄金搭档",也是消除 if/else 分支的两把利器。这篇把策略模式单独捋一遍:它解决什么、怎么落地、和工厂模式怎么配合、以及它和观察者模式容易被混淆的点。

一、解决什么问题

策略模式解决的是 一坨 if/elseswitch 的分支坏味道

java
// 折扣计算:每加一种折扣,就加一个 if 分支,函数越来越长
public double calc(String type, double price) {
    if ("normal".equals(type)) {
        return price;
    } else if ("vip".equals(type)) {
        return price * 0.8;
    } else if ("svip".equals(type)) {
        return price * 0.6;
    } else if ("new".equals(type)) {
        return price * 0.9;
    }
    return price;
}

问题是:每加一种策略就要改这个函数(违反开闭原则),而且所有策略的逻辑堆在一起,函数越写越长、越来越难维护。

策略模式把每种算法封装成一个独立的类,让它们可以互相替换。

二、策略模式怎么落地

三个角色:

  • 策略接口(Strategy):定义算法规范
  • 具体策略(ConcreteStrategy):每种算法一个类
  • 上下文(Context):持有一个策略引用,负责调用
java
// ① 策略接口
public interface DiscountStrategy {
    double discount(double price);
}

// ② 具体策略:每种折扣一个类
public class NormalDiscount implements DiscountStrategy {
    public double discount(double price) { return price; }
}
public class VipDiscount implements DiscountStrategy {
    public double discount(double price) { return price * 0.8; }
}
public class SvipDiscount implements DiscountStrategy {
    public double discount(double price) { return price * 0.6; }
}

// ③ 上下文:持有策略,负责调用
public class PriceContext {
    private DiscountStrategy strategy;
    public PriceContext(DiscountStrategy strategy) { this.strategy = strategy; }
    public double calc(double price) { return strategy.discount(price); }
}

// 使用
PriceContext ctx = new PriceContext(new VipDiscount());
double result = ctx.calc(100);   // 80.0

现在加一种折扣 = 新增一个策略类,不改任何已有代码if/else 消失了。

策略模式结构:上下文持有策略接口,多个具体策略实现该接口

三、和工厂模式配合(黄金搭档)

策略模式本身不解决"用哪个策略"的问题——还是得有人选策略。这时工厂模式就来了:

java
// 工厂负责"创建哪个策略"
public class StrategyFactory {
    public static DiscountStrategy create(String type) {
        switch (type) {
            case "vip":  return new VipDiscount();
            case "svip": return new SvipDiscount();
            default:     return new NormalDiscount();
        }
    }
}

// 组合:工厂选策略 + 策略执行算法
PriceContext ctx = new PriceContext(StrategyFactory.create("vip"));
ctx.calc(100);

分工很清晰:

模式职责
工厂模式创建哪个策略对象(解决"选谁")
策略模式执行哪种算法(解决"怎么做")

工厂模式更详细的讲解见《工厂模式》。

四、策略模式 vs 观察者模式(易混)

两者经常被一起提,但解决的是完全不同的问题

维度策略模式观察者模式
目的算法的可替换状态的变化通知
关系上下文主动持有一个策略主题维护一群观察者
触发调用时选择算法事件发生时广播通知
典型场景折扣、排序、支付渠道事件监听、发布订阅、消息推送

一句话区分:策略是"我来选算法",观察者是"你变了通知我"

小结

  • 策略模式消除 if/else 分支,把每种算法封装成独立类,符合开闭原则
  • 三要素:策略接口 + 具体策略 + 上下文
  • 和工厂模式是黄金搭档:工厂"创建"策略,策略"执行"算法
  • 与观察者模式区分:策略=算法可替换,观察者=状态变化通知

下一步可以看《观察者模式》——它讲"状态变了怎么通知一堆监听者",是事件驱动、消息队列的底层思想(文章整理中,也会讲清它和发布订阅模式的区别)。