设计模式
设计模式 #
软件设计的最佳实践,23种经典设计模式详解
📋 目录 #
设计模式概述 #
三类设计模式 #
设计原则 #
| 原则 | 说明 | 简写 |
|---|---|---|
| 单一职责 | 类只负责一项职责 | SRP |
| 开闭原则 | 对扩展开放,对修改关闭 | OCP |
| 里氏替换 | 子类可替换父类 | LSP |
| 接口隔离 | 接口细化,不依赖不需要 | ISP |
| 依赖倒置 | 依赖抽象,不依赖具体 | DIP |
创建型模式 #
单例模式 #
面试高频 ⭐⭐⭐⭐⭐
目的: 确保类只有一个实例,并提供全局访问点
// 饿汉式 - 类加载时创建
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
// 懒汉式 - 第一次使用时创建
public class LazySingleton {
private static volatile LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) { // 双重检查
instance = new LazySingleton();
}
}
}
return instance;
}
}
// 枚举方式 - 推荐线程安全
public enum EnumSingleton {
INSTANCE;
public void doSomething() {
// 业务逻辑
}
}
// Spring中使用
@Service
public class SingletonService {
// Spring默认单例
}
应用场景:
- 配置中心
- 线程池
- 缓存管理
- 数据库连接池
工厂模式 #
面试高频 ⭐⭐⭐⭐
目的: 封装对象创建过程,降低耦合
// 简单工厂
public interface Payment {
void pay(BigDecimal amount);
}
public class AlipayPayment implements Payment {
public void pay(BigDecimal amount) {
System.out.println("支付宝支付: " + amount);
}
}
public class WechatPayment implements Payment {
public void pay(BigDecimal amount) {
System.out.println("微信支付: " + amount);
}
}
// 工厂类
public class PaymentFactory {
public static Payment createPayment(String type) {
switch (type) {
case "alipay":
return new AlipayPayment();
case "wechat":
return new WechatPayment();
default:
throw new IllegalArgumentException("不支持的支付方式");
}
}
}
// 使用
Payment payment = PaymentFactory.createPayment("alipay");
payment.pay(new BigDecimal("100.00"));
应用场景:
- 需要创建多种相似对象
- 不想暴露创建逻辑
- 数据库连接工厂
- Spring Bean工厂
建造者模式 #
目的: 分步骤创建复杂对象
public class Computer {
private String cpu;
private String memory;
private String storage;
private String gpu;
private Computer() {}
// 建造者
public static class Builder {
private Computer computer = new Computer();
public Builder cpu(String cpu) {
computer.cpu = cpu;
return this;
}
public Builder memory(String memory) {
computer.memory = memory;
return this;
}
public Builder storage(String storage) {
computer.storage = storage;
return this;
}
public Builder gpu(String gpu) {
computer.gpu = gpu;
return this;
}
public Computer build() {
return computer;
}
}
@Override
public String toString() {
return "Computer{" + "cpu='" + cpu + "', memory='" + memory +
"', storage='" + storage + "', gpu='" + gpu + "'}";
}
}
// 使用链式调用
Computer computer = new Computer.Builder()
.cpu("Intel i9")
.memory("32GB DDR5")
.storage("1TB SSD")
.gpu("RTX 4090")
.build();
应用场景:
- 复杂对象构建
- Lombok @Builder注解
- StringBuilder(字符构建)
结构型模式 #
适配器模式 #
目的: 将一个类的接口转换成客户希望的另一个接口
// 目标接口
public interface PowerSocket {
void provide220V();
}
// 被适配者 - 美国插座
public class USPowerSocket {
public void provide110V() {
System.out.println("提供110V电压");
}
}
// 适配器
public class PowerAdapter implements PowerSocket {
private USPowerSocket usSocket;
public PowerAdapter(USPowerSocket usSocket) {
this.usSocket = usSocket;
}
@Override
public void provide220V() {
System.out.println("电压转换110V → 220V");
usSocket.provide110V();
}
}
// 使用
USPowerSocket usSocket = new USPowerSocket();
PowerSocket adapter = new PowerAdapter(usSocket);
adapter.provide220V(); // 提供转换后的220V
应用场景:
- Spring MVC HandlerAdapter
- 异常处理器转换
- 第三方API对接
装饰器模式 #
目的: 动态地给对象添加额外功能
// Component接口
public interface Coffee {
double cost();
String description();
}
// ConcreteComponent
public class BlackCoffee implements Coffee {
public double cost() {
return 10.0;
}
public String description() {
return "黑咖啡";
}
}
// Decorator
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
// ConcreteDecorator
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public double cost() {
return coffee.cost() + 2.0;
}
public String description() {
return coffee.description() + ", 牛奶";
}
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
public double cost() {
return coffee.cost() + 1.0;
}
public String description() {
return coffee.description() + ", 糖";
}
}
// 使用 - 动态组合
Coffee coffee = new BlackCoffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
System.out.println(coffee.description()); // 黑咖啡, 牛奶, 糖
System.out.println(coffee.cost()); // 13.0
应用场景:
- Java I/O (new BufferedReader(new FileReader(...)))
- Spring Bean装饰
代理模式 #
面试高频 ⭐⭐⭐⭐⭐
目的: 控制对象的访问
// 接口
public interface UserService {
User getUser(Long id);
}
// 真实对象
public class UserServiceImpl implements UserService {
public User getUser(Long id) {
System.out.println("查询数据库获取用户");
return new User(id, "Tom");
}
}
// 代理对象
public class UserServiceProxy implements UserService {
private UserServiceImpl realService;
public UserServiceProxy() {
this.realService = new UserServiceImpl();
}
@Override
public User getUser(Long id) {
System.out.println("前置逻辑: 权限检查");
User user = realService.getUser(id);
System.out.println("后置逻辑: 记录日志");
return user;
}
}
// 使用
UserService proxy = new UserServiceProxy();
proxy.getUser(1L);
应用场景:
- 远程代理 (RPC)
- 虚拟代理 (懒加载)
- 保护代理 (权限)
- Spring AOP动态代理
外观模式 #
目的: 为复杂子系统提供简单接口
// 复杂子系统
class CPU {
public void run() { System.out.println("CPU工作"); }
}
class Memory {
public void load() { System.out.println("内存加载"); }
}
class HardDrive {
public void read() { System.out.println("硬盘读取"); }
}
// 外观类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void start() {
System.out.println("电脑启动");
hardDrive.read();
memory.load();
cpu.run();
System.out.println("启动完成");
}
}
// 使用 - 简化接口
ComputerFacade computer = new ComputerFacade();
computer.start();
应用场景:
- SLF4J (统一日志接口)
- 复杂API简化
- Spring JdbcTemplate
行为型模式 #
策略模式 #
面试高频 ⭐⭐⭐⭐⭐
目的: 定义算法族,分别封装,互相替换
// 支付策略接口
public interface PaymentStrategy {
void pay(BigDecimal amount);
}
// 策略实现
public class AlipayStrategy implements PaymentStrategy {
public void pay(BigDecimal amount) {
System.out.println("支付宝支付: " + amount);
}
}
public class WechatStrategy implements PaymentStrategy {
public void pay(BigDecimal amount) {
System.out.println("微信支付: " + amount);
}
}
public class UnionPayStrategy implements PaymentStrategy {
public void pay(BigDecimal amount) {
System.out.println("银联支付: " + amount);
}
}
// 上下文
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(BigDecimal amount) {
strategy.pay(amount);
}
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
}
// 使用 - 动态切换策略
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(new BigDecimal("100.00"));
context.setStrategy(new WechatStrategy());
context.executePayment(new BigDecimal("200.00"));
应用场景:
- 多种支付方式 ⭐
- 多种排序算法
- 多种压缩方式
- Spring @Transactional 事务管理
模板方法模式 #
面试高频 ⭐⭐⭐⭐
目的: 定义算法骨架,子类实现具体步骤
// 抽象类 - 算法骨架
public abstract class DataProcessor {
// 模板方法 - 定义算法流程 (final防止重写)
public final void process() {
loadData();
validate();
transform();
save();
}
// 抽象方法 - 子类实现
protected abstract void loadData();
protected abstract void validate();
protected abstract void transform();
protected abstract void save();
// 钩子方法 - 可选重写
protected void beforeSave() {
System.out.println("默认前置处理");
}
}
// 具体实现
public class CSVDataProcessor extends DataProcessor {
protected void loadData() {
System.out.println("加载CSV数据");
}
protected void validate() {
System.out.println("CSV数据校验");
}
protected void transform() {
System.out.println("CSV格式转换");
}
protected void save() {
beforeSave();
System.out.println("保存CSV数据");
}
}
// 使用
DataProcessor csvProcessor = new CSVDataProcessor();
csvProcessor.process();
应用场景:
- Spring JdbcTemplate ⭐
- Spring RestTemplate ⭐
- Spring RedisTemplate
- Servlet doGet/doPost
观察者模式 #
面试高频 ⭐⭐⭐⭐⭐
目的: 一对多依赖,对象状态变化通知依赖者
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(String message);
}
// 被观察者
class Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void setState(String state) {
this.state = state;
notifyObservers();
}
private void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 具体观察者
class EmailObserver implements Observer {
public void update(String message) {
System.out.println("邮件通知: " + message);
}
}
class SMSObserver implements Observer {
public void update(String message) {
System.out.println("短信通知: " + message);
}
}
// 使用
Subject subject = new Subject();
subject.attach(new EmailObserver());
subject.attach(new SMSObserver());
subject.setState("订单已创建"); // 所有观察者收到通知
Java内置观察者:
import java.util.Observable;
import java.util.Observer;
// 使用Java内置Observer
class MessagePublisher extends Observable {
public void publish(String message) {
setChanged();
notifyObservers(message);
}
}
class User implements Observer {
public void update(Observable o, Object arg) {
System.out.println("收到消息: " + arg);
}
}
应用场景:
- 事件总线 (EventBus)
- 消息系统 (MQ)
- Spring ApplicationEvent
- 股市行情推送
状态机模式 #
目的:
示例: 订单状态机
// 状态接口
interface OrderState {
void process(Order order);
}
// 具体状态
class CreatedState implements OrderState {
public void process(Order order) {
System.out.println("订单已创建");
if (order.isPaid()) {
order.setState(new PaidState());
}
}
}
class PaidState implements OrderState {
public void process(Order order) {
System.out.println("订单已支付");
if (order.isShipped()) {
order.setState(new ShippedState());
}
}
}
class ShippedState implements OrderState {
public void process(Order order) {
System.out.println("订单已发货");
if (order.isDelivered()) {
order.setState(new CompletedState());
}
}
}
class CompletedState implements OrderState {
public void process(Order order) {
System.out.println("订单已完成");
}
}
// 订单类 (上下文)
class Order {
private OrderState state = new CreatedState();
private boolean paid = false;
private boolean shipped = false;
private boolean delivered = false;
public void setState(OrderState state) {
this.state = state;
}
public void process() {
state.process(this);
}
// 订单事件触发
public void paid() { this.paid = true; }
public void shipped() { this.shipped = true; }
public void delivered() { this.delivered = true; }
// getters
public boolean isPaid() { return paid; }
public boolean isShipped() { return shipped; }
public boolean isDelivered() { return delivered; }
}
// 使用
Order order = new Order();
order.process(); // 订单已创建
order.paid();
order.process(); // 订单已支付
order.shipped();
order.process(); // 订单已发货
order.delivered();
order.process(); // 订单已完成
应用场景:
- 交易系统 ⭐
- 订单状态管理
- 工单流转
- 审批流程
- 游戏状态
常见模式对比 #
| 模式 | 目的 | 典型场景 |
|---|---|---|
| 工厂 | 创建对象 | Spring BeanFactory |
| 策略 | 算法替换 | 多种支付方式 |
| 观察者 | 事件通知 | Spring Event |
| 模板方法 | 算法骨架 | JdbcTemplate |
| 代理 | 控制访问 | Spring AOP |
| 装饰器 | 动态增强 | I/O流、AOP |
| 适配器 | 接口转换 | HandlerAdapter |
| 状态机 | 状态流转 | 订单状态管理 |
面试题汇总 #
创建型 #
- 单例模式的几种实现方式?
- 工厂模式何时使用?
- 建造者模式与工厂模式区别?
结构型 #
- 适配器模式 vs 装饰器模式?
- 代理模式的应用场景?
- Spring用了哪些设计模式?
行为型 #
- 策略模式与工厂模式区别?
- 观察者模式的实现方式?
- 模板方法模式的应用?
综合题 #
- Spring IOC用了哪些设计模式?
- Spring AOP用了哪些设计模式?
- 你在项目中用过哪些设计模式?
面试题答案详解 #
创建型 #
- 单例模式的几种实现方式?
答案:
| 实现方式 | 说明 |
|---|---|
| 饿汉式 | 类加载就创建,线程安全 |
| 懒汉式 | 第一次用才创建,有并发问题 |
| 双重检查锁定 | DCL + volatile,线程安全 |
| 枚举方式 | 最简单,天然线程安全,推荐 |
代码示例:
// 1. 饿汉式
public class Singleton1 {
private static final Singleton1 INSTANCE = new Singleton1();
private Singleton1() {}
public static Singleton1 getInstance() {
return INSTANCE;
}
}
// 2. 双重检查锁定
public class Singleton2 {
private static volatile Singleton2 instance;
private Singleton2() {}
public static Singleton2 getInstance() {
if (instance == null) {
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();
}
}
}
return instance;
}
}
// 3. 枚举(推荐)
public enum Singleton3 {
INSTANCE;
public void doSomething() {}
}
- 工厂模式何时使用?
答案:
工厂模式适用场景:
| 场景 | 说明 |
|---|---|
| 创建对象逻辑复杂 | 非new那么简单 |
| 多种实现方式 | 根据条件返回不同实现 |
| 不想暴露创建细节 | 客户端只知道接口 |
| 解耦 | 创建和使用分离 |
示例:
// 根据类型创建不同的支付方式
PaymentFactory.create("alipay");
PaymentFactory.create("wechat");
- 建造者模式与工厂模式区别?
答案:
| 对比 | 工厂模式 | 建造者模式 |
|---|---|---|
| 关注点 | 创建什么对象 | 怎么创建对象(步骤) |
| 复杂度 | 简单 | 复杂 |
| 产品数 | 多个产品 | 一个产品,多种配置 |
| 示例 | PaymentFactory | Computer.Builder |
结构型 #
- 适配器模式 vs 装饰器模式?
答案:
| 对比 | 适配器模式 | 装饰器模式 |
|---|---|---|
| 目的 | 接口转换 | 增加功能 |
| 关系 | 不相关 → 兼容 | 同类增强 |
| 示例 | PowerAdapter、HandlerAdapter | InputStreamDecorator |
- 代理模式的应用场景?
答案:
| 场景 | 示例 |
|---|---|
| 远程代理 | RMI、RPC |
| 虚拟代理 | 图片懒加载 |
| 保护代理 | 权限控制 |
| 智能引用 | AOP动态代理 |
- Spring用了哪些设计模式?
答案:
| 模式 | Spring中的应用 |
|---|---|
| 工厂模式 | BeanFactory、ApplicationContext |
| 单例模式 | Bean默认单例 |
| 代理模式 | AOP(JDK/CGLIB) |
| 模板方法 | JdbcTemplate、RestTemplate |
| 观察者模式 | ApplicationEvent、Listener |
| 策略模式 | InstantiationStrategy |
| 装饰器模式 | BeanWrapper |
| 适配器模式 | HandlerAdapter |
行为型 #
- 策略模式与工厂模式区别?
答案:
| 对比 | 工厂模式 | 策略模式 |
|---|---|---|
| 目的 | 创建对象 | 选择算法 |
| 关注点 | 创建 | 行为 |
| 阶段 | 创建时 | 运行时 |
| 关系 | 创建 | 组合 |
策略模式结构:
- 观察者模式的实现方式?
答案:
| 方式 | 说明 |
|---|---|
| Java内置 | Observable + Observer(已过时) |
| 自定义 | Subject + Observer |
| 事件总线 | Guava EventBus、Spring Event |
Spring事件示例:
@Component
public class UserRegisteredEvent extends ApplicationEvent {
public UserRegisteredEvent(User user) {
super(user);
}
}
@Component
public class EmailListener {
@EventListener
public void onUserRegistered(UserRegisteredEvent event) {
}
}
- 模板方法模式的应用?
答案:
模板方法 = 算法骨架 + 子类实现
Spring中的应用:
| 应用 | 说明 |
|---|---|
| JdbcTemplate | SQL执行流程 |
| RestTemplate | HTTP请求流程 |
| AbstractRoutingDataSource | DataSource路由 |
| ApplicationContext.refresh | 容器刷新流程 |
综合题 #
- Spring IOC用了哪些设计模式?
答案:
| 模式 | 说明 |
|---|---|
| 工厂模式 | BeanFactory创建Bean |
| 单例模式 | 默认Singleton作用域 |
| 装饰器模式 | BeanWrapper装饰 |
| 策略模式 | InstantiationStrategy创建策略 |
| 观察者模式 | Bean生命周期回调 |
| 模板方法 | refresh()方法 |
- Spring AOP用了哪些设计模式?
答案:
| 模式 | 说明 |
|---|---|
| 代理模式 | JDK/CGLIB动态代理 |
| 策略模式 | 代理策略选择 |
| 观察者模式 | AOP通知 |
| 装饰器模式 | ProxyFactoryBean |
- 你在项目中用过哪些设计模式?
答案:
回答模板:
1. 策略模式
- 场景: 多种支付方式(Alipay/WechatPay)
- 好处: 新增支付方式不用改原有代码
2. 模板方法
- 场景: 不同第三方接口调用流程一致
- 好处: 复用流程,扩展方便
3. 建造者
- 场景: 复杂对象构建
- 好处: 链式调用,清晰
4. 观察者模式
- 场景: 订单创建后通知多个系统
- 好处: 解耦
🔗 相关笔记 #
📚 扩展阅读 #
- 《设计模式:可复用面向对象软件的基础》
- 《Head First 设计模式》
- 《敏捷软件开发:原则、模式与实践》
最后更新: 2026-04-29