前言
在软件开发中,我们常常会遇到这样的场景:同一个功能需要根据不同的条件选择不同的算法或行为。例如:
电商系统的促销活动(满减、折扣、积分抵扣等),不同活动对应不同的计算规则。
导航系统根据实时路况选择不同的路径策略(最短距离、最快速度、避开拥堵)。
支付系统支持多种支付方式(支付宝、微信、信用卡),每种方式有不同的处理逻辑。
最近开发遇到多平台AI不同处理逻辑也是通过策略模式+工厂方法来开发的
如果直接在代码中通过大量的 if-else
或 switch-case
实现这些分支逻辑,会导致代码臃肿、难以维护,且新增或修改算法时需要频繁修改原有代码,违反开闭原则(对扩展开放,对修改关闭)。
策略模式正是为了解决这类问题而诞生。它通过将算法抽象为独立的“策略”对象,使得算法可以灵活替换,系统更易扩展。接下来,我们从一个实际案例出发,一步步拆解策略模式的原理和实现。
策略模式从0开始教程
一、什么是策略模式?
策略模式(Strategy Pattern) 是一种行为型设计模式,允许你定义一系列算法(策略),并将每个算法封装成独立的类,使得它们可以相互替换。策略模式让算法的变化独立于使用它的客户端。
类比理解:
想象你有一个导航APP,可以根据不同策略(最快路线、最短路线、避开收费)规划路线。策略模式就像让你在APP运行时自由切换这些路线策略,而无需重写整个导航系统。
二、为什么需要策略模式?
1. 直接编码的问题
假设你要实现一个支付系统,支持支付宝、微信、信用卡支付。如果直接编码,可能会写出这样的代码:
public class PaymentService {
public void pay(String paymentType, double amount) {
if ("alipay".equals(paymentType)) {
// 支付宝支付逻辑
} else if ("wechat".equals(paymentType)) {
// 微信支付逻辑
} else if ("creditCard".equals(paymentType)) {
// 信用卡支付逻辑
}
}
}
问题:
违反开闭原则:新增支付方式需修改原有代码。
代码臃肿:大量
if-else
难以维护。复用性差:算法逻辑与业务耦合,无法复用。
2. 策略模式的优势
解耦:将算法逻辑与业务代码分离。
灵活扩展:新增策略无需修改已有代码。
消除条件判断:避免复杂的
if-else
分支。
策略模式的结构
策略模式包含三个核心角色:
策略模式实战:多AI服务动态调用
话不多说直接上代码
一、场景需求
开发智能客服系统,需根据业务场景调用不同AI服务:
OpenAI:生成创意文案
百度千帆:处理商品推荐
智谱AI:回答售后问题
DeepSeek:分析用户行为
要求:通过配置切换AI服务,核心业务代码无需修改。
二、策略模式实现
1. 定义策略接口
/**
* AI服务策略接口(所有AI服务的共同契约)
*/
public interface AIService {
String executeTask(String input); // 执行AI任务
String getProviderName(); // 返回服务商名称
}
2. 实现具体策略
策略1:OpenAI服务
public class OpenAIService implements AIService {
private final String apiKey;
public OpenAIService(String apiKey) {
this.apiKey = apiKey;
}
@Override
public String executeTask(String input) {
// 实际调用OpenAI API(此处模拟实现)
return "[OpenAI] 生成文案:" + input.toUpperCase() + "!";
}
@Override
public String getProviderName() {
return "OPENAI";
}
}
策略2:千帆商品推荐
public class QianfanService implements AIService {
private final String accessToken;
public QianfanService(String accessToken) {
this.accessToken = accessToken;
}
@Override
public String executeTask(String input) {
// 调用千帆推荐API
return "[千帆] 推荐商品:手机、耳机,基于输入:" + input;
}
@Override
public String getProviderName() {
return "QIANFAN";
}
}
策略3:智谱客服问答
public class ZhipuService implements AIService {
private final String secretKey;
public ZhipuService(String secretKey) {
this.secretKey = secretKey;
}
@Override
public String executeTask(String input) {
// 调用智谱问答API
return "[智谱] 您的问题'" + input + "'的答案是:商品已发货";
}
@Override
public String getProviderName() {
return "ZHIPU";
}
}
3. 上下文控制类
/**
* AI服务执行上下文
*/
public class AIServiceContext {
private AIService strategy;
// 动态注入策略
public void setStrategy(AIService strategy) {
this.strategy = strategy;
System.out.println("已切换至AI服务:" + strategy.getProviderName());
}
// 执行AI任务
public String processInput(String input) {
if (strategy == null) {
throw new IllegalStateException("未选择AI服务策略");
}
return strategy.executeTask(input);
}
}
三、客户端动态调用
public class Client {
public static void main(String[] args) {
AIServiceContext context = new AIServiceContext();
// 创建策略对象
AIService openAI = new OpenAIService("sk-xxx");
AIService qianfan = new QianfanService("token-xxx");
// 动态切换策略
context.setStrategy(openAI);
System.out.println(context.processInput("夏季促销"));
context.setStrategy(qianfan);
System.out.println(context.processInput("用户喜欢电子产品"));
}
}
输出结果:
已切换至AI服务:OPENAI
[OpenAI] 生成文案:夏季促销!
已切换至AI服务:QIANFAN
[千帆] 推荐商品:手机、耳机,基于输入:用户喜欢电子产品
四、工厂模式扩展(配置化)
/**
* AI服务工厂(根据配置创建策略)
*/
public class AIServiceFactory {
public static AIService createService(String config) {
// 解析配置(示例格式:PROVIDER:KEY)
String[] parts = config.split(":");
String provider = parts[0];
String authKey = parts[1];
switch (provider.toUpperCase()) {
case "OPENAI":
return new OpenAIService(authKey);
case "QIANFAN":
return new QianfanService(authKey);
case "ZHIPU":
return new ZhipuService(authKey);
default:
throw new IllegalArgumentException("不支持的AI服务: " + provider);
}
}
}
// 配置文件 application.conf
ai.config=QIANFAN:token-xxx
// 配置化调用示例
public class ConfigClient {
public static void main(String[] args) {
// 从配置文件读取配置
String config = "QIANFAN:token-xxx";
AIService service = AIServiceFactory.createService(config);
AIServiceContext context = new AIServiceContext();
context.setStrategy(service);
System.out.println(context.processInput("用户咨询订单"));
}
}
五、实际应用场景
AB测试:同时使用多个AI服务生成结果,对比质量
AIService serviceA = new OpenAIService("sk-xxx"); AIService serviceB = new QianfanService("token-xxx"); String resultA = serviceA.executeTask(input); String resultB = serviceB.executeTask(input);
故障转移:当主服务不可用时自动切换备用服务
try { return mainService.executeTask(input); } catch (ServiceException e) { log.warn("主服务不可用,切换备用"); return backupService.executeTask(input); }
策略模式的优缺点
优点
符合开闭原则:新增策略无需修改已有代码。
避免多重条件判断。
提高代码复用性:策略可被多个客户端共享。
缺点
客户端必须知晓所有策略:需理解不同策略的区别。
类数量增加:每个策略一个类,可能增加系统复杂度。
适用场景
系统需要多种算法变体(例如排序、支付、压缩算法)。
需要在运行时动态切换算法。
需要将算法细节与业务逻辑解耦。