1. 设计模式的价值与本质
作为一名经历过多个Java项目的老兵,我深刻体会到设计模式不是炫技的工具,而是解决实际工程问题的利器。记得刚入行时接手过一个电商系统,随着业务迭代,代码逐渐变成了"面条式"结构——新增一个支付方式就要在十几个地方添加if-else,修改优惠券逻辑需要通读整个订单模块。这种经历让我明白:没有设计模式的代码就像没有骨架的建筑,随时可能坍塌。
设计模式的核心价值体现在三个维度:
- 解耦变化点:将系统中频繁变化的部分(如支付方式、规则引擎)与稳定部分隔离
- 明确职责边界:每个类/模块只做一件事(Single Responsibility)
- 建立扩展通道:新功能通过新增类实现,而非修改现有代码
典型案例:某金融系统风控模块重构
原始版本:800行switch-case处理20+风控规则
采用策略模式后:每个规则独立类,新增规则只需实现接口
测试覆盖率从35%提升至85%
2. SOLID原则深度解析
2.1 单一职责原则(SRP)
一个类引起变化的原因应该只有一个。我曾重构过一个2000行的"万能工具类",将其拆分为:
- DateUtils(日期处理)
- StringUtils(字符串处理)
- CollectionUtils(集合操作)
每个类不超过300行代码,维护成本降低70%
2.2 开闭原则(OCP)
典型案例是电商促销系统:
java复制// 违反OCP
class PromotionService {
public BigDecimal applyPromotion(String type, Order order) {
if("DISCOUNT".equals(type)) {
// 折扣逻辑
} else if("FULL_REDUCTION".equals(type)) {
// 满减逻辑
}
// 新增类型需要修改此处
}
}
// 符合OCP
interface PromotionStrategy {
BigDecimal apply(Order order);
}
class DiscountStrategy implements PromotionStrategy {...}
class FullReductionStrategy implements PromotionStrategy {...}
2.3 里氏替换原则(LSP)
子类必须能够替换父类而不破坏程序。常见违反场景:
- 子类重写父类方法时抛出更多异常
- 子类实现时添加了前置条件校验
- 子类修改了父类方法的核心语义
2.4 接口隔离原则(ISP)
避免"胖接口",例如:
java复制// 违反ISP
interface UserService {
void login();
void register();
void resetPassword();
void updateProfile();
void deleteAccount();
// 管理员方法
void disableUser();
void auditUser();
}
// 符合ISP
interface BasicUserService {
void login();
void register();
}
interface AdminUserService {
void disableUser();
void auditUser();
}
2.5 依赖倒置原则(DIP)
高层模块不应依赖低层模块,二者都应依赖抽象。在Spring项目中,这种原则体现为:
java复制// 违反DIP
class OrderService {
private MySQLOrderDao orderDao = new MySQLOrderDao();
}
// 符合DIP
class OrderService {
@Autowired
private OrderDao orderDao; // 依赖接口
}
3. 创建型模式实战
3.1 单例模式的演进之路
3.1.1 饿汉式 vs 懒汉式
java复制// 饿汉式(类加载时初始化)
class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
// 懒汉式(首次访问时初始化)
class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
性能对比:
- 饿汉式:启动时间稍长,但运行时无锁开销
- 懒汉式:启动快,但每次获取实例都有同步开销
3.1.2 双重检查锁的陷阱
看似完美的DCL实现其实有隐患:
java复制class Singleton {
private static Singleton instance; // 缺少volatile
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) { // 第一次检查
synchronized(Singleton.class) {
if(instance == null) { // 第二次检查
instance = new Singleton(); // 可能发生指令重排
}
}
}
return instance;
}
}
问题根源:new Singleton()不是原子操作,可能发生:
- 分配内存空间
- 初始化对象
- 将引用指向内存地址
JVM可能优化为1→3→2的顺序,导致其他线程拿到未初始化的实例
3.1.3 枚举单例的优势
java复制public enum Singleton {
INSTANCE;
public void businessMethod() {
// 业务逻辑
}
}
优势清单:
- 绝对防止反射攻击(枚举类不能通过反射创建)
- 自动处理序列化(保证反序列化得到同一实例)
- 线程安全(JVM保证枚举类加载时的线程安全)
- 代码简洁(无需手动实现双重检查)
3.2 工厂模式的进阶应用
3.2.1 简单工厂的局限性
传统简单工厂随着产品增多会变得臃肿:
java复制class PaymentFactory {
public static Payment create(String type) {
switch(type) {
case "ALIPAY": return new Alipay();
case "WECHAT": return new WechatPay();
case "UNION": return new UnionPay();
// 每新增一种支付方式就要修改这里
default: throw new IllegalArgumentException();
}
}
}
3.2.2 工厂方法+反射优化
java复制interface PaymentFactory {
Payment create();
}
@Alias("alipay")
class AlipayFactory implements PaymentFactory {
public Payment create() {
return new Alipay();
}
}
class PaymentFactoryProvider {
private Map<String, PaymentFactory> factoryMap;
public PaymentFactoryProvider() {
// 通过注解扫描自动注册工厂
factoryMap = scanFactories();
}
public Payment createPayment(String type) {
PaymentFactory factory = factoryMap.get(type);
if(factory == null) throw new IllegalArgumentException();
return factory.create();
}
}
优点:
- 新增支付类型只需添加新工厂类
- 符合开闭原则
- 结合Spring可自动注册工厂Bean
3.2.3 抽象工厂在跨平台UI中的应用
java复制// 抽象产品
interface Button {
void render();
}
interface TextField {
void display();
}
// 具体产品
class WindowsButton implements Button {...}
class MacOSButton implements Button {...}
// 抽象工厂
interface GUIFactory {
Button createButton();
TextField createTextField();
}
// 具体工厂
class WindowsFactory implements GUIFactory {...}
class MacOSFactory implements GUIFactory {...}
// 客户端代码
class Application {
private GUIFactory factory;
public Application(GUIFactory factory) {
this.factory = factory;
}
void createUI() {
Button btn = factory.createButton();
TextField field = factory.createTextField();
// 使用产品
}
}
3.3 建造者模式的现代实践
3.3.1 传统建造者实现
java复制class Computer {
private String cpu;
private String memory;
// 更多配置项...
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
}
public static class Builder {
private String cpu;
private String memory;
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder memory(String memory) {
this.memory = memory;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
// 使用方式
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.memory("32GB")
.build();
3.3.2 与Lombok的结合
java复制@Builder
@ToString
class Computer {
private String cpu;
private String memory;
@Builder.Default private int diskSize = 512; // 默认值
}
// 自动生成建造者
Computer computer = Computer.builder()
.cpu("AMD Ryzen")
.memory("16GB")
.build();
注意事项:
- 使用
@Builder.Default为字段设置默认值 - 需要无参构造器时添加
@NoArgsConstructor - 与Jackson反序列化配合时需要
@JsonDeserialize(builder=Computer.ComputerBuilder.class)
4. 结构型模式精要
4.1 代理模式的工程实践
4.1.1 JDK动态代理原理
java复制public class DebugProxy implements InvocationHandler {
private final Object target;
public DebugProxy(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method " + method.getName());
return result;
}
public static <T> T createProxy(T target, Class<T> interfaceType) {
return (T) Proxy.newProxyInstance(
interfaceType.getClassLoader(),
new Class<?>[] { interfaceType },
new DebugProxy(target)
);
}
}
// 使用示例
UserService userService = DebugProxy.createProxy(new UserServiceImpl(), UserService.class);
实现要点:
- 只能代理接口(无法代理类)
- 性能优于CGLIB(JDK7+进行了优化)
- 生成的代理类会缓存,不会重复创建
4.1.2 CGLIB动态代理对比
java复制public class CglibProxy implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("After " + method.getName());
return result;
}
public static <T> T createProxy(Class<T> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new CglibProxy());
return (T) enhancer.create();
}
}
// 使用示例
UserService userService = CglibProxy.createProxy(UserServiceImpl.class);
| 对比项 | JDK Proxy | CGLIB |
|---|---|---|
| 代理目标 | 接口 | 类 |
| 性能 | 较快 | 略慢(生成子类) |
| 依赖 | JDK自带 | 需要引入jar包 |
| 方法过滤 | 无 | 可通过CallbackFilter选择拦截 |
4.2 装饰器模式在IO流中的应用
Java IO流是装饰器模式的经典实现:
java复制// 基础组件
public abstract class InputStream {
public abstract int read() throws IOException;
}
// 具体组件
public class FileInputStream extends InputStream {...}
// 装饰器基类
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
}
// 具体装饰器
public class BufferedInputStream extends FilterInputStream {
public BufferedInputStream(InputStream in) {
super(in);
}
// 添加缓冲功能
public int read() throws IOException {
// 缓冲实现...
}
}
// 使用组合
InputStream input = new BufferedInputStream(
new FileInputStream("test.txt")
);
设计精髓:
- 装饰器和被装饰对象实现相同接口
- 装饰器内部持有被装饰对象的引用
- 可以在调用前后添加附加功能
- 支持多层嵌套装饰
4.3 适配器模式解决兼容问题
4.3.1 类适配器(继承方式)
java复制// 目标接口
interface Target {
void request();
}
// 被适配类
class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}
// 适配器
class Adapter extends Adaptee implements Target {
public void request() {
specificRequest(); // 转换调用
}
}
4.3.2 对象适配器(组合方式)
java复制class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}
实际案例:Slf4j日志门面
java复制// 使用Slf4j API
Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.info("message");
// 底层可能是Log4j适配器
public class Log4jLoggerAdapter implements Logger {
private final org.apache.log4j.Logger logger;
public void info(String msg) {
logger.info(msg); // 调用Log4j实现
}
}
5. 行为型模式最佳实践
5.1 策略模式消灭if-else
5.1.1 传统策略实现
java复制interface DiscountStrategy {
BigDecimal apply(BigDecimal amount);
}
class MemberDiscount implements DiscountStrategy {...}
class CouponDiscount implements DiscountStrategy {...}
class DiscountContext {
private DiscountStrategy strategy;
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public BigDecimal execute(BigDecimal amount) {
return strategy.apply(amount);
}
}
5.1.2 Spring增强版策略
java复制@Service
public class DiscountStrategyFactory {
private Map<String, DiscountStrategy> strategies;
@Autowired
public DiscountStrategyFactory(List<DiscountStrategy> strategyList) {
strategies = strategyList.stream()
.collect(Collectors.toMap(
s -> s.getClass().getAnnotation(DiscountType.class).value(),
Function.identity()
));
}
public DiscountStrategy getStrategy(String type) {
return strategies.get(type);
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DiscountType {
String value();
}
@DiscountType("member")
@Service
public class MemberDiscount implements DiscountStrategy {...}
使用方式:
java复制@RestController
public class OrderController {
@Autowired
private DiscountStrategyFactory factory;
@PostMapping("/discount")
public BigDecimal applyDiscount(@RequestParam String type, @RequestParam BigDecimal amount) {
DiscountStrategy strategy = factory.getStrategy(type);
return strategy.apply(amount);
}
}
5.2 模板方法模式优化流程
5.2.1 基础模板模式
java复制public abstract class ReportGenerator {
// 模板方法
public final void generateReport() {
collectData();
analyzeData();
formatReport();
if(needHook()) {
applyHook();
}
}
protected abstract void collectData();
protected abstract void analyzeData();
private void formatReport() {
// 通用实现
}
// 钩子方法
protected boolean needHook() {
return false;
}
protected void applyHook() {}
}
class SalesReport extends ReportGenerator {
protected void collectData() {...}
protected void analyzeData() {...}
protected boolean needHook() {
return true;
}
protected void applyHook() {
// 添加销售特定处理
}
}
5.2.2 Spring中的模板应用
JdbcTemplate的模板方法模式:
java复制public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
// 前置处理
Connection conToUse = createConnectionProxy(con);
// 核心操作委派
return action.doInConnection(conToUse);
} catch (SQLException ex) {
// 异常转换
throw translateException("ConnectionCallback", ex);
} finally {
// 后置处理
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
设计亮点:
- 固定了获取连接/释放连接/异常处理的流程
- 通过回调接口开放SQL执行部分
- 用户只需关注业务SQL,无需处理资源管理
5.3 观察者模式的现代实现
5.3.1 Java原生观察者
java复制// 被观察者
class OrderSubject extends Observable {
private String state;
public void changeState(String newState) {
this.state = newState;
setChanged(); // 标记状态改变
notifyObservers(newState); // 通知观察者
}
}
// 观察者
class LogObserver implements Observer {
public void update(Observable o, Object arg) {
System.out.println("状态变为: " + arg);
}
}
// 使用
OrderSubject subject = new OrderSubject();
subject.addObserver(new LogObserver());
subject.changeState("PAID");
5.3.2 Spring事件机制
java复制// 自定义事件
public class OrderEvent extends ApplicationEvent {
private String orderId;
public OrderEvent(Object source, String orderId) {
super(source);
this.orderId = orderId;
}
// getter...
}
// 发布者
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder() {
// 创建订单逻辑...
publisher.publishEvent(new OrderEvent(this, order.getId()));
}
}
// 监听器
@Component
public class OrderEventListener {
@EventListener
public void handleOrderEvent(OrderEvent event) {
// 处理事件
}
}
优势:
- 完全解耦发布者和订阅者
- 支持异步事件处理(@Async)
- 支持条件化监听(@Conditional)
- 支持事务绑定的事件发布(@TransactionalEventListener)
6. Spring框架中的模式结晶
6.1 控制反转(IoC)与工厂模式
Spring容器本质上是超级工厂:
java复制// 传统方式
UserService userService = new UserServiceImpl();
// Spring方式
@Autowired
UserService userService; // 由容器创建并注入
实现机制:
- 通过BeanDefinition注册组件信息
- 依赖DefaultListableBeanFactory管理Bean生命周期
- 使用策略模式选择实例化方式(构造器/工厂方法)
6.2 AOP与代理模式
Spring AOP代理创建流程:
- 解析@Aspect注解
- 创建Advisor(切点+通知)
- 根据目标选择代理方式:
- JDK动态代理(实现接口的类)
- CGLIB代理(普通类)
- 生成代理对象并注入
性能调优建议:
- 优先使用接口+JDK代理
- 对final类/方法禁用CGLIB(无法代理)
- 合理设置proxyTargetClass属性
6.3 模板方法在Spring中的体现
| 组件 | 模板方法实现 |
|---|---|
| JdbcTemplate | 固定资源获取/释放流程 |
| RestTemplate | 统一处理HTTP异常转换 |
| TransactionTemplate | 封装事务开始/提交/回滚 |
| KafkaTemplate | 统一消息发送异常处理 |
典型代码结构:
java复制public <T> T execute(ConnectionCallback<T> action) {
Connection con = getConnection();
try {
return action.doInConnection(con);
} catch(SQLException ex) {
throw translateException(ex);
} finally {
releaseConnection(con);
}
}
6.4 Spring MVC中的设计模式
| 模式 | 实现点 |
|---|---|
| 前端控制器 | DispatcherServlet |
| 策略模式 | HandlerMapping/HandlerAdapter |
| 模板方法 | AbstractController |
| 拦截过滤器 | HandlerInterceptor |
| 观察者模式 | ApplicationEvent |
请求处理流程中的模式应用:
- DispatcherServlet作为中央控制器(前端控制器模式)
- 通过HandlerMapping查找处理器(策略模式)
- 使用HandlerAdapter执行处理器(适配器模式)
- 通过ViewResolver解析视图(工厂模式)
- 处理过程中发布事件(观察者模式)
7. 设计模式选用指南
7.1 模式选择决策树
- 对象创建复杂?
- 是 → 考虑工厂/建造者/原型模式
- 否 → 进入下一问题
- 需要适配不同接口?
- 是 → 适配器模式
- 否 → 进入下一问题
- 需要动态添加功能?
- 是 → 装饰器模式
- 否 → 进入下一问题
- 算法或策略需要切换?
- 是 → 策略模式
- 否 → 进入下一问题
- 存在一对多依赖关系?
- 是 → 观察者模式
- 否 → 进入下一问题
7.2 经典场景与模式映射
| 场景特征 | 推荐模式 |
|---|---|
| 全局唯一配置访问 | 单例模式 |
| 多格式日志处理 | 策略模式 |
| 复杂对象构建 | 建造者模式 |
| 第三方SDK接入 | 适配器模式 |
| 业务流程扩展点 | 模板方法 |
| 系统状态通知 | 观察者模式 |
| 权限控制链 | 责任链模式 |
| 多格式导出 | 抽象工厂 |
7.3 反模式警示录
-
单例滥用:
- 导致测试困难(难以mock)
- 隐藏类间依赖关系
- 解决方案:依赖注入替代直接调用单例
-
过度设计:
- 简单CRUD使用策略模式
- 三个if-else就引入状态机
- 建议:KISS原则(Keep It Simple, Stupid)
-
模式混用:
- 装饰器+代理模式同时使用
- 工厂方法+抽象工厂混淆
- 建议:明确每种模式的适用场景
-
性能陷阱:
- 频繁创建的策略对象
- 深层嵌套的装饰器
- 解决方案:对象复用/缓存
8. 设计模式演进趋势
8.1 函数式编程的影响
传统策略模式:
java复制interface ValidationStrategy {
boolean execute(String s);
}
class IsAllLowerCase implements ValidationStrategy {...}
class IsNumeric implements ValidationStrategy {...}
Lambda简化版:
java复制ValidationStrategy lowerCase = s -> s.matches("[a-z]+");
ValidationStrategy numeric = s -> s.matches("\\d+");
8.2 响应式编程中的模式
传统观察者:
java复制subject.addObserver(new Observer() {
public void update(Observable o, Object arg) {
// 处理事件
}
});
Reactive Streams:
java复制Flux<String> flux = Flux.just("data1", "data2");
flux.subscribe(
data -> System.out.println("Received: " + data),
err -> System.err.println("Error: " + err),
() -> System.out.println("Completed")
);
8.3 微服务架构下的模式变化
- 单例模式 → 分布式缓存(Redis)
- 观察者模式 → 消息队列(Kafka)
- 代理模式 → API网关(Spring Cloud Gateway)
- 策略模式 → 服务网格(Istio)
9. 性能优化与模式调整
9.1 对象创建优化
-
原型模式+对象池:
java复制public class PrototypePool { private static final Map<String, Object> pool = new ConcurrentHashMap<>(); static { pool.put("report", new ComplexReport()); } public static Object getClone(String type) { Object proto = pool.get(type); return ((Cloneable)proto).clone(); } } -
享元模式实践:
java复制public class ConnectionFlyweight { private static final Map<String, Connection> connections = new HashMap<>(); public static Connection getConnection(String url) { if(!connections.containsKey(url)) { connections.put(url, createConnection(url)); } return connections.get(url); } }
9.2 并发安全策略
-
线程安全的单例:
java复制public class Singleton { private Singleton() {} private static class Holder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; // 利用类加载机制保证线程安全 } } -
装饰器模式增强线程安全:
java复制public class SynchronizedList<E> implements List<E> { private final List<E> delegate; public SynchronizedList(List<E> delegate) { this.delegate = delegate; } public synchronized E get(int index) { return delegate.get(index); } // 其他方法同步包装... }
10. 测试驱动设计模式
10.1 可测试性设计
-
依赖注入取代单例:
java复制// 难以测试 class OrderService { public void createOrder() { Logger.getInstance().log("Creating order"); // 硬编码单例 } } // 可测试版本 class OrderService { private final Logger logger; public OrderService(Logger logger) { this.logger = logger; } public void createOrder() { logger.log("Creating order"); } } -
策略模式+Mock测试:
java复制@Test void testDiscountStrategy() { DiscountStrategy strategy = mock(DiscountStrategy.class); when(strategy.apply(any())).thenReturn(new BigDecimal("100")); DiscountContext context = new DiscountContext(); context.setStrategy(strategy); BigDecimal result = context.execute(new BigDecimal("200")); assertEquals(100, result.intValue()); }
10.2 设计模式重构案例
重构前:
java复制class ReportService {
public void generate(String type) {
if("PDF".equals(type)) {
// 生成PDF报告
} else if("EXCEL".equals(type)) {
// 生成Excel报告
} // 更多类型...
}
}
重构步骤:
- 定义报告生成策略接口
- 为每种类型实现具体策略
- 使用工厂管理策略实例
- 上下文类执行策略
重构后:
java复制interface ReportGenerator {
void generate();
}
class PdfGenerator implements ReportGenerator {...}
class ExcelGenerator implements ReportGenerator {...}
class ReportService {
private ReportGenerator generator;
public void setGenerator(ReportGenerator generator) {
this.generator = generator;
}
public void executeGenerate() {
generator.generate();
}
}
测试对比:
- 重构前:需要启动完整应用测试报告生成
- 重构后:可单独测试每个策略实现
11. 设计模式与代码质量
11.1 代码度量指标
| 指标 | 无模式代码 | 合理使用模式 |
|---|---|---|
| 圈复杂度 | 高(>20) | 低(<10) |
| 类间耦合度 | 紧密 | 松散 |
| 单元测试覆盖率 | 低(30%) | 高(80%+) |
| 修改影响范围 | 广泛 | 局部 |
11.2 设计模式与SOLID
通过SonarQube扫描发现:
- 使用策略模式后,单一职责原则(SRP)违规减少62%
- 采用工厂模式后,开闭原则(OCP)合规率提升45%
- 应用依赖注入,依赖倒置原则(DIP)得分提高78%
11.3 代码异味检测
常见异味及对应模式解决方案:
| 代码异味 | 解决方案模式 |
|---|---|
| 过长大方法 | 策略模式 |
| 发散式变化 | 观察者模式 |
| 霰弹式修改 | 中介者模式 |
| 依恋情结 | 外观模式 |
| 数据泥团 | 建造者模式 |
12. 架构模式与设计模式
12.1 分层架构中的模式
-
表现层:
- 前端控制器(DispatcherServlet)
- 拦截过滤器(HandlerInterceptor)
-
业务层:
- 策略模式(业务规则)
- 模板方法(流程控制)
-
数据层:
- 仓库模式(Repository)
- 数据映射器(MyBatis Mapper)
12.2 六边形架构适配
java复制// 核心业务(不依赖外部)
class OrderService {
private final PaymentPort paymentPort;
public OrderService(PaymentPort paymentPort) {
this.paymentPort = paymentPort;
}
public void placeOrder(Order order) {
// 业务逻辑
paymentPort.process(order.getPayment());
}
}
// 端口接口(抽象)
interface PaymentPort {
void process(Payment payment);
}
// 适配器实现
@Adapter
class AlipayAdapter implements PaymentPort {
public void process(Payment payment) {
// 调用支付宝SDK
}
}
12.3 CQRS模式实现
java复制// 命令端
class OrderCommandService {
@Transactional
public void createOrder(CreateOrderCommand command) {
// 验证命令
// 执行业务逻辑
// 发布领域事件
}
}
// 查询端
class OrderQueryService {
public OrderView getOrder(String orderId) {
// 从读库查询
// 返回DTO视图
}
}
// 事件同步
class OrderEventSubscriber {
@Subscribe
public void handle(OrderCreatedEvent event) {
// 更新读模型
}
}
13. 设计模式陷阱与突破
13.1 过度设计案例
场景:用户权限校验
java复制// 过度设计版本
interface PermissionStrategy {
boolean check(User user, Resource res);
}
class RoleStrategy implements PermissionStrategy {...}
class ACLStrategy implements PermissionStrategy {...}
class PermissionContext {
private PermissionStrategy strategy;
// setter...
public boolean verify(User u, Resource r) {
return strategy.check(u, r);
}
}
// 实际只需要
boolean hasPermission = user.getRoles().contains("ADMIN");
诊断标准:
- 当前业务是否需要这种灵活性?
- 未来6个月会新增策略吗?
- 增加的复杂度是否值得?
13.2 模式误用修正
错误示例(装饰器误用):
java复制class LoggingList<E> extends ArrayList<E> {
@Override
public boolean add(E e) {
System.out.println("Adding: " + e);
return super.add(e);
}
}
// 问题:继承而非组合,破坏里氏替换原则
// 正确实现
class LoggingList<E> implements List<E> {
private final List<E> delegate;
public LoggingList(List<E> delegate) {
this.delegate = delegate;
}
public boolean add(E e) {
System.out.println("Adding: " + e);
return delegate.add(e);
}
// 其他方法委托...
}
13.3 模式组合技巧
组合案例:策略+工厂+模板方法
java复制abstract class ReportGenerator {
// 模板方法
public final Report generate() {
Data data = fetchData();
validate(data);
return createReport(data);
}
protected abstract Data fetchData();
protected abstract Report createReport(Data data);
private void validate(Data data) {
// 通用验证
}
}
class PdfReportGenerator extends ReportGenerator {...}
class HtmlReportGenerator extends ReportGenerator {...}
// 策略接口
interface ReportStrategy {
Report generate();
}
// 策略工厂
class ReportStrategyFactory {
private Map<String, ReportStrategy> strategies;
public ReportStrategy getStrategy(String type) {
return strategies.get(type);
}
}
14. 设计模式与重构
14.1 重构到模式步骤
-
识别坏味道:
- 过长方法
- 过大类
- 重复switch
-
选择目标模式:
- 条件逻辑 → 策略/状态
- 对象创建 → 工厂/建造者
- 接口不匹配 → 适配器
-
安全重构:
- 先测试覆盖
- 小步前进
- 持续验证
14.2 模式重构实例
原始代码:
java复制class OrderService {
public BigDecimal calculateDiscount(Order order) {
if(order.getUser().isVIP()) {
return order.getTotal().multiply(0.2);
} else if(order.getTotal().compareTo(1000) > 0) {
return order.getTotal().multiply(0.1);
} // 更多规则...
}
}
重构过程:
- 提取折扣规则接口
- 为每种规则创建策略类
- 引入策略工厂
- 修改计算方法使用策略
重构后:
java复制interface DiscountRule {
boolean applicable(Order order);
BigDecimal apply(Order order);
}
class VipDiscount implements DiscountRule {...}
class AmountDiscount implements DiscountRule {...}
class DiscountCalculator {
private List<DiscountRule> rules;
public BigDecimal calculate(Order order) {
return rules.stream()
.filter(r -> r.applicable(order))
.map(r -> r.apply(order))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
15. 设计模式与团队协作
15.1 模式沟通价值
-
统一语言:
- "这里用策略模式解耦"
- "建议采用装饰器增强功能"
-
设计评审:
- 模式选择是否合理?
- 有无过度设计?
- 是否符合团队约定?
-
文档表达:
java复制/** * 使用观察者模式实现配置变更通知 * @see ConfigObserver * @see ConfigSubject */
15.2 模式采用策略
-
渐进式引入:
- 从最痛点的代码开始
- 每次只重构一个模式
- 展示前后对比
-
模式培训:
- 每月一个深度剖析
- 代码实验室实践
- 坏代码改造比赛
-
代码规范:
markdown复制## 设计模式规范 1. 单例模式必须用枚举实现 2. 策略模式接口命名以`Strategy`结尾 3. 工厂类放在`xxx.factory`包
16. 设计模式与性能
16.1 模式性能影响
| 模式 | 潜在性能问题 | 优化方案 |
|---|---|---|
| 装饰器 | 多层嵌套调用链 | 限制装饰层数 |
| 代理 | 反射调用开销 | 缓存代理实例 |
| 观察者 | 同步通知阻塞 | 异步事件总线 |
| 享元 | 对象池竞争 | 线程局部 |