Spring 中常见的三种设计模式及其实现
1. 策略模式
策略模式在 Spring 中常用于根据上下文动态选择具体处理逻辑。其核心思想是定义一个统一接口,多个实现类各自负责一种策略。
以奖励发放系统为例,可定义如下接口:
public interface RewardDispatcher {
boolean canHandle(RewardContext context);
void dispatch(RewardContext context);
}
不同奖励类型(如积分、代金券、实物)分别实现该接口:
@Component
public class PointsDispatcher implements RewardDispatcher {
@Override
public boolean canHandle(RewardContext ctx) {
return ctx.getRewardType() == RewardType.POINTS;
}
@Override
public void dispatch(RewardContext ctx) {
System.out.println("发放积分奖励");
}
}
@Component
public class VoucherDispatcher implements RewardDispatcher {
@Override
public boolean canHandle(RewardContext ctx) {
return ctx.getRewardType() == RewardType.VOUCHER;
}
@Override
public void dispatch(RewardContext ctx) {
System.out.println("发放代金券");
}
}
关键点:
- 使用
@Component将实现类注册为 Spring Bean; - 通过
canHandle()方法判断是否适用当前上下文; - 上下文对象(
RewardContext)封装所有必要参数,便于扩展。
2. 工厂方法模式
工厂方法模式用于解耦对象创建与使用逻辑。在 Spring 中,可通过自动注入所有策略实现,并动态选择合适实例。
@Component
public class RewardDispatcherFactory {
private final List<RewardDispatcher> dispatchers;
public RewardDispatcherFactory(List<RewardDispatcher> dispatchers) {
this.dispatchers = dispatchers;
}
public RewardDispatcher getDispatcher(RewardContext context) {
return dispatchers.stream()
.filter(d -> d.canHandle(context))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No dispatcher found"));
}
}
客户端调用示例:
@Service
public class RewardService {
private final RewardDispatcherFactory factory;
public RewardService(RewardDispatcherFactory factory) {
this.factory = factory;
}
public void issueReward(RewardContext ctx) {
RewardDispatcher dispatcher = factory.getDispatcher(ctx);
dispatcher.dispatch(ctx);
}
}
优势:新增奖励类型只需添加新实现类,无需修改工厂或服务逻辑,符合开闭原则。
3. Builder 模式
Builder 模式用于构建复杂对象,尤其适用于需要依赖注入参与构造过程的场景。与 Lombok 的简单 Builder 不同,Spring 管理的 Builder 可注入其他 Bean。
public class RewardContext {
private final RewardType type;
private final int quantity;
private final String userId;
private RewardContext(RewardType type, int quantity, String userId) {
this.type = type;
this.quantity = quantity;
this.userId = userId;
}
@Component
@Scope("prototype")
public static class Builder {
@Autowired
private RewardRepository repository;
private long rewardId;
private String userId;
public Builder rewardId(long id) {
this.rewardId = id;
return this;
}
public Builder forUser(String uid) {
this.userId = uid;
return this;
}
public RewardContext build() {
RewardConfig config = repository.findById(rewardId);
return new RewardContext(config.getType(), config.getAmount(), userId);
}
}
// getters...
}
使用方式:
@Service
public class RewardOrchestrator {
@Autowired
private ApplicationContext ctx;
public void process(long rewardId, String userId) {
RewardContext context = ctx.getBean(RewardContext.Builder.class)
.rewardId(rewardId)
.forUser(userId)
.build();
// 后续分发逻辑...
}
}
注意点:
- Builder 类必须为
static,避免依赖外部实例; - 使用
@Scope("prototype")确保每次获取新实例,避免状态污染; - 通过
ApplicationContext.getBean()获取多例 Builder 实例。