刚入行那会儿,我总觉得设计模式是那些架构师才需要关心的高级玩意儿。直到有次接手一个祖传代码库,看到满屏的if-else和重复代码时,才意识到不懂设计模式就像拿着螺丝刀修汽车——不是不能修,但效率低得可怕。
设计模式本质上是前辈们总结出来的最佳实践套路。就像做菜有"红烧""清蒸"等固定做法,软件开发中面对特定场景时,用对设计模式能让代码:
Java的23种经典设计模式,按用途可分为三大类:
重要提示:不要为了用模式而用模式。我见过最糟糕的代码,是把所有模式都塞进一个项目里,结果比不用还难维护。
新手最爱用也最容易被误用的模式。去年我们系统就因单例导致内存泄漏——某个"全局配置"单例持有了Activity引用。
安全实现要点:
java复制public class SafeSingleton {
// volatile保证可见性
private static volatile SafeSingleton instance;
private SafeSingleton() {}
public static SafeSingleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (SafeSingleton.class) {
if (instance == null) { // 第二次检查
instance = new SafeSingleton();
}
}
}
return instance;
}
}
实际应用场景:
血泪教训:在Spring等框架中,默认Bean就是单例的,再套单例模式会导致诡异问题。
这两个模式经常被混淆。简单来说:
电商系统案例:
java复制// 支付方式工厂
interface PaymentFactory {
Payment createPayment();
Refund createRefund();
}
// 支付宝产品族
class AlipayFactory implements PaymentFactory {
public Payment createPayment() { return new Alipay(); }
public Refund createRefund() { return new AlipayRefund(); }
}
// 微信支付产品族
class WechatPayFactory implements PaymentFactory {
public Payment createPayment() { return new WechatPay(); }
public Refund createRefund() { return new WechatPayRefund(); }
}
IO流是装饰器模式的经典实现。但实际开发中,我们更常用它来做业务增强。
权限校验场景:
java复制interface DataService {
String fetchData();
}
class BasicDataService implements DataService {
public String fetchData() { return "核心数据"; }
}
class AuthDecorator implements DataService {
private DataService wrappee;
public AuthDecorator(DataService service) {
this.wrappee = service;
}
public String fetchData() {
if(checkPermission()) {
return wrappee.fetchData();
}
throw new SecurityException("无权限访问");
}
private boolean checkPermission() {
// 实际项目会结合Spring Security等框架
return true;
}
}
// 使用方式
DataService service = new AuthDecorator(new BasicDataService());
去年接手的老系统需要对接新支付网关,但接口完全不兼容。用适配器模式三天搞定:
java复制// 老系统接口
interface OldPayment {
void pay(int dollars);
}
// 新支付SDK
class NewPaymentGateway {
void processPayment(float yuan) {
// 新网关的实现
}
}
// 适配器
class PaymentAdapter implements OldPayment {
private NewPaymentGateway gateway = new NewPaymentGateway();
public void pay(int dollars) {
float yuan = dollars * 6.5f; // 汇率转换
gateway.processPayment(yuan);
}
}
不用再自己实现Subject/Observer接口了,Java自带:
java复制// 使用PropertyChangeSupport
class Order {
private String status;
private PropertyChangeSupport support = new PropertyChangeSupport(this);
public void addObserver(PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
public void setStatus(String newStatus) {
String old = this.status;
this.status = newStatus;
support.firePropertyChange("status", old, newStatus);
}
}
// 监听器
class LogisticsTracker implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent evt) {
if("status".equals(evt.getPropertyName())) {
System.out.println("物流状态更新:" + evt.getNewValue());
}
}
}
传统策略模式需要定义一堆类,Java8后可以用Lambda简化:
java复制// 传统方式
interface DiscountStrategy {
double applyDiscount(double amount);
}
class ChristmasDiscount implements DiscountStrategy {
public double applyDiscount(double amount) {
return amount * 0.8;
}
}
// Java8方式
class Order {
private DoubleUnaryOperator discountStrategy = a -> a; // 默认无折扣
public void setDiscountStrategy(DoubleUnaryOperator strategy) {
this.discountStrategy = strategy;
}
public double calculateTotal() {
double subtotal = 100.0; // 假设金额
return discountStrategy.applyAsDouble(subtotal);
}
}
// 使用
Order order = new Order();
order.setDiscountStrategy(amount -> amount > 200 ? amount * 0.9 : amount);
综合运用多个模式的实际案例:
java复制// 订单创建 - 工厂方法
interface OrderFactory {
Order createOrder(User user);
}
// 订单处理 - 责任链
interface OrderHandler {
void setNext(OrderHandler next);
void handle(Order order);
}
// 支付处理 - 策略
interface PaymentStrategy {
boolean pay(Order order);
}
// 典型调用流程
Order order = new VIPOrderFactory().createUser(user);
new ValidationHandler()
.setNext(new InventoryCheckHandler())
.setNext(new PaymentHandler())
.handle(order);
// 配合Spring的依赖注入
@Bean
public PaymentStrategy alipayStrategy() {
return order -> { /* 支付宝实现 */ };
}
@Bean
public PaymentStrategy wechatPayStrategy() {
return order -> { /* 微信支付实现 */ };
}
过度设计警告:在简单CRUD项目里用全套设计模式,就像用航天飞机送外卖
单例的线程安全问题:即使双重检查锁,在某些JVM实现上仍可能出问题
观察者内存泄漏:忘了移除监听器会导致对象无法回收
滥用继承:能用组合(装饰器/策略)就别用继承
模式混用冲突:比如在Spring管理的Bean中使用单例模式
实用建议:先写"脏代码"实现功能,再考虑用模式重构。一开始就追求完美设计往往事倍功半。
随着Java语言发展,一些模式有了新写法:
最后记住:设计模式是手段不是目的。我见过最优雅的系统,不是用了最多模式的,而是用最简单方案解决复杂问题的。当你发现自己在强行套用模式时,停下来想想——这个场景真的需要吗?