设计模式在企业项目中的实战应用
设计模式在实际项目中的核心价值是解决代码复用、扩展性和可维护性问题。以下结合 Spring、MyBatis 等主流框架的源码,分析设计模式在企业项目中的真实应用。
创建型模式
单例模式(Singleton)
Spring Bean 作用域:
Spring 容器管理的 Bean 默认就是单例(@Scope("singleton")),其实现方式是非懒加载的饿汉式 + 双重检查锁。
java
// Spring 中获取单例 Bean 的核心逻辑(DefaultSingletonBeanRegistry)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 1. 从一级缓存获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 2. 创建 Bean
singletonObject = singletonFactory.getObject();
// 3. 加入一级缓存
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
}
return singletonObject;
}
}实战-配置管理器:
java
@Component
@Scope("singleton")
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.version}")
private String version;
// 全局配置,确保整个应用只有一份配置实例
}工厂方法模式(Factory Method)
MyBatis SqlSessionFactory:
java
// MyBatis 的工厂模式
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();
// 内部实现(DefaultSqlSessionFactory)
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level) {
// 获取环境配置中的数据源和事务工厂
final DataSource dataSource = configuration.getEnvironment().getDataSource();
final TransactionFactory transactionFactory = configuration.getEnvironment().getTransactionFactory();
// 获取对应类型的执行器(SIMPLE/REUSE/BATCH)
final Executor executor = configuration.newExecutor(tx, execType);
// 返回 SqlSession 实现
return new DefaultSqlSession(configuration, executor);
}实战-支付渠道工厂:
java
// 支付接口
public interface Payment {
void pay(Order order);
}
// 具体实现
@Service("alipay")
public class Alipay implements Payment { ... }
@Service("wechatpay")
public class WechatPay implements Payment { ... }
// 工厂 + 策略组合
@Service
public class PaymentFactory {
@Autowired
private Map<String, Payment> paymentMap; // Spring 自动注入所有 Payment 实现
public Payment getPayment(String channel) {
Payment payment = paymentMap.get(channel);
if (payment == null) throw new IllegalArgumentException("不支持的支付渠道");
return payment;
}
}
// 使用
@RestController
public class OrderController {
@PostMapping("/pay")
public Result pay(@RequestParam String channel, @RequestBody Order order) {
Payment payment = paymentFactory.getPayment(channel);
payment.pay(order);
return Result.success();
}
}建造者模式(Builder)
Lombok @Builder:
java
@Builder
public class UserDTO {
private String name;
private String email;
private Integer age;
private List<String> tags;
}
// 使用链式构建
UserDTO user = UserDTO.builder()
.name("Alice")
.email("alice@example.com")
.age(25)
.tag("vip")
.build();实战-复杂查询条件构建:
java
// 类似 MyBatis-Plus 的 LambdaQueryWrapper
List<User> users = userMapper.selectList(
Wrappers.<User>lambdaQuery()
.eq(User::getName, "Alice")
.like(User::getEmail, "@example.com")
.in(User::getRole, "admin", "user")
.orderByDesc(User::getCreateTime)
.last("LIMIT 10")
);结构型模式
代理模式(Proxy)
Spring AOP 核心原理:
text
Spring AOP 通过动态代理实现方法增强:
- JDK 动态代理:目标类实现接口时使用
- CGLIB 代理:目标类未实现接口时使用
@Transactional、@Cacheable、@Async 等注解
都是通过 AOP 代理实现的。java
// Spring AOP 示例
@Aspect
@Component
public class LogAspect {
@Around("@annotation(LogOperation)")
public Object logOperation(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
String methodName = pjp.getSignature().toShortString();
try {
Object result = pjp.proceed();
long elapsed = System.currentTimeMillis() - start;
log.info("{} 执行成功, 耗时 {}ms", methodName, elapsed);
return result;
} catch (Exception e) {
log.error("{} 执行失败: {}", methodName, e.getMessage());
throw e;
}
}
}适配器模式(Adapter)
Spring MVC HandlerAdapter:
java
// Spring MVC 通过 HandlerAdapter 统一处理不同类型的处理器
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);
}
// 不同处理器的适配器实现
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
public ModelAndView handle(...) {
return ((Controller) handler).handleRequest(request, response);
}
}
public class RequestMappingHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof HandlerMethod);
}
public ModelAndView handle(...) {
// 执行 @RequestMapping 方法
return invokeHandlerMethod(request, response, handler);
}
}实战-第三方 API 适配:
java
// 统一短信发送接口
public interface SmsSender {
boolean send(String phone, String content);
}
// 适配阿里云短信
@Component
public class AliyunSmsAdapter implements SmsSender {
@Override
public boolean send(String phone, String content) {
// 调用阿里云 SDK
AliyunSmsClient client = new AliyunSmsClient();
return client.sendSms(phone, content);
}
}
// 适配腾讯云短信
@Component
public class TencentSmsAdapter implements SmsSender {
@Override
public boolean send(String phone, String content) {
TencentSmsClient client = new TencentSmsClient();
return client.sendMessage(phone, content);
}
}
// 业务层调用,与具体厂商解耦
@Service
public class NotificationService {
@Autowired
private SmsSender smsSender; // 可通过配置切换实现
public void sendVerificationCode(String phone) {
smsSender.send(phone, "您的验证码是: 123456");
}
}装饰器模式(Decorator)
Java IO 流:
java
// Java IO 是装饰器模式的经典应用
InputStream inputStream = new FileInputStream("test.txt"); // 基础流
InputStream buffered = new BufferedInputStream(inputStream); // 缓冲装饰
InputStream gzip = new GzipInputStream(inputStream); // 压缩装饰实战-权限缓存装饰:
java
// 基础服务
@Service
public class UserServiceImpl implements UserService {
public User getUser(Long id) {
return userMapper.selectById(id);
}
}
// 装饰器:添加缓存
public class CachedUserService implements UserService {
private final UserService delegate;
private final RedisTemplate redis;
public CachedUserService(UserService delegate, RedisTemplate redis) {
this.delegate = delegate;
this.redis = redis;
}
@Override
public User getUser(Long id) {
String key = "user:" + id;
User user = (User) redis.opsForValue().get(key);
if (user != null) return user;
user = delegate.getUser(id);
redis.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
return user;
}
}
// 使用(不修改原有代码)
UserService userService = new CachedUserService(new UserServiceImpl(), redisTemplate);行为型模式
策略模式(Strategy)
实战-订单处理策略:
java
// 订单类型枚举
public enum OrderType {
NORMAL, GROUP, SECKILL, PRESALE
}
// 策略接口
public interface OrderHandler {
OrderType getType();
void handle(Order order);
}
// 普通订单
@Component
public class NormalOrderHandler implements OrderHandler {
@Override
public OrderType getType() { return OrderType.PRIMARY; }
@Override
public void handle(Order order) {
// 常规库存扣减
}
}
// 秒杀订单
@Component
public class SeckillOrderHandler implements OrderHandler {
@Override
public OrderType getType() { return OrderType.SECKILL; }
@Override
public void handle(Order order) {
// 秒杀特殊校验 + 限流
}
}
// 策略分发(Spring 自动注入)
@Service
public class OrderService {
@Autowired
private List<OrderHandler> handlers;
@Autowired
private Map<OrderType, OrderHandler> handlerMap; // 或者用 Map
public void processOrder(Order order) {
// 匹配策略
OrderHandler handler = handlerMap.get(order.getType());
handler.handle(order);
}
}模板方法模式(Template Method)
Spring JdbcTemplate:
java
// JdbcTemplate 的 execute 方法定义了"获取连接-执行SQL-处理结果-释放资源"的固定模板
public <T> T execute(ConnectionCallback<T> action) {
Connection con = DataSourceUtils.getConnection(dataSource);
try {
// 回调:具体的 SQL 执行由调用方实现
return action.doInConnection(con);
} catch (SQLException ex) {
throw translateException("ConnectionCallback", sql, ex);
} finally {
DataSourceUtils.releaseConnection(con, dataSource);
}
}实战-数据导入模板:
java
public abstract class DataImportTemplate {
// 模板方法:定义导入流程骨架
public final ImportResult importData(MultipartFile file) {
// 1. 文件校验
validateFile(file);
// 2. 解析文件
List<String[]> rows = parseFile(file);
// 3. 数据校验(子类实现具体规则)
List<String> errors = validateData(rows);
if (!errors.isEmpty()) {
return ImportResult.fail(errors);
}
// 4. 批量保存(子类实现具体的存储逻辑)
int count = saveData(rows);
// 5. 记录日志
logImport(file.getOriginalFilename(), count);
return ImportResult.success(count);
}
// 抽象方法 — 子类必须实现
protected abstract List<String[]> parseFile(MultipartFile file);
protected abstract List<String> validateData(List<String[]> rows);
protected abstract int saveData(List<String[]> rows);
// 钩子方法 — 子类可选覆盖
protected void validateFile(MultipartFile file) {
if (file.isEmpty()) throw new IllegalArgumentException("文件为空");
}
protected void logImport(String filename, int count) {
log.info("导入文件: {}, 记录数: {}", filename, count);
}
}
// 使用
@Component
public class UserImportService extends DataImportTemplate {
@Override
protected List<String[]> parseFile(MultipartFile file) {
return ExcelUtils.read(file); // 使用 EasyExcel
}
@Override
protected List<String> validateData(List<String[]> rows) {
// 校验手机号格式、邮箱格式等
}
@Override
protected int saveData(List<String[]> rows) {
List<User> users = rows.stream().map(this::toUser).collect(toList());
userService.saveBatch(users);
return users.size();
}
}观察者模式(Observer)
Spring Event / ApplicationListener:
java
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private final Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
}
// 2. 发布事件
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 创建订单
orderDao.save(order);
// 发布事件 — 触发所有监听器
publisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
// 3. 监听事件(松耦合)
@Component
public class SmsListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 发送下单成功短信
smsService.send(event.getOrder().getPhone(), "订单创建成功");
}
}
@Component
public class InventoryListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 扣减库存
inventoryService.deduct(event.getOrder().getItems());
}
}
@Component
public class CouponListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 发放优惠券
couponService.grant(event.getOrder().getUserId());
}
}责任链模式(Chain of Responsibility)
MyBatis 插件机制:MyBatis 的拦截器(Interceptor)通过 Plugin.wrap() 形成责任链,每个插件可选择是否继续执行。
实战-参数校验责任链:
java
// 校验节点抽象
public abstract class ValidationHandler {
protected ValidationHandler next;
public ValidationHandler setNext(ValidationHandler next) {
this.next = next;
return next;
}
public void validate(Request request) {
doValidate(request);
if (next != null) {
next.validate(request);
}
}
protected abstract void doValidate(Request request);
}
// 具体校验节点
public class NotNullValidation extends ValidationHandler {
protected void doValidate(Request request) {
if (request.getUserId() == null) {
throw new ValidationException("用户ID不能为空");
}
}
}
public class AuthValidation extends ValidationHandler {
protected void doValidate(Request request) {
if (!authService.hasPermission(request.getUserId(), request.getOperation())) {
throw new ValidationException("无操作权限");
}
}
}
public class RateLimitValidation extends ValidationHandler {
protected void doValidate(Request request) {
if (!rateLimiter.tryAcquire(request.getUserId())) {
throw new ValidationException("操作过于频繁");
}
}
}
// 构建责任链
ValidationHandler chain = new NotNullValidation();
chain.setNext(new AuthValidation())
.setNext(new RateLimitValidation());
// 执行校验
chain.validate(request);设计模式总结
| 模式 | 核心意图 | 框架实战案例 |
|---|---|---|
| 单例 | 全局唯一实例 | Spring Bean 默认作用域 |
| 工厂方法 | 封装对象创建 | MyBatis SqlSessionFactory |
| 建造者 | 分步构建复杂对象 | MyBatis-Plus LambdaQueryWrapper |
| 代理 | 控制对象访问 | Spring AOP、@Transactional |
| 适配器 | 统一不同接口调用 | Spring MVC HandlerAdapter |
| 装饰器 | 动态增强已有对象 | Java IO BufferedInputStream |
| 策略 | 算法族替换 | 支付渠道、订单类型处理 |
| 模板方法 | 固定流程骨架 | JdbcTemplate、数据导入 |
| 观察者 | 事件解耦 | Spring Event、消息队列 |
| 责任链 | 请求逐级处理 | MyBatis 插件、过滤器 |
选型原则
text
1. 组合优于继承 — 优先使用策略/装饰器模式,而非大量子类
2. 开闭原则 — 新增功能时尽量不修改已有代码(观察者、策略)
3. 单一职责 — 每个类只负责一项职责(责任链拆分校验逻辑)
4. 接口隔离 — 不要强迫调用方依赖不需要的方法(适配器模式)
5. 依赖倒置 — 依赖抽象而非具体实现(工厂 + 策略)设计模式不是模板,是解决特定问题的思路。过度设计比没有设计更糟糕。