常用设计模式详解

从理论到框架实践

设计模式是软件开发中经过验证的最佳实践,能够有效解决代码复用、解耦和扩展性问题。本文将深入解析创建型、结构型、行为型三大类中最常用的设计模式,提供完整Java代码示例,并结合Spring、MyBatis等主流框架的源码场景,展示设计模式的工业级应用。

一、创建型模式:对象实例化的艺术

1.1 单例模式(Singleton Pattern)

定义:确保一个类仅有一个实例,并提供全局访问点。
核心价值:控制资源访问、减少对象创建开销(如数据库连接池、日志对象)。

代码实现:五种经典单例
实现方式线程安全延迟加载防止反射/序列化代码示例
饿汉式✅ 天然安全❌ 类加载时初始化❌ 不能public class EagerSingleton { private static final EagerSingleton INSTANCE = new EagerSingleton(); private EagerSingleton() {} public static EagerSingleton getInstance() { return INSTANCE; }}
懒汉式(加锁)✅ 方法级synchronized✅ 首次调用时初始化❌ 不能public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; }}
双重检查锁(DCL)✅ volatile+同步块✅ 延迟初始化❌ 不能public class DCLSingleton { private static volatile DCLSingleton instance; private DCLSingleton() {} public static DCLSingleton getInstance() { if (instance == null) { synchronized (DCLSingleton.class) { if (instance == null) { instance = new DCLSingleton(); } } } return instance; }}
静态内部类✅ JVM类加载机制✅ 内部类加载时初始化❌ 不能public class InnerClassSingleton { private InnerClassSingleton() {} private static class Holder { private static final InnerClassSingleton INSTANCE = new InnerClassSingleton(); } public static InnerClassSingleton getInstance() { return Holder.INSTANCE; }}
枚举单例✅ JVM保证❌ 枚举类加载时初始化✅ 天然防止public enum EnumSingleton { INSTANCE; public void doSomething() { System.out.println("Singleton method called"); }}
框架应用:Spring中的单例实现

Spring容器默认对Bean采用单例模式,核心实现位于DefaultSingletonBeanRegistry类,通过三级缓存解决循环依赖问题:

  • 一级缓存(singletonObjects):存储完全初始化的单例Bean
  • 二级缓存(earlySingletonObjects):存储提前暴露的未完全初始化Bean
  • 三级缓存(singletonFactories):存储Bean工厂,用于生成代理对象

源码关键逻辑

// DefaultSingletonBeanRegistry.java
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 一级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); // 二级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject(); // 从工厂获取对象(可能是代理)
                    this.earlySingletonObjects.put(beanName, singletonObject); // 放入二级缓存
                    this.singletonFactories.remove(beanName); // 移除三级缓存
                }
            }
        }
    }
    return singletonObject;
}

1.2 工厂模式(Factory Pattern)

定义:通过工厂接口封装对象创建逻辑,使客户端无需关注具体实现类。
类型:简单工厂、工厂方法、抽象工厂。

代码实现:工厂方法模式
// 产品接口
interface Shape { void draw(); }

// 具体产品
class Circle implements Shape { @Override public void draw() { System.out.println("Drawing Circle"); } }
class Rectangle implements Shape { @Override public void draw() { System.out.println("Drawing Rectangle"); } }

// 工厂接口
interface ShapeFactory { Shape getShape(); }

// 具体工厂
class CircleFactory implements ShapeFactory { @Override public Shape getShape() { return new Circle(); } }
class RectangleFactory implements ShapeFactory { @Override public Shape getShape() { return new Rectangle(); } }

// 使用示例
public class FactoryDemo {
    public static void main(String[] args) {
        ShapeFactory factory = new CircleFactory();
        Shape shape = factory.getShape();
        shape.draw(); // 输出: Drawing Circle
    }
}
框架应用:Spring的Bean工厂体系

Spring的IoC容器核心是工厂模式的实现,主要接口和类:

  • BeanFactory:基础工厂接口,定义getBean()等方法,实现类如XmlBeanFactory(已过时)
  • ApplicationContext:继承BeanFactory,提供事件传播、国际化等增强功能,实现类如ClassPathXmlApplicationContextAnnotationConfigApplicationContext
  • FactoryBean:自定义Bean创建逻辑的接口,例如DataSourceFactoryBean用于创建数据库连接池

示例:通过FactoryBean创建复杂对象

public class DataSourceFactoryBean implements FactoryBean<DataSource> {
    private String url;
    private String username;
    private String password;

    @Override
    public DataSource getObject() throws Exception {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(url);
        config.setUsername(username);
        config.setPassword(password);
        return new HikariDataSource(config); // 自定义连接池创建逻辑
    }

    @Override
    public Class<?> getObjectType() { return DataSource.class; }
}

// Spring配置
@Configuration
public class AppConfig {
    @Bean
    public DataSourceFactoryBean dataSource() {
        DataSourceFactoryBean factory = new DataSourceFactoryBean();
        factory.setUrl("jdbc:mysql://localhost:3306/test");
        factory.setUsername("root");
        factory.setPassword("123456");
        return factory;
    }
}

二、结构型模式:对象组合的设计

2.1 装饰器模式(Decorator Pattern)

定义:动态给对象添加额外功能,不改变其原有结构。
核心价值:功能扩展灵活(比继承更轻量),解决“类爆炸”问题。

代码实现:IO流中的装饰器
// 抽象构件
interface DataSource { void writeData(String data); }

// 具体构件(被装饰对象)
class FileDataSource implements DataSource {
    private String filename;
    public FileDataSource(String filename) { this.filename = filename; }
    @Override
    public void writeData(String data) { System.out.println("写入原始数据到文件: " + data); }
}

// 装饰器抽象类
abstract class DataSourceDecorator implements DataSource {
    protected DataSource wrappee;
    public DataSourceDecorator(DataSource source) { this.wrappee = source; }
    @Override
    public void writeData(String data) { wrappee.writeData(data); }
}

// 具体装饰器(加密功能)
class EncryptionDecorator extends DataSourceDecorator {
    public EncryptionDecorator(DataSource source) { super(source); }
    @Override
    public void writeData(String data) {
        String encrypted = encrypt(data); // 加密逻辑
        super.writeData(encrypted);
    }
    private String encrypt(String data) { return Base64.getEncoder().encodeToString(data.getBytes()); }
}

// 使用示例
public class DecoratorDemo {
    public static void main(String[] args) {
        DataSource source = new FileDataSource("test.txt");
        DataSource encryptedSource = new EncryptionDecorator(source);
        encryptedSource.writeData("敏感数据"); // 输出: 写入原始数据到文件: U2Vuc2l0aXZlIERhdGE=
    }
}
框架应用:MyBatis缓存模块

MyBatis的缓存体系完全基于装饰器模式,Cache接口为抽象构件,PerpetualCache为基础实现,其他装饰器动态添加功能:

  • LruCache:最近最少使用策略(缓存淘汰)
  • LoggingCache:输出缓存命中日志
  • SynchronizedCache:同步锁(线程安全)
  • SerializedCache:对象序列化存储

源码结构

// 抽象构件
public interface Cache {
    String getId();
    void putObject(Object key, Object value);
    Object getObject(Object key);
    Object removeObject(Object key);
    void clear();
}

// 具体构件(基础实现)
public class PerpetualCache implements Cache {
    private final String id;
    private final Map<Object, Object> cache = new HashMap<>(); // 核心存储结构
    // 实现Cache接口方法...
}

// 装饰器:LruCache(最近最少使用淘汰)
public class LruCache implements Cache {
    private final Cache delegate;
    private final Map<Object, Object> keyMap; // 记录访问顺序
    private Object eldestKey;

    public LruCache(Cache delegate) {
        this.delegate = delegate;
        this.keyMap = new LinkedHashMap<>(16, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<Object, Object> eldest) {
                boolean tooBig = size() > 1024; // 超过容量时淘汰最久未使用
                if (tooBig) eldestKey = eldest.getKey();
                return tooBig;
            }
        };
    }
    // 实现Cache接口方法,通过delegate调用基础缓存...
}

2.2 适配器模式(Adapter Pattern)

定义:将一个类的接口转换成客户端期望的另一种接口,解决接口不兼容问题。
核心价值:复用现有类,无需修改源码即可适配新接口。

代码实现:类适配器与对象适配器
// 目标接口(客户端期望的接口)
interface Target { void request(); }

// 被适配者(现有接口)
class Adaptee { public void specificRequest() { System.out.println("特殊请求(被适配接口)"); } }

// 类适配器(通过继承)
class ClassAdapter extends Adaptee implements Target {
    @Override
    public void request() { super.specificRequest(); } // 适配调用
}

// 对象适配器(通过组合)
class ObjectAdapter implements Target {
    private Adaptee adaptee;
    public ObjectAdapter(Adaptee adaptee) { this.adaptee = adaptee; }
    @Override
    public void request() { adaptee.specificRequest(); } // 适配调用
}

// 使用示例
public class AdapterDemo {
    public static void main(String[] args) {
        Target classAdapter = new ClassAdapter();
        classAdapter.request(); // 输出: 特殊请求(被适配接口)

        Target objectAdapter = new ObjectAdapter(new Adaptee());
        objectAdapter.request(); // 输出: 特殊请求(被适配接口)
    }
}
框架应用:Spring MVC的HandlerAdapter

Spring MVC中,DispatcherServlet通过HandlerAdapter适配不同类型的处理器(Controller),使调用统一化:

  • RequestMappingHandlerAdapter:适配@Controller注解的处理器方法
  • HttpRequestHandlerAdapter:适配实现HttpRequestHandler接口的处理器
  • SimpleControllerHandlerAdapter:适配实现Controller接口的传统处理器

核心流程

// DispatcherServlet核心代码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HandlerExecutionChain mappedHandler = getHandler(request); // 获取处理器
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 获取适配器
    ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler()); // 统一调用
    // ...视图渲染
}

// HandlerAdapter接口
public interface HandlerAdapter {
    boolean supports(Object handler); // 判断是否支持当前处理器
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

三、行为型模式:对象交互的策略

3.1 策略模式(Strategy Pattern)

定义:定义算法族,封装每个算法,使它们可互换。
核心价值:消除复杂条件判断,算法切换灵活。

代码实现:支付策略
// 策略接口
interface PaymentStrategy { void pay(double amount); }

// 具体策略
class AlipayStrategy implements PaymentStrategy {
    @Override public void pay(double amount) { System.out.println("支付宝支付: " + amount + "元"); }
}
class WechatPayStrategy implements PaymentStrategy {
    @Override public void pay(double amount) { System.out.println("微信支付: " + amount + "元"); }
}

// 上下文
class PaymentContext {
    private PaymentStrategy strategy;
    public void setStrategy(PaymentStrategy strategy) { this.strategy = strategy; }
    public void executePayment(double amount) { strategy.pay(amount); }
}

// 使用示例
public class StrategyDemo {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();
        context.setStrategy(new AlipayStrategy());
        context.executePayment(100); // 输出: 支付宝支付: 100.0元

        context.setStrategy(new WechatPayStrategy());
        context.executePayment(200); // 输出: 微信支付: 200.0元
    }
}
框架应用:Spring的资源访问策略

Spring的Resource接口定义资源访问策略,不同实现类适配不同资源类型:

  • ClassPathResource:类路径资源
  • FileSystemResource:文件系统资源
  • UrlResource:URL资源
  • ServletContextResource:Web应用资源

示例

Resource resource = new ClassPathResource("application.properties"); // 类路径策略
InputStream in = resource.getInputStream(); // 统一接口访问

3.2 代理模式(Proxy Pattern)

定义:为对象提供代理,控制对原对象的访问。
核心价值:增强功能(如日志、事务)、延迟加载、权限控制。

代码实现:JDK动态代理与CGLIB代理
代理方式实现原理目标要求性能特点
JDK动态代理实现InvocationHandler目标类需实现接口创建快,执行慢
CGLIB代理继承目标类,修改字节码无需接口,不能代理final类创建慢,执行快

JDK动态代理示例

// 目标接口
interface UserService { void update(); }

// 目标类
class UserServiceImpl implements UserService {
    @Override public void update() { System.out.println("执行更新操作"); }
}

// 代理处理器
class LogProxy implements InvocationHandler {
    private Object target;
    public LogProxy(Object target) { this.target = target; }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("日志: 方法执行前"); // 增强逻辑
        Object result = method.invoke(target, args); // 调用目标方法
        System.out.println("日志: 方法执行后");
        return result;
    }
}

// 使用示例
public class ProxyDemo {
    public static void main(String[] args) {
        UserService target = new UserServiceImpl();
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            new Class[]{UserService.class},
            new LogProxy(target)
        );
        proxy.update(); // 输出: 日志: 方法执行前 → 执行更新操作 → 日志: 方法执行后
    }
}
框架应用:Spring AOP的代理机制

Spring AOP基于代理模式实现,默认规则:

  • 目标类有接口 → 使用JDK动态代理JdkDynamicAopProxy
  • 目标类无接口 → 使用CGLIB代理CglibAopProxy

核心源码

// DefaultAopProxyFactory.java
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
        Class<?> targetClass = config.getTargetClass();
        if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
            return new JdkDynamicAopProxy(config); // JDK代理
        }
        return new ObjenesisCglibAopProxy(config); // CGLIB代理
    } else {
        return new JdkDynamicAopProxy(config);
    }
}

3.3 观察者模式(Observer Pattern)

定义:定义对象间一对多依赖,当主题状态变化时,所有观察者自动收到通知。
核心价值:解耦事件发布者与订阅者,支持动态扩展。

代码实现:自定义事件监听
// 主题接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// 观察者接口
interface Observer { void update(String message); }

// 具体主题
class NewsSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String message;

    @Override public void registerObserver(Observer observer) { observers.add(observer); }
    @Override public void removeObserver(Observer observer) { observers.remove(observer); }
    @Override public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(message); // 通知所有观察者
        }
    }
    public void setMessage(String message) {
        this.message = message;
        notifyObservers(); // 状态变化时触发通知
    }
}

// 具体观察者
class UserObserver implements Observer {
    private String name;
    public UserObserver(String name) { this.name = name; }
    @Override public void update(String message) {
        System.out.println(name + "收到新闻: " + message);
    }
}

// 使用示例
public class ObserverDemo {
    public static void main(String[] args) {
        NewsSubject subject = new NewsSubject();
        subject.registerObserver(new UserObserver("张三"));
        subject.registerObserver(new UserObserver("李四"));
        subject.setMessage("设计模式专栏更新啦!"); // 输出: 张三收到新闻... 李四收到新闻...
    }
}
框架应用:Spring事件机制

Spring基于观察者模式实现事件驱动模型,核心组件:

  • ApplicationEvent:事件基类(如ContextRefreshedEvent容器刷新事件)
  • ApplicationListener:观察者接口(或@EventListener注解)
  • ApplicationEventPublisher:事件发布器(由ApplicationContext实现)

示例:自定义事件

// 自定义事件
class UserRegisterEvent extends ApplicationEvent {
    private String username;
    public UserRegisterEvent(Object source, String username) {
        super(source);
        this.username = username;
    }
    public String getUsername() { return username; }
}

// 事件发布者
@Service
class UserService implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher publisher;
    @Override public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
    public void register(String username) {
        // 业务逻辑: 用户注册
        publisher.publishEvent(new UserRegisterEvent(this, username)); // 发布事件
    }
}

// 事件监听器
@Service
class EmailListener {
    @EventListener // 注解式监听
    public void sendEmail(UserRegisterEvent event) {
        System.out.println("给" + event.getUsername() + "发送欢迎邮件");
    }
}

@Service
class CouponListener implements ApplicationListener<UserRegisterEvent> {
    @Override // 接口式监听
    public void onApplicationEvent(UserRegisterEvent event) {
        System.out.println("给" + event.getUsername() + "发放优惠券");
    }
}

四、责任链模式

4.1 模式定义与核心思想

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,其核心思想是将请求的发送者与接收者解耦,通过构建一条处理者对象链,使请求能够沿着链传递,直到被某个处理者处理或到达链尾。每个处理者只需关注自身职责范围内的请求,无需知道整体链结构,从而实现请求处理的动态组合与扩展。

4.2 代码示例:请假审批流程

以企业请假审批为例,展示责任链模式的实现:

// 请假请求类
class LeaveRequest {
    private String employee;
    private int days;
    
    // 构造函数、getter
    public LeaveRequest(String employee, int days) {
        this.employee = employee;
        this.days = days;
    }
    
    public int getDays() { return days; }
    public String getEmployee() { return employee; }
}

// 抽象处理者
abstract class Approver {
    protected Approver nextApprover;
    
    public void setNextApprover(Approver next) {
        this.nextApprover = next;
    }
    
    public abstract void processRequest(LeaveRequest request);
}

// 具体处理者:组长(处理≤3天)
class TeamLeader extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 3) {
            System.out.println("组长批准" + request.getEmployee() + "的" + request.getDays() + "天请假");
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

// 具体处理者:CTO(处理≤7天)
class CTO extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 7) {
            System.out.println("CTO批准" + request.getEmployee() + "的" + request.getDays() + "天请假");
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

// 具体处理者:CEO(处理所有请假)
class CEO extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        System.out.println("CEO批准" + request.getEmployee() + "的" + request.getDays() + "天请假");
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Approver teamLeader = new TeamLeader();
        Approver cto = new CTO();
        Approver ceo = new CEO();
        
        // 构建责任链:组长 → CTO → CEO
        teamLeader.setNextApprover(cto);
        cto.setNextApprover(ceo);
        
        // 提交请求
        teamLeader.processRequest(new LeaveRequest("张三", 5));  // CTO处理
        teamLeader.processRequest(new LeaveRequest("李四", 10)); // CEO处理
    }
}

4.3 框架应用场景

4.3.1 Spring Security过滤器链

Spring Security的核心机制基于责任链模式,通过FilterChainProxy管理一系列过滤器(Filter),每个过滤器专注于特定安全功能:

  • UsernamePasswordAuthenticationFilter:处理表单登录
  • CsrfFilter:防御跨站请求伪造
  • FilterSecurityInterceptor:权限控制决策

执行流程

  1. 请求进入FilterChainProxy,按顺序经过过滤器链
  2. 每个过滤器判断是否处理当前请求(如登录请求由UsernamePasswordAuthenticationFilter处理)
  3. 处理完成后通过chain.doFilter()传递给下一个过滤器

关键代码片段

// 自定义过滤器示例
public class CustomLoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        // 处理逻辑(如记录请求日志)
        System.out.println("Request URI: " + ((HttpServletRequest) request).getRequestURI());
        chain.doFilter(request, response); // 传递给下一个过滤器
    }
}
4.3.2 Tomcat的Pipeline-Valve机制

Tomcat容器(Engine/Host/Context/Wrapper)通过Pipeline-Valve实现责任链:

  • Pipeline:维护Valve链的容器
  • Valve:具体处理节点,如StandardEngineValveStandardHostValve

层级调用流程

EngineValve → HostValve → ContextValve → WrapperValve → Servlet

核心接口

public interface Valve {
    Valve getNext();
    void setNext(Valve valve);
    void invoke(Request request, Response response); // 处理请求
}

4.4 优缺点分析

优点缺点
解耦请求发送者与处理者链过长可能导致性能损耗
动态组合处理逻辑(增减处理者)请求可能未被处理而到达链尾
符合单一职责原则调试复杂(需追踪整条链)

五、总结:设计模式在框架中的应用全景

设计模式核心思想典型框架应用场景
单例模式唯一实例+全局访问Spring Bean默认单例(三级缓存解决循环依赖)、数据库连接池
工厂模式封装对象创建逻辑Spring BeanFactory/ApplicationContext、MyBatis SqlSessionFactory
装饰器模式动态扩展功能MyBatis缓存(LruCache/LoggingCache)、JDK IO流(BufferedReader)
适配器模式接口转换兼容Spring MVC HandlerAdapter、JDBC驱动适配
策略模式算法族封装与互换Spring Resource资源访问、支付方式选择
代理模式控制对象访问Spring AOP(JDK/CGLIB代理)、事务管理
观察者模式事件发布-订阅机制Spring事件机制(ApplicationEvent/Listener)、GUI界面事件

设计模式的价值不仅在于“代码模板”,更在于其背后的设计原则(如开闭原则、单一职责原则)。在实际开发中,应结合业务场景灵活选择,避免过度设计。通过学习Spring、MyBatis等框架对设计模式的经典应用,我们能更深刻地理解“为何用”而非“如何用”,真正提升架构设计能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值