系统讲解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框架源码加深理解,重点掌握策略、工厂、代理、模板方法、责任链这五种在企业开发中使用最为广泛的模式。




