欢迎光临
我们一直在努力

设计模式详解与实战:23种经典模式精讲

系统讲解GoF 23种设计模式中面试高频模式,每种模式包含:核心概念、UML结构、完整实战代码、框架中的应用。按创建型、结构型、行为型三大类组织。


目录

  • 一、创建型模式

    • 1. 单例模式 Singleton

    • 2. 工厂方法模式 Factory Method

    • 3. 抽象工厂模式 Abstract Factory

    • 4. 建造者模式 Builder

    • 5. 原型模式 Prototype

  • 二、结构型模式

    • 6. 代理模式 Proxy

    • 7. 适配器模式 Adapter

    • 8. 装饰器模式 Decorator

    • 9. 外观模式 Facade

    • 10. 组合模式 Composite

    • 11. 享元模式 Flyweight

  • 三、行为型模式

    • 12. 策略模式 Strategy

    • 13. 模板方法模式 Template Method

    • 14. 观察者模式 Observer

    • 15. 责任链模式 Chain of Responsibility

    • 16. 状态模式 State

    • 17. 命令模式 Command

    • 18. 迭代器模式 Iterator

  • 四、设计模式对比与选型


一、创建型模式

创建型模式关注对象的创建机制,将对象的创建与使用分离,使系统更灵活。

1. 单例模式 Singleton

概念

确保一个类只有一个实例,并提供一个全局访问点。

适用场景
  • 配置管理器、连接池、线程池、日志对象

  • 需要频繁创建和销毁的对象

  • 需要全局协调的资源(如ID生成器)

实现方式对比
方式线程安全懒加载防反射防序列化
饿汉式
DCL双重检查锁
静态内部类
枚举
实战代码

// ========== 方式一:静态内部类(推荐) ==========
public class Singleton {
   private Singleton() {}

   // 利用类加载机制保证线程安全,实现懒加载
   private static class Holder {
       private static final Singleton INSTANCE = new Singleton();
  }

   public static Singleton getInstance() {
       return Holder.INSTANCE;
  }
}

// ========== 方式二:枚举(最安全) ==========
public enum SingletonEnum {
   INSTANCE;

   private AtomicLong idCounter = new AtomicLong(0);

   public long generateId() {
       return idCounter.incrementAndGet();
  }
}

// 使用方式
long id = SingletonEnum.INSTANCE.generateId();

// ========== 方式三:双重检查锁(面试常问) ==========
public class SingletonDCL {
   // volatile禁止指令重排序
   private static volatile SingletonDCL instance;

   private SingletonDCL() {}

   public static SingletonDCL getInstance() {
       if (instance == null) {                // 第一次检查,避免不必要的同步
           synchronized (SingletonDCL.class) {
               if (instance == null) {        // 第二次检查,防止重复创建
                   instance = new SingletonDCL();
              }
          }
      }
       return instance;
  }
}

框架应用
  • Spring: Bean默认是singleton作用域

  • Runtime.getRuntime(): JDK中的饿汉式单例

  • MyBatis: SqlSessionFactory通常设计为单例


2. 工厂方法模式 Factory Method

概念

定义一个创建对象的接口,让子类决定实例化哪个类。工厂方法将实例化操作推迟到子类。

与简单工厂的区别
  • 简单工厂:一个工厂生产所有产品(违反开闭原则)

  • 工厂方法:每个产品有自己的工厂(符合开闭原则)

实战代码

// ===== 产品接口 =====
public interface DataSource {
   Connection getConnection();
   void close();
}

// ===== 具体产品 =====
public class MySQLDataSource implements DataSource {
   private String url;
   private String username;

   public MySQLDataSource(String url, String username) {
       this.url = url;
       this.username = username;
  }

   @Override
   public Connection getConnection() {
       System.out.println("获取MySQL连接: " + url);
       // 实际建立连接逻辑
       return null;
  }

   @Override
   public void close() {
       System.out.println("关闭MySQL连接");
  }
}

public class PostgreSQLDataSource implements DataSource {
   private String url;

   public PostgreSQLDataSource(String url) {
       this.url = url;
  }

   @Override
   public Connection getConnection() {
       System.out.println("获取PostgreSQL连接: " + url);
       return null;
  }

   @Override
   public void close() {
       System.out.println("关闭PostgreSQL连接");
  }
}

// ===== 工厂接口 =====
public interface DataSourceFactory {
   DataSource createDataSource(Map<String, String> config);
}

// ===== 具体工厂 =====
public class MySQLDataSourceFactory implements DataSourceFactory {
   @Override
   public DataSource createDataSource(Map<String, String> config) {
       return new MySQLDataSource(
           config.get("url"),
           config.get("username")
      );
  }
}

public class PostgreSQLDataSourceFactory implements DataSourceFactory {
   @Override
   public DataSource createDataSource(Map<String, String> config) {
       return new PostgreSQLDataSource(config.get("url"));
  }
}

// ===== 使用:通过工厂注册表实现动态选择 =====
public class DataSourceRegistry {
   private static final Map<String, DataSourceFactory> FACTORIES = new HashMap<>();

   static {
       FACTORIES.put("mysql", new MySQLDataSourceFactory());
       FACTORIES.put("postgresql", new PostgreSQLDataSourceFactory());
  }

   public static void register(String type, DataSourceFactory factory) {
       FACTORIES.put(type, factory);
  }

   public static DataSource create(String type, Map<String, String> config) {
       DataSourceFactory factory = FACTORIES.get(type);
       if (factory == null) {
           throw new IllegalArgumentException("不支持的数据源类型: " + type);
      }
       return factory.createDataSource(config);
  }
}

框架应用
  • Spring: BeanFactory、FactoryBean接口

  • SLF4J: LoggerFactory.getLogger()

  • Collection: iterator()方法是工厂方法


3. 抽象工厂模式 Abstract Factory

概念

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。重点在于产品族的创建。

与工厂方法的区别
  • 工厂方法:创建一种产品

  • 抽象工厂:创建一族相关产品

实战代码:跨数据库DAO工厂

// ===== 产品族接口 =====
public interface UserDao {
   void save(User user);
   User findById(Long id);
}

public interface OrderDao {
   void save(Order order);
   List<Order> findByUserId(Long userId);
}

// ===== MySQL产品族 =====
public class MySQLUserDao implements UserDao {
   @Override
   public void save(User user) {
       System.out.println("MySQL保存用户: " + user.getName());
  }

   @Override
   public User findById(Long id) {
       System.out.println("MySQL查询用户: " + id);
       return new User(id, "mysql_user");
  }
}

public class MySQLOrderDao implements OrderDao {
   @Override
   public void save(Order order) {
       System.out.println("MySQL保存订单: " + order.getId());
  }

   @Override
   public List<Order> findByUserId(Long userId) {
       System.out.println("MySQL查询用户订单: " + userId);
       return Collections.emptyList();
  }
}

// ===== Oracle产品族 =====
public class OracleUserDao implements UserDao {
   @Override
   public void save(User user) {
       System.out.println("Oracle保存用户: " + user.getName());
  }

   @Override
   public User findById(Long id) {
       System.out.println("Oracle查询用户: " + id);
       return new User(id, "oracle_user");
  }
}

public class OracleOrderDao implements OrderDao {
   @Override
   public void save(Order order) {
       System.out.println("Oracle保存订单: " + order.getId());
  }

   @Override
   public List<Order> findByUserId(Long userId) {
       System.out.println("Oracle查询用户订单: " + userId);
       return Collections.emptyList();
  }
}

// ===== 抽象工厂 =====
public interface DaoFactory {
   UserDao createUserDao();
   OrderDao createOrderDao();
}

// ===== 具体工厂 =====
public class MySQLDaoFactory implements DaoFactory {
   @Override
   public UserDao createUserDao() { return new MySQLUserDao(); }

   @Override
   public OrderDao createOrderDao() { return new MySQLOrderDao(); }
}

public class OracleDaoFactory implements DaoFactory {
   @Override
   public UserDao createUserDao() { return new OracleUserDao(); }

   @Override
   public OrderDao createOrderDao() { return new OracleOrderDao(); }
}

// ===== 客户端代码:完全解耦具体实现 =====
public class UserService {
   private final UserDao userDao;
   private final OrderDao orderDao;

   public UserService(DaoFactory factory) {
       this.userDao = factory.createUserDao();
       this.orderDao = factory.createOrderDao();
  }

   public void createUserWithOrder(User user, Order order) {
       userDao.save(user);
       orderDao.save(order);
  }
}


4. 建造者模式 Builder

概念

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。适用于参数多、构建步骤复杂的对象。

适用场景
  • 对象有很多可选参数

  • 构建过程需要多个步骤

  • 需要构建不同表示的同类对象

实战代码

// ===== 方式一:经典Builder(链式调用) =====
public class HttpRequest {
   private final String method;
   private final String url;
   private final Map<String, String> headers;
   private final String body;
   private final int timeout;
   private final boolean followRedirects;

   private HttpRequest(Builder builder) {
       this.method = builder.method;
       this.url = builder.url;
       this.headers = Collections.unmodifiableMap(builder.headers);
       this.body = builder.body;
       this.timeout = builder.timeout;
       this.followRedirects = builder.followRedirects;
  }

   // getter方法省略…

   public static class Builder {
       // 必需参数
       private final String method;
       private final String url;
       // 可选参数(带默认值)
       private Map<String, String> headers = new HashMap<>();
       private String body;
       private int timeout = 30000;
       private boolean followRedirects = true;

       public Builder(String method, String url) {
           this.method = method;
           this.url = url;
      }

       public Builder header(String key, String value) {
           this.headers.put(key, value);
           return this;
      }

       public Builder body(String body) {
           this.body = body;
           return this;
      }

       public Builder timeout(int timeout) {
           this.timeout = timeout;
           return this;
      }

       public Builder followRedirects(boolean follow) {
           this.followRedirects = follow;
           return this;
      }

       public HttpRequest build() {
           // 参数校验
           if (url == null || url.isEmpty()) {
               throw new IllegalStateException("URL不能为空");
          }
           return new HttpRequest(this);
      }
  }
}

// 使用示例
HttpRequest request = new HttpRequest.Builder("POST", "https://api.example.com/users")
  .header("Content-Type", "application/json")
  .header("Authorization", "Bearer token123")
  .body("{\\"name\\":\\"张三\\"}")
  .timeout(5000)
  .build();

// ===== 方式二:Lombok @Builder(实际项目推荐) =====
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TaskConfig {
   private String taskName;
   private String sourceType;
   private String sinkType;
   @Builder.Default
   private int parallelism = 1;
   @Builder.Default
   private int retryCount = 3;
   private Map<String, String> properties;
}

// 使用
TaskConfig config = TaskConfig.builder()
  .taskName("数据同步任务")
  .sourceType("mysql")
  .sinkType("hive")
  .parallelism(4)
  .build();

框架应用
  • StringBuilder: 字符串构建

  • Stream API: 链式操作构建数据流

  • Lombok @Builder: 自动生成Builder

  • OkHttp: Request.Builder


5. 原型模式 Prototype

概念

通过复制现有对象来创建新对象,而不是通过new实例化。适用于创建成本高的对象。

深拷贝 vs 浅拷贝
  • 浅拷贝: 只复制基本类型和引用地址,引用对象共享

  • 深拷贝: 完全独立的副本,引用对象也复制一份

实战代码

// ===== 浅拷贝 =====
public class TaskTemplate implements Cloneable {
   private String name;
   private String type;
   private List<String> columns;  // 引用类型

   @Override
   public TaskTemplate clone() {
       try {
           return (TaskTemplate) super.clone();
           // 注意:columns是浅拷贝,修改clone的columns会影响原对象
      } catch (CloneNotSupportedException e) {
           throw new RuntimeException(e);
      }
  }
}

// ===== 深拷贝方式一:手动复制 =====
public class TaskTemplate implements Cloneable {
   private String name;
   private String type;
   private List<String> columns;

   @Override
   public TaskTemplate clone() {
       try {
           TaskTemplate clone = (TaskTemplate) super.clone();
           // 手动深拷贝引用类型
           clone.columns = new ArrayList<>(this.columns);
           return clone;
      } catch (CloneNotSupportedException e) {
           throw new RuntimeException(e);
      }
  }
}

// ===== 深拷贝方式二:序列化(更通用) =====
public class DeepCopyUtil {
   @SuppressWarnings("unchecked")
   public static <T extends Serializable> T deepCopy(T object) {
       try {
           ByteArrayOutputStream bos = new ByteArrayOutputStream();
           ObjectOutputStream oos = new ObjectOutputStream(bos);
           oos.writeObject(object);

           ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
           ObjectInputStream ois = new ObjectInputStream(bis);
           return (T) ois.readObject();
      } catch (Exception e) {
           throw new RuntimeException("深拷贝失败", e);
      }
  }
}

// ===== 原型注册表:管理可克隆的模板 =====
public class PrototypeRegistry {
   private Map<String, TaskTemplate> templates = new ConcurrentHashMap<>();

   public void register(String key, TaskTemplate template) {
       templates.put(key, template);
  }

   public TaskTemplate createFromTemplate(String key) {
       TaskTemplate template = templates.get(key);
       if (template == null) {
           throw new IllegalArgumentException("模板不存在: " + key);
      }
       return template.clone();
  }
}

框架应用
  • Spring: scope="prototype" 每次getBean返回新实例

  • Object.clone(): JDK原生支持

  • BeanUtils.copyProperties(): Spring属性复制


二、结构型模式

结构型模式关注类和对象的组合,形成更大的结构。

6. 代理模式 Proxy

概念

为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用。

三种代理方式
类型实现方式限制性能
静态代理 手动编写代理类 每个接口都要写 最快
JDK动态代理 基于接口+反射 必须有接口 中等
CGLIB代理 基于继承+字节码生成 不能代理final类 较快
实战代码

// ===== 目标接口和实现 =====
public interface UserService {
   User getUserById(Long id);
   void updateUser(User user);
}

public class UserServiceImpl implements UserService {
   @Override
   public User getUserById(Long id) {
       // 模拟数据库查询
       System.out.println("查询用户: " + id);
       return new User(id, "张三");
  }

   @Override
   public void updateUser(User user) {
       System.out.println("更新用户: " + user.getName());
  }
}

// ===== JDK动态代理 =====
public class LoggingProxy implements InvocationHandler {
   private final Object target;

   public LoggingProxy(Object target) {
       this.target = target;
  }

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       long start = System.currentTimeMillis();
       System.out.println("[日志] 调用方法: " + method.getName());

       try {
           Object result = method.invoke(target, args);
           long cost = System.currentTimeMillis() – start;
           System.out.println("[日志] 方法执行完成, 耗时: " + cost + "ms");
           return result;
      } catch (InvocationTargetException e) {
           System.out.println("[日志] 方法执行异常: " + e.getTargetException().getMessage());
           throw e.getTargetException();
      }
  }

   // 工厂方法创建代理
   @SuppressWarnings("unchecked")
   public static <T> T createProxy(T target) {
       return (T) Proxy.newProxyInstance(
           target.getClass().getClassLoader(),
           target.getClass().getInterfaces(),
           new LoggingProxy(target)
      );
  }
}

// 使用
UserService userService = LoggingProxy.createProxy(new UserServiceImpl());
userService.getUserById(1L);  // 自动打印日志

// ===== CGLIB动态代理(不需要接口) =====
public class CglibProxy implements MethodInterceptor {
   @Override
   public Object intercept(Object obj, Method method, Object[] args,
                          MethodProxy proxy) throws Throwable {
       System.out.println("[CGLIB] 方法前置处理: " + method.getName());
       Object result = proxy.invokeSuper(obj, args);
       System.out.println("[CGLIB] 方法后置处理");
       return result;
  }

   @SuppressWarnings("unchecked")
   public static <T> T createProxy(Class<T> clazz) {
       Enhancer enhancer = new Enhancer();
       enhancer.setSuperclass(clazz);
       enhancer.setCallback(new CglibProxy());
       return (T) enhancer.create();
  }
}

框架应用
  • Spring AOP: 有接口用JDK代理,无接口用CGLIB

  • MyBatis: Mapper接口的动态代理实现

  • Dubbo/gRPC: RPC客户端代理


7. 适配器模式 Adapter

概念

将一个类的接口转换成客户端所期望的另一个接口。让原本接口不兼容的类可以合作。

类适配器 vs 对象适配器
  • 类适配器:通过继承适配(Java单继承限制大)

  • 对象适配器:通过组合适配(更灵活,推荐)

实战代码:统一日志接口

// ===== 目标接口(系统期望的统一日志接口) =====
public interface UnifiedLogger {
   void info(String message);
   void error(String message, Throwable t);
   void debug(String message);
}

// ===== 被适配者:第三方日志库A =====
public class ThirdPartyLoggerA {
   public void writeLog(int level, String msg) {
       System.out.println("[LibA-" + level + "] " + msg);
  }

   public void writeError(String msg, Exception ex) {
       System.out.println("[LibA-ERROR] " + msg + ": " + ex.getMessage());
  }
}

// ===== 被适配者:第三方日志库B =====
public class ThirdPartyLoggerB {
   public void log(String severity, String content) {
       System.out.println("[LibB/" + severity + "] " + content);
  }
}

// ===== 适配器A =====
public class LoggerAdapterA implements UnifiedLogger {
   private final ThirdPartyLoggerA logger;

   public LoggerAdapterA(ThirdPartyLoggerA logger) {
       this.logger = logger;
  }

   @Override
   public void info(String message) {
       logger.writeLog(1, message);
  }

   @Override
   public void error(String message, Throwable t) {
       logger.writeError(message, (Exception) t);
  }

   @Override
   public void debug(String message) {
       logger.writeLog(0, message);
  }
}

// ===== 适配器B =====
public class LoggerAdapterB implements UnifiedLogger {
   private final ThirdPartyLoggerB logger;

   public LoggerAdapterB(ThirdPartyLoggerB logger) {
       this.logger = logger;
  }

   @Override
   public void info(String message) {
       logger.log("INFO", message);
  }

   @Override
   public void error(String message, Throwable t) {
       logger.log("ERROR", message + " – " + t.getMessage());
  }

   @Override
   public void debug(String message) {
       logger.log("DEBUG", message);
  }
}

// ===== 客户端代码统一使用 =====
public class Application {
   private final UnifiedLogger logger;

   public Application(UnifiedLogger logger) {
       this.logger = logger;
  }

   public void doSomething() {
       logger.info("操作开始");
       // 业务逻辑…
       logger.info("操作完成");
  }
}

框架应用
  • SLF4J: 统一日志门面,适配Log4j、Logback等

  • Spring MVC: HandlerAdapter 适配不同类型的Handler

  • Arrays.asList(): 数组适配为List接口

  • InputStreamReader: 字节流适配为字符流


8. 装饰器模式 Decorator

概念

动态地给对象添加额外的职责,比继承更灵活的扩展方式。装饰器与被装饰对象实现相同接口,可以层层嵌套。

与继承的区别
  • 继承:编译时静态扩展,类爆炸问题

  • 装饰器:运行时动态组合,灵活搭配

实战代码:数据流处理增强

// ===== 组件接口 =====
public interface DataProcessor {
   byte[] process(byte[] data);
}

// ===== 基础实现 =====
public class RawDataProcessor implements DataProcessor {
   @Override
   public byte[] process(byte[] data) {
       System.out.println("原始数据处理, 大小: " + data.length);
       return data;
  }
}

// ===== 装饰器基类 =====
public abstract class DataProcessorDecorator implements DataProcessor {
   protected final DataProcessor wrapped;

   public DataProcessorDecorator(DataProcessor wrapped) {
       this.wrapped = wrapped;
  }

   @Override
   public byte[] process(byte[] data) {
       return wrapped.process(data);
  }
}

// ===== 压缩装饰器 =====
public class CompressionDecorator extends DataProcessorDecorator {
   public CompressionDecorator(DataProcessor wrapped) {
       super(wrapped);
  }

   @Override
   public byte[] process(byte[] data) {
       byte[] compressed = compress(data);
       System.out.println("压缩: " + data.length + " -> " + compressed.length);
       return super.process(compressed);
  }

   private byte[] compress(byte[] data) {
       // GZIP压缩逻辑
       try {
           ByteArrayOutputStream bos = new ByteArrayOutputStream();
           GZIPOutputStream gzip = new GZIPOutputStream(bos);
           gzip.write(data);
           gzip.close();
           return bos.toByteArray();
      } catch (IOException e) {
           throw new RuntimeException("压缩失败", e);
      }
  }
}

// ===== 加密装饰器 =====
public class EncryptionDecorator extends DataProcessorDecorator {
   private final String key;

   public EncryptionDecorator(DataProcessor wrapped, String key) {
       super(wrapped);
       this.key = key;
  }

   @Override
   public byte[] process(byte[] data) {
       byte[] encrypted = encrypt(data);
       System.out.println("加密完成, 密钥: " + key.substring(0, 4) + "***");
       return super.process(encrypted);
  }

   private byte[] encrypt(byte[] data) {
       // AES加密逻辑(示意)
       byte[] result = new byte[data.length];
       for (int i = 0; i < data.length; i++) {
           result[i] = (byte) (data[i] ^ key.charAt(i % key.length()));
      }
       return result;
  }
}

// ===== 灵活组合 =====
public class Demo {
   public static void main(String[] args) {
       byte[] data = "Hello, 设计模式!".getBytes();

       // 只压缩
       DataProcessor compressOnly = new CompressionDecorator(new RawDataProcessor());
       compressOnly.process(data);

       // 先加密再压缩
       DataProcessor encryptThenCompress = new CompressionDecorator(
           new EncryptionDecorator(new RawDataProcessor(), "mySecretKey123")
      );
       encryptThenCompress.process(data);

       // 先压缩再加密(顺序不同,结果不同)
       DataProcessor compressThenEncrypt = new EncryptionDecorator(
           new CompressionDecorator(new RawDataProcessor()), "mySecretKey123"
      );
       compressThenEncrypt.process(data);
  }
}

框架应用
  • Java IO: BufferedInputStream(FileInputStream) 层层包装

  • Spring: HttpServletRequestWrapper 增强Request

  • MyBatis: Cache装饰器链(LruCache、LoggingCache等)


9. 外观模式 Facade

概念

为子系统中的一组接口提供一个一致的界面。外观定义了一个高层接口,让子系统更容易使用。

实战代码:订单处理外观

// ===== 子系统:库存服务 =====
public class InventoryService {
   public boolean checkStock(String productId, int quantity) {
       System.out.println("检查库存: " + productId + ", 数量: " + quantity);
       return true;
  }

   public void deductStock(String productId, int quantity) {
       System.out.println("扣减库存: " + productId + " – " + quantity);
  }
}

// ===== 子系统:支付服务 =====
public class PaymentService {
   public boolean processPayment(String userId, BigDecimal amount) {
       System.out.println("处理支付: 用户" + userId + ", 金额" + amount);
       return true;
  }

   public void refund(String orderId) {
       System.out.println("退款: 订单" + orderId);
  }
}

// ===== 子系统:物流服务 =====
public class ShippingService {
   public String createShipment(String orderId, String address) {
       System.out.println("创建物流单: " + orderId + " -> " + address);
       return "SF" + System.currentTimeMillis();
  }
}

// ===== 子系统:通知服务 =====
public class NotificationService {
   public void sendOrderConfirmation(String userId, String orderId) {
       System.out.println("发送订单确认通知: " + userId);
  }
}

// ===== 外观类:统一入口 =====
public class OrderFacade {
   private final InventoryService inventoryService;
   private final PaymentService paymentService;
   private final ShippingService shippingService;
   private final NotificationService notificationService;

   public OrderFacade() {
       this.inventoryService = new InventoryService();
       this.paymentService = new PaymentService();
       this.shippingService = new ShippingService();
       this.notificationService = new NotificationService();
  }

   /**
    * 一键下单:协调多个子系统完成完整下单流程
    */
   public OrderResult placeOrder(String userId, String productId,
                                 int quantity, String address) {
       // 1. 检查库存
       if (!inventoryService.checkStock(productId, quantity)) {
           return OrderResult.fail("库存不足");
      }

       // 2. 处理支付
       BigDecimal amount = calculateAmount(productId, quantity);
       if (!paymentService.processPayment(userId, amount)) {
           return OrderResult.fail("支付失败");
      }

       // 3. 扣减库存
       inventoryService.deductStock(productId, quantity);

       // 4. 创建物流
       String trackingNo = shippingService.createShipment(
           generateOrderId(), address);

       // 5. 发送通知
       notificationService.sendOrderConfirmation(userId, trackingNo);

       return OrderResult.success(trackingNo);
  }

   private BigDecimal calculateAmount(String productId, int quantity) {
       return new BigDecimal("99.9").multiply(new BigDecimal(quantity));
  }

   private String generateOrderId() {
       return "ORD" + System.currentTimeMillis();
  }
}

框架应用
  • SLF4J: 日志外观,屏蔽底层日志框架差异

  • Spring JDBC: JdbcTemplate封装了获取连接、创建Statement、处理异常等

  • Tomcat: RequestFacade封装内部Request对象


10. 组合模式 Composite

概念

将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

实战代码:菜单权限树

// ===== 组件接口 =====
public interface MenuComponent {
   String getName();
   void display(int depth);
   default void add(MenuComponent component) {
       throw new UnsupportedOperationException();
  }
   default void remove(MenuComponent component) {
       throw new UnsupportedOperationException();
  }
   default List<MenuComponent> getChildren() {
       return Collections.emptyList();
  }
}

// ===== 叶子节点:菜单项 =====
public class MenuItem implements MenuComponent {
   private final String name;
   private final String url;
   private final String permission;

   public MenuItem(String name, String url, String permission) {
       this.name = name;
       this.url = url;
       this.permission = permission;
  }

   @Override
   public String getName() { return name; }

   @Override
   public void display(int depth) {
       String indent = String.join("", Collections.nCopies(depth, " "));
       System.out.println(indent + "├─ " + name + " [" + url + "]");
  }
}

// ===== 组合节点:菜单组 =====
public class MenuGroup implements MenuComponent {
   private final String name;
   private final List<MenuComponent> children = new ArrayList<>();

   public MenuGroup(String name) {
       this.name = name;
  }

   @Override
   public String getName() { return name; }

   @Override
   public void add(MenuComponent component) {
       children.add(component);
  }

   @Override
   public void remove(MenuComponent component) {
       children.remove(component);
  }

   @Override
   public List<MenuComponent> getChildren() {
       return Collections.unmodifiableList(children);
  }

   @Override
   public void display(int depth) {
       String indent = String.join("", Collections.nCopies(depth, " "));
       System.out.println(indent + "├─ [" + name + "]");
       for (MenuComponent child : children) {
           child.display(depth + 1);
      }
  }
}

// ===== 使用 =====
public class Demo {
   public static void main(String[] args) {
       MenuGroup root = new MenuGroup("系统管理");

       MenuGroup userMenu = new MenuGroup("用户管理");
       userMenu.add(new MenuItem("用户列表", "/user/list", "user:list"));
       userMenu.add(new MenuItem("添加用户", "/user/add", "user:add"));

       MenuGroup roleMenu = new MenuGroup("角色管理");
       roleMenu.add(new MenuItem("角色列表", "/role/list", "role:list"));

       root.add(userMenu);
       root.add(roleMenu);
       root.add(new MenuItem("系统配置", "/config", "config:view"));

       root.display(0);
  }
}


11. 享元模式 Flyweight

概念

运用共享技术有效支持大量细粒度的对象。通过共享已存在的对象来减少内存消耗。

核心要点
  • 内部状态: 可以共享的、不变的状态

  • 外部状态: 不能共享的、随环境变化的状态

实战代码:数据库连接池

// ===== 享元对象:数据库连接包装 =====
public class PooledConnection {
   private final Connection realConnection;  // 内部状态:可共享
   private boolean inUse;                    // 外部状态:使用标记

   public PooledConnection(Connection realConnection) {
       this.realConnection = realConnection;
       this.inUse = false;
  }

   public Connection getConnection() { return realConnection; }
   public boolean isInUse() { return inUse; }
   public void setInUse(boolean inUse) { this.inUse = inUse; }
}

// ===== 享元工厂:连接池 =====
public class ConnectionPool {
   private final List<PooledConnection> pool;
   private final String url;
   private final String username;
   private final String password;
   private final int maxSize;

   public ConnectionPool(String url, String username, String password, int maxSize) {
       this.url = url;
       this.username = username;
       this.password = password;
       this.maxSize = maxSize;
       this.pool = new ArrayList<>(maxSize);
       initPool();
  }

   private void initPool() {
       for (int i = 0; i < maxSize; i++) {
           try {
               Connection conn = DriverManager.getConnection(url, username, password);
               pool.add(new PooledConnection(conn));
          } catch (SQLException e) {
               throw new RuntimeException("初始化连接池失败", e);
          }
      }
  }

   public synchronized Connection acquire() {
       for (PooledConnection pc : pool) {
           if (!pc.isInUse()) {
               pc.setInUse(true);
               System.out.println("获取连接, 当前使用: " + getActiveCount());
               return pc.getConnection();
          }
      }
       throw new RuntimeException("连接池已满,无可用连接");
  }

   public synchronized void release(Connection conn) {
       for (PooledConnection pc : pool) {
           if (pc.getConnection() == conn) {
               pc.setInUse(false);
               System.out.println("释放连接, 当前使用: " + getActiveCount());
               return;
          }
      }
  }

   private long getActiveCount() {
       return pool.stream().filter(PooledConnection::isInUse).count();
  }
}

框架应用
  • Integer.valueOf(): -128~127的缓存

  • String常量池: 字符串字面量共享

  • 线程池: 线程对象的复用


三、行为型模式

行为型模式关注对象之间的通信和职责分配。

12. 策略模式 Strategy

概念

定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式让算法独立于使用它的客户端。

核心结构
  • Strategy接口: 定义算法规范

  • ConcreteStrategy: 具体算法实现

  • Context: 持有策略引用,委托策略执行

实战代码:支付系统

// ===== 策略接口 =====
public interface PaymentStrategy {
   /**
    * 执行支付
    * @return 支付结果
    */
   PaymentResult pay(PaymentRequest request);

   /**
    * 获取支付方式名称
    */
   String getPaymentType();
}

// ===== 具体策略 =====
public class AlipayStrategy implements PaymentStrategy {
   @Override
   public PaymentResult pay(PaymentRequest request) {
       System.out.println("调用支付宝接口, 金额: " + request.getAmount());
       // 调用支付宝SDK…
       return PaymentResult.success("ALI" + System.currentTimeMillis());
  }

   @Override
   public String getPaymentType() { return "alipay"; }
}

public class WechatPayStrategy implements PaymentStrategy {
   @Override
   public PaymentResult pay(PaymentRequest request) {
       System.out.println("调用微信支付接口, 金额: " + request.getAmount());
       return PaymentResult.success("WX" + System.currentTimeMillis());
  }

   @Override
   public String getPaymentType() { return "wechat"; }
}

public class BankCardStrategy implements PaymentStrategy {
   @Override
   public PaymentResult pay(PaymentRequest request) {
       System.out.println("调用银联接口, 金额: " + request.getAmount());
       return PaymentResult.success("BANK" + System.currentTimeMillis());
  }

   @Override
   public String getPaymentType() { return "bankcard"; }
}

// ===== 策略上下文(配合Spring使用) =====
@Component
public class PaymentContext {
   private final Map<String, PaymentStrategy> strategyMap;

   // Spring自动注入所有PaymentStrategy实现
   @Autowired
   public PaymentContext(List<PaymentStrategy> strategies) {
       this.strategyMap = strategies.stream()
          .collect(Collectors.toMap(
               PaymentStrategy::getPaymentType,
               Function.identity()
          ));
  }

   public PaymentResult executePayment(String paymentType, PaymentRequest request) {
       PaymentStrategy strategy = strategyMap.get(paymentType);
       if (strategy == null) {
           throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
      }
       return strategy.pay(request);
  }
}

策略模式 vs if-else

// ❌ 不好:大量if-else,违反开闭原则
public PaymentResult pay(String type, PaymentRequest req) {
   if ("alipay".equals(type)) { … }
   else if ("wechat".equals(type)) { … }
   else if ("bankcard".equals(type)) { … }
   // 每新增一种支付方式都要改这里
}

// ✅ 好:策略模式,新增支付只需添加新类
@Component
public class ApplePayStrategy implements PaymentStrategy { … }


13. 模板方法模式 Template Method

概念

在一个方法中定义算法的骨架,将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

实战代码:数据导出框架

// ===== 抽象模板 =====
public abstract class DataExporter {

   // 模板方法:定义导出流程(final防止子类覆盖流程)
   public final ExportResult export(ExportRequest request) {
       // 1. 参数校验
       validate(request);
       // 2. 查询数据
       List<Map<String, Object>> data = queryData(request);
       // 3. 数据转换
       byte[] content = transformData(data, request);
       // 4. 钩子方法:导出前处理
       beforeWrite(request);
       // 5. 写出文件
       String filePath = writeFile(content, request);
       // 6. 钩子方法:导出后处理
       afterWrite(filePath, request);

       return new ExportResult(filePath, data.size());
  }

   // 通用校验逻辑(可覆盖)
   protected void validate(ExportRequest request) {
       if (request.getColumns() == null || request.getColumns().isEmpty()) {
           throw new IllegalArgumentException("导出列不能为空");
      }
  }

   // 抽象方法:子类必须实现
   protected abstract List<Map<String, Object>> queryData(ExportRequest request);
   protected abstract byte[] transformData(List<Map<String, Object>> data,
                                          ExportRequest request);
   protected abstract String writeFile(byte[] content, ExportRequest request);

   // 钩子方法:子类可选覆盖
   protected void beforeWrite(ExportRequest request) {}
   protected void afterWrite(String filePath, ExportRequest request) {}
}

// ===== 具体实现:CSV导出 =====
public class CsvExporter extends DataExporter {
   @Override
   protected List<Map<String, Object>> queryData(ExportRequest request) {
       System.out.println("查询数据: " + request.getSql());
       // 执行SQL查询…
       return Collections.emptyList();
  }

   @Override
   protected byte[] transformData(List<Map<String, Object>> data,
                                 ExportRequest request) {
       StringBuilder sb = new StringBuilder();
       // 写表头
       sb.append(String.join(",", request.getColumns())).append("\\n");
       // 写数据行
       for (Map<String, Object> row : data) {
           sb.append(request.getColumns().stream()
              .map(col -> String.valueOf(row.getOrDefault(col, "")))
              .collect(Collectors.joining(","))
          ).append("\\n");
      }
       return sb.toString().getBytes();
  }

   @Override
   protected String writeFile(byte[] content, ExportRequest request) {
       String path = "/tmp/export_" + System.currentTimeMillis() + ".csv";
       // 写文件…
       return path;
  }
}

// ===== 具体实现:Excel导出 =====
public class ExcelExporter extends DataExporter {
   @Override
   protected List<Map<String, Object>> queryData(ExportRequest request) {
       // 与CSV相同的查询逻辑
       return Collections.emptyList();
  }

   @Override
   protected byte[] transformData(List<Map<String, Object>> data,
                                 ExportRequest request) {
       // 使用POI生成Excel
       System.out.println("生成Excel文件, 共" + data.size() + "行");
       return new byte[0];
  }

   @Override
   protected String writeFile(byte[] content, ExportRequest request) {
       String path = "/tmp/export_" + System.currentTimeMillis() + ".xlsx";
       return path;
  }

   @Override
   protected void afterWrite(String filePath, ExportRequest request) {
       // Excel导出后发送通知
       System.out.println("Excel导出完成,通知用户下载: " + filePath);
  }
}

框架应用
  • AbstractQueuedSynchronizer (AQS): acquire()定义获取锁流程,tryAcquire()子类实现

  • HttpServlet: service()分发到doGet()、doPost()

  • Spring JdbcTemplate: 定义数据库操作流程


14. 观察者模式 Observer

概念

定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖于它的对象都得到通知并自动更新。

实战代码:事件驱动系统

// ===== 事件基类 =====
public abstract class DomainEvent {
   private final LocalDateTime occurredAt;
   private final String eventId;

   protected DomainEvent() {
       this.occurredAt = LocalDateTime.now();
       this.eventId = UUID.randomUUID().toString();
  }

   public LocalDateTime getOccurredAt() { return occurredAt; }
   public String getEventId() { return eventId; }
}

// ===== 具体事件 =====
public class OrderCreatedEvent extends DomainEvent {
   private final String orderId;
   private final String userId;
   private final BigDecimal amount;

   public OrderCreatedEvent(String orderId, String userId, BigDecimal amount) {
       super();
       this.orderId = orderId;
       this.userId = userId;
       this.amount = amount;
  }

   // getter省略
   public String getOrderId() { return orderId; }
   public String getUserId() { return userId; }
   public BigDecimal getAmount() { return amount; }
}

// ===== 观察者接口 =====
public interface EventListener<E extends DomainEvent> {
   void onEvent(E event);
   Class<E> supportedEventType();
}

// ===== 具体观察者 =====
@Component
public class InventoryDeductListener implements EventListener<OrderCreatedEvent> {
   @Override
   public void onEvent(OrderCreatedEvent event) {
       System.out.println("扣减库存, 订单: " + event.getOrderId());
  }

   @Override
   public Class<OrderCreatedEvent> supportedEventType() {
       return OrderCreatedEvent.class;
  }
}

@Component
public class PointsAccrualListener implements EventListener<OrderCreatedEvent> {
   @Override
   public void onEvent(OrderCreatedEvent event) {
       int points = event.getAmount().intValue();
       System.out.println("积分增加: " + points + ", 用户: " + event.getUserId());
  }

   @Override
   public Class<OrderCreatedEvent> supportedEventType() {
       return OrderCreatedEvent.class;
  }
}

// ===== 事件总线(被观察者) =====
@Component
public class EventBus {
   private final Map<Class<?>, List<EventListener<?>>> listeners = new ConcurrentHashMap<>();

   @Autowired
   public EventBus(List<EventListener<?>> allListeners) {
       for (EventListener<?> listener : allListeners) {
           listeners.computeIfAbsent(listener.supportedEventType(),
               k -> new CopyOnWriteArrayList<>()).add(listener);
      }
  }

   @SuppressWarnings("unchecked")
   public <E extends DomainEvent> void publish(E event) {
       List<EventListener<?>> eventListeners = listeners.get(event.getClass());
       if (eventListeners != null) {
           for (EventListener<?> listener : eventListeners) {
              ((EventListener<E>) listener).onEvent(event);
          }
      }
  }
}

框架应用
  • Spring事件: ApplicationEventPublisher + @EventListener

  • Guava EventBus: Google的事件总线实现

  • JDK Observable/Observer: 已废弃但面试常问


15. 责任链模式 Chain of Responsibility

概念

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求。

两种形式
  • 纯责任链: 要么处理要么传递,只有一个处理者

  • 不纯责任链: 每个处理者都可以处理一部分(更常见)

实战代码:请求参数校验链

// ===== 处理器接口 =====
public interface ValidationHandler {
   /**
    * 执行校验
    * @return 校验结果,null表示通过
    */
   ValidationResult validate(ApiRequest request);

   /**
    * 排序值,越小越先执行
    */
   int getOrder();
}

// ===== 具体处理器 =====
@Component
public class AuthValidationHandler implements ValidationHandler {
   @Override
   public ValidationResult validate(ApiRequest request) {
       if (request.getToken() == null || request.getToken().isEmpty()) {
           return ValidationResult.fail("认证令牌不能为空");
      }
       // 验证token有效性
       if (!TokenUtil.verify(request.getToken())) {
           return ValidationResult.fail("认证令牌无效或已过期");
      }
       return null;  // 通过,交给下一个处理器
  }

   @Override
   public int getOrder() { return 1; }
}

@Component
public class RateLimitHandler implements ValidationHandler {
   private final Map<String, AtomicInteger> counters = new ConcurrentHashMap<>();

   @Override
   public ValidationResult validate(ApiRequest request) {
       String key = request.getClientIp();
       AtomicInteger count = counters.computeIfAbsent(key, k -> new AtomicInteger(0));
       if (count.incrementAndGet() > 100) {
           return ValidationResult.fail("请求频率超限");
      }
       return null;
  }

   @Override
   public int getOrder() { return 2; }
}

@Component
public class ParamValidationHandler implements ValidationHandler {
   @Override
   public ValidationResult validate(ApiRequest request) {
       if (request.getBody() == null) {
           return ValidationResult.fail("请求体不能为空");
      }
       if (request.getBody().length() > 1024 * 1024) {
           return ValidationResult.fail("请求体超出大小限制");
      }
       return null;
  }

   @Override
   public int getOrder() { return 3; }
}

// ===== 责任链执行器 =====
@Component
public class ValidationChain {
   private final List<ValidationHandler> handlers;

   @Autowired
   public ValidationChain(List<ValidationHandler> handlers) {
       // 按order排序
       this.handlers = handlers.stream()
          .sorted(Comparator.comparingInt(ValidationHandler::getOrder))
          .collect(Collectors.toList());
  }

   public ValidationResult execute(ApiRequest request) {
       for (ValidationHandler handler : handlers) {
           ValidationResult result = handler.validate(request);
           if (result != null) {
               return result;  // 校验失败,中断链
          }
      }
       return ValidationResult.success();  // 全部通过
  }
}

框架应用
  • Servlet Filter链: FilterChain.doFilter()

  • Spring Security: 过滤器链

  • Netty: ChannelPipeline中的Handler链

  • MyBatis: 插件拦截器链


16. 状态模式 State

概念

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。将状态相关的行为封装到独立的状态类中。

状态模式 vs 策略模式
  • 策略模式:客户端主动选择策略

  • 状态模式:状态自动流转,客户端无感知

实战代码:订单状态机

// ===== 状态接口 =====
public interface OrderState {
   void pay(OrderContext context);
   void ship(OrderContext context);
   void receive(OrderContext context);
   void cancel(OrderContext context);
   String getStateName();
}

// ===== 状态上下文 =====
public class OrderContext {
   private OrderState currentState;
   private String orderId;

   public OrderContext(String orderId) {
       this.orderId = orderId;
       this.currentState = new CreatedState();
  }

   public void setState(OrderState state) {
       System.out.println("订单[" + orderId + "] 状态变更: "
           + currentState.getStateName() + " -> " + state.getStateName());
       this.currentState = state;
  }

   public void pay() { currentState.pay(this); }
   public void ship() { currentState.ship(this); }
   public void receive() { currentState.receive(this); }
   public void cancel() { currentState.cancel(this); }
   public String getStateName() { return currentState.getStateName(); }
}

// ===== 具体状态 =====
public class CreatedState implements OrderState {
   @Override
   public void pay(OrderContext context) {
       System.out.println("支付成功");
       context.setState(new PaidState());
  }

   @Override
   public void ship(OrderContext context) {
       System.out.println("未支付,不能发货");
  }

   @Override
   public void receive(OrderContext context) {
       System.out.println("未支付,不能确认收货");
  }

   @Override
   public void cancel(OrderContext context) {
       System.out.println("取消订单");
       context.setState(new CancelledState());
  }

   @Override
   public String getStateName() { return "待支付"; }
}

public class PaidState implements OrderState {
   @Override
   public void pay(OrderContext context) {
       System.out.println("已支付,请勿重复支付");
  }

   @Override
   public void ship(OrderContext context) {
       System.out.println("开始发货");
       context.setState(new ShippedState());
  }

   @Override
   public void receive(OrderContext context) {
       System.out.println("未发货,不能确认收货");
  }

   @Override
   public void cancel(OrderContext context) {
       System.out.println("申请退款并取消");
       context.setState(new CancelledState());
  }

   @Override
   public String getStateName() { return "已支付"; }
}

public class ShippedState implements OrderState {
   @Override
   public void pay(OrderContext context) {
       System.out.println("已支付");
  }

   @Override
   public void ship(OrderContext context) {
       System.out.println("已发货,请勿重复操作");
  }

   @Override
   public void receive(OrderContext context) {
       System.out.println("确认收货");
       context.setState(new CompletedState());
  }

   @Override
   public void cancel(OrderContext context) {
       System.out.println("已发货,不能取消");
  }

   @Override
   public String getStateName() { return "已发货"; }
}

public class CompletedState implements OrderState {
   @Override
   public void pay(OrderContext ctx) { System.out.println("订单已完成"); }
   @Override
   public void ship(OrderContext ctx) { System.out.println("订单已完成"); }
   @Override
   public void receive(OrderContext ctx) { System.out.println("订单已完成"); }
   @Override
   public void cancel(OrderContext ctx) { System.out.println("已完成不能取消"); }
   @Override
   public String getStateName() { return "已完成"; }
}

public class CancelledState implements OrderState {
   @Override
   public void pay(OrderContext ctx) { System.out.println("订单已取消"); }
   @Override
   public void ship(OrderContext ctx) { System.out.println("订单已取消"); }
   @Override
   public void receive(OrderContext ctx) { System.out.println("订单已取消"); }
   @Override
   public void cancel(OrderContext ctx) { System.out.println("订单已取消"); }
   @Override
   public String getStateName() { return "已取消"; }
}

// ===== 使用 =====
OrderContext order = new OrderContext("ORD001");
order.pay();      // 待支付 -> 已支付
order.ship();     // 已支付 -> 已发货
order.receive();  // 已发货 -> 已完成


17. 命令模式 Command

概念

将请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

实战代码:任务调度系统

// ===== 命令接口 =====
public interface Command {
   void execute();
   void undo();
   String getDescription();
}

// ===== 具体命令 =====
public class SqlExecuteCommand implements Command {
   private final JdbcTemplate jdbcTemplate;
   private final String sql;
   private final String undoSql;

   public SqlExecuteCommand(JdbcTemplate jdbcTemplate, String sql, String undoSql) {
       this.jdbcTemplate = jdbcTemplate;
       this.sql = sql;
       this.undoSql = undoSql;
  }

   @Override
   public void execute() {
       System.out.println("执行SQL: " + sql);
       jdbcTemplate.execute(sql);
  }

   @Override
   public void undo() {
       System.out.println("回滚SQL: " + undoSql);
       jdbcTemplate.execute(undoSql);
  }

   @Override
   public String getDescription() { return "SQL执行: " + sql; }
}

public class FileTransferCommand implements Command {
   private final String source;
   private final String destination;

   public FileTransferCommand(String source, String destination) {
       this.source = source;
       this.destination = destination;
  }

   @Override
   public void execute() {
       System.out.println("传输文件: " + source + " -> " + destination);
       // 文件传输逻辑
  }

   @Override
   public void undo() {
       System.out.println("删除已传输文件: " + destination);
       // 删除目标文件
  }

   @Override
   public String getDescription() { return "文件传输: " + source; }
}

// ===== 命令调度器(Invoker) =====
public class TaskScheduler {
   private final Queue<Command> pendingQueue = new LinkedList<>();
   private final Deque<Command> executedStack = new ArrayDeque<>();
   private final List<Command> failedCommands = new ArrayList<>();

   public void submit(Command command) {
       pendingQueue.offer(command);
       System.out.println("任务入队: " + command.getDescription());
  }

   public void executeAll() {
       while (!pendingQueue.isEmpty()) {
           Command command = pendingQueue.poll();
           try {
               command.execute();
               executedStack.push(command);
          } catch (Exception e) {
               System.out.println("执行失败: " + command.getDescription());
               failedCommands.add(command);
               // 回滚已执行的命令
               rollbackAll();
               break;
          }
      }
  }

   public void rollbackAll() {
       System.out.println("开始回滚…");
       while (!executedStack.isEmpty()) {
           Command command = executedStack.pop();
           command.undo();
      }
  }

   public void undoLast() {
       if (!executedStack.isEmpty()) {
           Command command = executedStack.pop();
           command.undo();
      }
  }
}

框架应用
  • Runnable/Callable: 将任务封装为对象

  • Spring事务: 事务命令可回滚

  • GUI操作: 撤销/重做功能


18. 迭代器模式 Iterator

概念

提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露该对象的内部表示。

实战代码:分页数据迭代器

// ===== 分页迭代器:自动翻页获取数据 =====
public class PageIterator<T> implements Iterator<T> {
   private final Function<Integer, List<T>> pageFetcher;
   private final int pageSize;
   private int currentPage = 0;
   private List<T> currentBatch;
   private int indexInBatch = 0;
   private boolean hasMorePages = true;

   public PageIterator(Function<Integer, List<T>> pageFetcher, int pageSize) {
       this.pageFetcher = pageFetcher;
       this.pageSize = pageSize;
       fetchNextPage();
  }

   private void fetchNextPage() {
       currentBatch = pageFetcher.apply(currentPage);
       indexInBatch = 0;
       if (currentBatch == null || currentBatch.size() < pageSize) {
           hasMorePages = false;
      }
       currentPage++;
  }

   @Override
   public boolean hasNext() {
       if (currentBatch == null) return false;
       if (indexInBatch < currentBatch.size()) return true;
       if (hasMorePages) {
           fetchNextPage();
           return currentBatch != null && !currentBatch.isEmpty();
      }
       return false;
  }

   @Override
   public T next() {
       if (!hasNext()) throw new NoSuchElementException();
       return currentBatch.get(indexInBatch++);
  }
}

// ===== 使用:透明遍历百万数据 =====
public class Demo {
   public static void main(String[] args) {
       // 模拟从数据库分页查询
       PageIterator<User> iterator = new PageIterator<>(page -> {
           System.out.println("查询第 " + page + " 页");
           return userDao.findByPage(page, 1000);
      }, 1000);

       // 像遍历普通集合一样使用
       while (iterator.hasNext()) {
           User user = iterator.next();
           // 处理用户数据…
      }
  }
}

框架应用
  • Java集合: 所有Collection都实现了Iterable

  • JDBC ResultSet: 结果集游标遍历

  • MyBatis Cursor: 流式查询大数据量


四、设计模式对比与选型

模式对比速查表

模式分类核心意图关键词
单例 创建型 全局唯一实例 唯一、共享、全局
工厂方法 创建型 延迟到子类创建 解耦创建、多态
抽象工厂 创建型 创建产品族 产品族、风格统一
建造者 创建型 分步构建复杂对象 多参数、链式调用
原型 创建型 克隆已有对象 拷贝、模板
代理 结构型 控制对象访问 增强、拦截、AOP
适配器 结构型 接口转换 兼容、包装
装饰器 结构型 动态增加职责 包装、层层嵌套
外观 结构型 简化子系统接口 统一入口、简化
组合 结构型 部分-整体树结构 树形、递归
享元 结构型 共享减少内存 池化、缓存、复用
策略 行为型 算法可替换 if-else消除
模板方法 行为型 固定流程可变步骤 骨架、钩子
观察者 行为型 状态变更通知 事件、监听、发布订阅
责任链 行为型 链式传递处理 过滤器、拦截器
状态 行为型 状态驱动行为变更 状态机、自动流转
命令 行为型 请求封装为对象 撤销、队列、日志
迭代器 行为型 顺序访问集合 遍历、游标

面试高频问题

Q: 策略模式和状态模式的区别?

  • 策略:客户端选择算法,策略之间平等独立

  • 状态:状态自动流转,行为由内部状态决定

Q: 装饰器和代理的区别?

  • 装饰器:增强功能,可以层层叠加(关注功能扩展)

  • 代理:控制访问,通常只有一层(关注访问控制)

Q: 工厂方法和抽象工厂的区别?

  • 工厂方法:一个工厂生产一种产品(产品等级)

  • 抽象工厂:一个工厂生产一族产品(产品族)

Q: 模板方法和策略模式的区别?

  • 模板方法:基于继承,子类实现抽象步骤(白箱复用)

  • 策略:基于组合,运行时注入策略对象(黑箱复用)

设计原则与模式关系

设计原则相关模式
单一职责 策略、命令、状态
开闭原则 策略、工厂方法、装饰器
里氏替换 模板方法、策略
接口隔离 适配器、外观
依赖倒置 工厂、策略、观察者
迪米特法则 外观、中介者

本文涵盖了面试中高频出现的18种设计模式,每种模式都提供了贴近实际业务的代码示例。建议结合Spring框架源码加深理解,重点掌握策略、工厂、代理、模板方法、责任链这五种在企业开发中使用最为广泛的模式。

赞(0)
未经允许不得转载:171主机测评 » 设计模式详解与实战:23种经典模式精讲
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址