1. 设计模式入门:为什么每个Java开发者都需要掌握
刚入行那会儿,我总觉得设计模式是那些架构师才需要关心的高级玩意儿。直到有次接手一个祖传代码,看到满屏的if-else和new关键字时,才明白为什么前辈说"不懂设计模式写不出好代码"。设计模式本质上就是前人总结的最佳实践套路,就像做菜的固定搭配——宫保鸡丁就该那么炒,回锅肉就得那么做。
在Java生态里,设计模式的应用几乎无处不在。Spring框架用工厂模式创建Bean,MyBatis用代理模式实现Mapper接口,JDK自身的集合类也大量运用迭代器模式。掌握这些模式后,你会发现很多框架源码突然变得亲切起来,甚至能预判某些类的设计思路。更重要的是,当产品经理又双叒叕改需求时,用对设计模式的代码往往只需要调整局部结构,而不用推倒重来。
2. 创建型模式:对象出生的艺术
2.1 单例模式(Singleton)
面试被问烂的单例模式,实际项目里最常见的用途是配置管理和线程池管理。我见过最离谱的代码是每个请求都new一个线程池,最后OOM了还找不到原因。正确的饿汉式写法应该是:
java复制public class ThreadPoolSingleton {
private static final ExecutorService INSTANCE = Executors.newFixedThreadPool(10);
private ThreadPoolSingleton() {}
public static ExecutorService getInstance() {
return INSTANCE;
}
}
注意:枚举实现单例才是《Effective Java》推荐的方式,既能防止反射攻击,又保证序列化安全
2.2 工厂方法模式
Spring的BeanFactory就是活教材。去年我重构过一个电商优惠券系统,原始代码里满是switch(couponType),每新增一种券类型就要修改核心逻辑。用工厂模式改造后:
java复制public interface CouponProcessor {
void applyCoupon(Order order);
}
public class DiscountCouponProcessor implements CouponProcessor {
// 具体实现
}
public class CouponProcessorFactory {
private static Map<String, CouponProcessor> processors = new HashMap<>();
static {
processors.put("DISCOUNT", new DiscountCouponProcessor());
processors.put("FULL_REDUCTION", new FullReductionCouponProcessor());
}
public static CouponProcessor getProcessor(String couponType) {
return processors.get(couponType);
}
}
这样新增券类型时,只需要实现新的CouponProcessor并在工厂里注册,核心业务代码完全不用动。
3. 结构型模式:构建灵活架构的积木
3.1 适配器模式
对接第三方支付时最有用。各家的SDK接口千奇百怪,用适配器统一成我们系统内部的支付接口:
java复制public interface PaymentService {
PaymentResult pay(PaymentRequest request);
}
// 支付宝适配器
public class AlipayAdapter implements PaymentService {
private AlipayClient alipayClient;
@Override
public PaymentResult pay(PaymentRequest request) {
// 将通用参数转换为支付宝特定参数
AlipayTradePayModel model = new AlipayTradePayModel();
model.setTotalAmount(request.getAmount());
// 调用支付宝SDK
return convertResult(alipayClient.execute(model));
}
}
3.2 装饰器模式
Java IO流就是经典案例。最近给系统加功能时,需要在不修改原有日志逻辑的前提下,增加日志内容脱敏处理:
java复制public class SensitiveLogDecorator implements Logger {
private Logger delegate;
public SensitiveLogDecorator(Logger delegate) {
this.delegate = delegate;
}
@Override
public void info(String message) {
delegate.info(desensitize(message));
}
private String desensitize(String raw) {
// 实现脱敏逻辑
}
}
// 使用方式
Logger logger = new SensitiveLogDecorator(originalLogger);
4. 行为型模式:对象间的沟通之道
4.1 策略模式
电商促销活动切换的绝配。把满减、折扣、赠品等促销算法封装成独立策略:
java复制public interface PromotionStrategy {
Order applyPromotion(Order order);
}
public class FullReductionStrategy implements PromotionStrategy {
private BigDecimal conditionAmount;
private BigDecimal reductionAmount;
@Override
public Order applyPromotion(Order order) {
if (order.getTotal().compareTo(conditionAmount) >= 0) {
order.setDiscount(reductionAmount);
}
return order;
}
}
// 上下文类
public class PromotionContext {
private PromotionStrategy strategy;
public void setStrategy(PromotionStrategy strategy) {
this.strategy = strategy;
}
public Order executeStrategy(Order order) {
return strategy.applyPromotion(order);
}
}
大促时只需切换策略实现,业务主流程完全不受影响。
4.2 观察者模式
事件驱动系统的基石。用Java自带实现做个用户注册通知:
java复制public class UserRegisterEvent extends EventObject {
private User user;
public UserRegisterEvent(Object source, User user) {
super(source);
this.user = user;
}
// getter...
}
// 被观察者
public class UserService {
private List<EventListener> listeners = new ArrayList<>();
public void addListener(EventListener listener) {
listeners.add(listener);
}
public void register(User user) {
// 注册逻辑...
notifyListeners(new UserRegisterEvent(this, user));
}
private void notifyListeners(UserRegisterEvent event) {
for (EventListener listener : listeners) {
listener.onEvent(event);
}
}
}
// 观察者实现
public class EmailSender implements EventListener {
@Override
public void onEvent(EventObject event) {
if (event instanceof UserRegisterEvent) {
sendWelcomeEmail(((UserRegisterEvent)event).getUser());
}
}
}
5. 模式混搭实战:电商订单系统设计
真实项目往往是多个模式组合使用。比如订单系统:
- 用工厂方法创建不同渠道订单(普通/秒杀/拼团)
- 用责任链处理订单校验(库存校验→风控校验→优惠校验)
- 用状态模式管理订单生命周期(待支付→已支付→待发货→...)
- 用观察者模式通知相关系统(库存系统→物流系统→财务系统)
java复制// 状态模式示例
public interface OrderState {
void pay(Order order);
void cancel(Order order);
void ship(Order order);
}
public class PaidState implements OrderState {
@Override
public void ship(Order order) {
order.setState(new ShippedState());
// 触发发货逻辑
}
// 其他方法实现...
}
// 责任链示例
public abstract class OrderValidator {
protected OrderValidator next;
public void setNext(OrderValidator next) {
this.next = next;
}
public abstract void validate(Order order);
}
public class StockValidator extends OrderValidator {
@Override
public void validate(Order order) {
if (!checkStock(order)) {
throw new ValidationException("库存不足");
}
if (next != null) {
next.validate(order);
}
}
}
6. 避坑指南:设计模式常见误用
-
单例的滥用:把本应该是无状态的工具类强行做成单例,导致并发问题。曾经见过把SimpleDateFormat放在单例里引发的线上事故。
-
过度设计:在简单CRUD里硬套设计模式,比如为3个if-else的场景搞策略模式,反而增加复杂度。
-
混淆相似模式:
- 策略vs状态:策略是算法替换,状态是行为随内部状态改变
- 装饰器vs代理:装饰器重在增强功能,代理重在控制访问
-
忽视线程安全:比如懒汉式单例没加volatile,工厂类没做并发控制等。
-
死板套用GOF:现在很多场景有更优雅的实现,比如用函数式接口替代部分策略模式,用Spring事件机制代替手动实现的观察者。
7. 现代Java中的模式新写法
随着Java语言发展,有些模式有了更简洁的实现:
- Lambda实现策略模式:
java复制public void processOrder(Order order, Consumer<Order> promotionStrategy) {
// 前置处理
promotionStrategy.accept(order);
// 后置处理
}
// 调用
processOrder(order, o -> o.setDiscount(new BigDecimal("50")));
- 方法引用实现命令模式:
java复制public class Operation {
public static void saveToDB(Data data) {
// 保存逻辑
}
}
// 命令对象
Runnable command = () -> Operation.saveToDB(data);
commandExecutor.execute(command);
- Spring事件机制实现观察者:
java复制@Component
public class EmailListener {
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
// 发送邮件
}
}
真正用好设计模式的关键,在于理解其思想本质而非死记硬背类图。当遇到重复的代码坏味道时,能自然想到"这个问题好像可以用XX模式解决",这才是真正掌握了设计模式。