# 设计模式 ## 问题 1. 什么是设计模式?设计模式的六大原则是什么? 2. 单例模式的实现方式有哪些?如何保证线程安全? 3. 工厂模式和抽象工厂模式的区别是什么? 4. 观察者模式的应用场景有哪些?Spring 中哪些地方用到了观察者模式? 5. 策略模式如何解决 if-else 过多的问题? 6. 装饰器模式和代理模式的区别是什么? 7. 在实际项目中如何使用设计模式? --- ## 标准答案 ### 1. 设计模式的六大原则(SOLID + 1) #### **单一职责原则(Single Responsibility Principle)** **定义**:一个类只负责一个职责。 **示例**: ```java // ❌ 违反单一职责 class UserService { public void saveUser(User user) { } public void sendEmail(User user) { } public void log(User user) { } } // ✅ 符合单一职责 class UserService { public void saveUser(User user) { } } class EmailService { public void sendEmail(User user) { } } class LogService { public void log(User user) { } } ``` --- #### **开闭原则(Open-Closed Principle)** **定义**:对扩展开放,对修改关闭。 **示例**: ```java // ❌ 每次新增类型需要修改代码 class OrderService { public double calculateDiscount(String type, double price) { if (type.equals("VIP")) { return price * 0.8; } else if (type.equals("SVIP")) { return price * 0.7; } // 新增类型需要修改这里 return price; } } // ✅ 使用策略模式 interface DiscountStrategy { double calculate(double price); } class VipDiscount implements DiscountStrategy { @Override public double calculate(double price) { return price * 0.8; } } class OrderService { private Map strategyMap = new HashMap<>(); public void registerStrategy(String type, DiscountStrategy strategy) { strategyMap.put(type, strategy); } public double calculateDiscount(String type, double price) { DiscountStrategy strategy = strategyMap.get(type); return strategy != null ? strategy.calculate(price) : price; } } ``` --- #### **里氏替换原则(Liskov Substitution Principle)** **定义**:子类可以替换父类出现在父类能够出现的任何地方。 **示例**: ```java // ❌ 违反里氏替换 class Bird { public void fly() { System.out.println("Flying"); } } class Penguin extends Bird { @Override public void fly() { throw new UnsupportedOperationException("企鹅不会飞"); } } // ✅ 符合里氏替换 class Bird { } class FlyingBird extends Bird { public void fly() { System.out.println("Flying"); } } class Penguin extends Bird { public void swim() { System.out.println("Swimming"); } } ``` --- #### **接口隔离原则(Interface Segregation Principle)** **定义**:客户端不应该依赖它不需要的接口。 **示例**: ```java // ❌ 接口过于臃肿 interface Animal { void fly(); void swim(); void run(); } // ✅ 拆分接口 interface Flyable { void fly(); } interface Swimmable { void swim(); } interface Runnable { void run(); } class Duck implements Flyable, Swimmable, Runnable { @Override public void fly() { } @Override public void swim() { } @Override public void run() { } } ``` --- #### **依赖倒置原则(Dependency Inversion Principle)** **定义**:高层模块不应该依赖低层模块,两者都应该依赖抽象。 **示例**: ```java // ❌ 高层依赖低层 class OrderService { private MySQLDatabase database = new MySQLDatabase(); // 直接依赖具体实现 public void saveOrder(Order order) { database.save(order); } } // ✅ 依赖抽象 interface Database { void save(Object obj); } class MySQLDatabase implements Database { @Override public void save(Object obj) { // MySQL 实现 } } class OrderService { private final Database database; public OrderService(Database database) { this.database = database; // 依赖注入 } public void saveOrder(Order order) { database.save(order); } } ``` --- #### **迪米特法则(Law of Demeter / Least Knowledge Principle)** **定义**:一个对象应该对其他对象有最少的了解。 **示例**: ```java // ❌ 违反迪米特法则 class Customer { private Order order; public void printOrderDetails() { System.out.println(order.getItem().getProduct().getName()); // Customer → Order → Item → Product(了解太多) } } // ✅ 符合迪米特法则 class Customer { private Order order; public void printOrderDetails() { System.out.println(order.getProductName()); } } class Order { private Item item; public String getProductName() { return item.getProduct().getName(); } } ``` --- ### 2. 单例模式 #### **实现方式** ##### **方式 1:饿汉式(线程安全)** ```java public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() { } public static Singleton getInstance() { return INSTANCE; } } ``` **优点**:简单、线程安全 **缺点**:类加载时初始化,可能浪费资源 --- ##### **方式 2:懒汉式(线程不安全)** ```java public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } ``` **问题**:线程不安全 --- ##### **方式 3:懒汉式 + synchronized(线程安全但性能差)** ```java public class Singleton { private static Singleton instance; private Singleton() { } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } ``` **问题**:每次调用都需要加锁,性能差 --- ##### **方式 4:双重检查锁定(推荐)** ```java public class Singleton { // volatile 禁止指令重排序 private static volatile Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { // 第一次检查(无锁) synchronized (Singleton.class) { if (instance == null) { // 第二次检查(有锁) instance = new Singleton(); } } } return instance; } } ``` **为什么需要 volatile?** ```java instance = new Singleton(); // 分三步: // 1. 分配内存 // 2. 初始化对象 // 3. 将 instance 指向内存 // 指令重排序后可能是:1 → 3 → 2 // 线程 A 执行了 1、3,线程 B 发现 instance 不为 null,但对象未初始化! ``` --- ##### **方式 5:静态内部类(推荐)** ```java public class Singleton { private Singleton() { } private static class Holder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; } } ``` **优点**: - 延迟加载(调用 getInstance 时才初始化) - 线程安全(类加载机制保证) - 性能好(无锁) --- ##### **方式 6:枚举(最佳实践)** ```java public enum Singleton { INSTANCE; public void doSomething() { // 业务方法 } } // 使用 Singleton.INSTANCE.doSomething(); ``` **优点**: - 线程安全(JVM 保证) - 防止反射攻击 - 防止序列化破坏 --- #### **单例模式的问题** **1. 反射破坏单例**: ```java Constructor constructor = Singleton.class.getDeclaredConstructor(); constructor.setAccessible(true); Singleton instance1 = constructor.newInstance(); Singleton instance2 = constructor.newInstance(); // instance1 != instance2(单例被破坏) ``` **解决**: ```java private Singleton() { if (Holder.INSTANCE != null) { throw new RuntimeException("不允许创建多个实例"); } } ``` **2. 序列化破坏单例**: ```java Singleton instance1 = Singleton.getInstance(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(instance1); ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray()) ); Singleton instance2 = (Singleton) ois.readObject(); // instance1 != instance2(单例被破坏) ``` **解决**: ```java public class Singleton implements Serializable { private Singleton() { } private static class Holder { private static final Singleton INSTANCE = new Singleton(); } // 反序列化时返回单例 private Object readResolve() { return Holder.INSTANCE; } } ``` --- ### 3. 工厂模式 #### **简单工厂** ```java // 产品接口 interface Payment { void pay(int amount); } // 具体产品 class Alipay implements Payment { @Override public void pay(int amount) { System.out.println("支付宝支付:" + amount); } } class WechatPay implements Payment { @Override public void pay(int amount) { System.out.println("微信支付:" + amount); } } // 工厂类 class PaymentFactory { public static Payment createPayment(String type) { switch (type) { case "alipay": return new Alipay(); case "wechat": return new WechatPay(); default: throw new IllegalArgumentException("不支持支付方式"); } } } // 使用 Payment payment = PaymentFactory.createPayment("alipay"); payment.pay(100); ``` **问题**:新增支付方式需要修改工厂类(违反开闭原则) --- #### **工厂方法** ```java // 工厂接口 interface PaymentFactory { Payment createPayment(); } // 具体工厂 class AlipayFactory implements PaymentFactory { @Override public Payment createPayment() { return new Alipay(); } } class WechatPayFactory implements PaymentFactory { @Override public Payment createPayment() { return new WechatPay(); } } // 使用 PaymentFactory factory = new AlipayFactory(); Payment payment = factory.createPayment(); payment.pay(100); ``` **优点**:符合开闭原则(新增支付方式无需修改代码) --- #### **抽象工厂** **场景**:跨平台 UI 工具包 ```java // 抽象产品 interface Button { void render(); } interface Checkbox { void render(); } // 具体产品(Windows 风格) class WindowsButton implements Button { @Override public void render() { System.out.println("Windows 按钮"); } } class WindowsCheckbox implements Checkbox { @Override public void render() { System.out.println("Windows 复选框"); } } // 具体产品(Mac 风格) class MacButton implements Button { @Override public void render() { System.out.println("Mac 按钮"); } } class MacCheckbox implements Checkbox { @Override public void render() { System.out.println("Mac 复选框"); } } // 抽象工厂 interface GUIFactory { Button createButton(); Checkbox createCheckbox(); } // 具体工厂 class WindowsFactory implements GUIFactory { @Override public Button createButton() { return new WindowsButton(); } @Override public Checkbox createCheckbox() { return new WindowsCheckbox(); } } class MacFactory implements GUIFactory { @Override public Button createButton() { return new MacButton(); } @Override public Checkbox createCheckbox() { return new MacCheckbox(); } } // 使用 GUIFactory factory = new WindowsFactory(); Button button = factory.createButton(); Checkbox checkbox = factory.createCheckbox(); button.render(); checkbox.render(); ``` --- ### 4. 观察者模式 #### **原理** 定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都得到通知并自动更新。 --- #### **Java 实现** ```java // 观察者接口 interface Observer { void update(String message); } // 被观察者(主题) interface Subject { void attach(Observer observer); void detach(Observer observer); void notifyObservers(); } // 具体主题 class MessageQueue implements Subject { private List observers = new ArrayList<>(); private String message; @Override public void attach(Observer observer) { observers.add(observer); } @Override public void detach(Observer observer) { observers.remove(observer); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update(message); } } public void setMessage(String message) { this.message = message; notifyObservers(); } } // 具体观察者 class EmailNotifier implements Observer { @Override public void update(String message) { System.out.println("发送邮件:" + message); } } class SMSNotifier implements Observer { @Override public void update(String message) { System.out.println("发送短信:" + message); } } // 使用 MessageQueue queue = new MessageQueue(); queue.attach(new EmailNotifier()); queue.attach(new SMSNotifier()); queue.setMessage("新订单创建"); ``` --- #### **Spring 事件机制(观察者模式)** ```java // 1. 定义事件 class OrderCreatedEvent extends ApplicationEvent { private final Order order; public OrderCreatedEvent(Object source, Order order) { super(source); this.order = order; } public Order getOrder() { return order; } } // 2. 定义监听器 @Component class OrderEmailListener { @EventListener public void handleOrderCreated(OrderCreatedEvent event) { System.out.println("发送邮件:" + event.getOrder()); } } @Component class OrderSMSListener { @EventListener public void handleOrderCreated(OrderCreatedEvent event) { System.out.println("发送短信:" + event.getOrder()); } } // 3. 发布事件 @Service class OrderService { @Autowired private ApplicationEventPublisher eventPublisher; public void createOrder(Order order) { // 保存订单 orderRepository.save(order); // 发布事件 eventPublisher.publishEvent(new OrderCreatedEvent(this, order)); } } ``` --- ### 5. 策略模式 #### **场景:计算不同类型的折扣** ```java // 策略接口 interface DiscountStrategy { double calculate(double price); } // 具体策略 class VipDiscount implements DiscountStrategy { @Override public double calculate(double price) { return price * 0.8; } } class SvipDiscount implements DiscountStrategy { @Override public double calculate(double price) { return price * 0.7; } } class NormalDiscount implements DiscountStrategy { @Override public double calculate(double price) { return price; } } // 上下文 class OrderService { private Map strategyMap = new HashMap<>(); @PostConstruct public void init() { strategyMap.put("VIP", new VipDiscount()); strategyMap.put("SVIP", new SvipDiscount()); strategyMap.put("NORMAL", new NormalDiscount()); } public double calculatePrice(String userType, double price) { DiscountStrategy strategy = strategyMap.get(userType); if (strategy == null) { throw new IllegalArgumentException("不支持的用户类型"); } return strategy.calculate(price); } } // 使用 OrderService orderService = new OrderService(); double price = orderService.calculatePrice("VIP", 100); ``` --- #### **Spring 实现策略模式** ```java // 策略接口 public interface PaymentStrategy { void pay(int amount); // 获取策略类型 String getType(); } // 具体策略(标注为 Spring Bean) @Component public class AlipayStrategy implements PaymentStrategy { @Override public void pay(int amount) { System.out.println("支付宝支付:" + amount); } @Override public String getType() { return "alipay"; } } @Component public class WechatPayStrategy implements PaymentStrategy { @Override public void pay(int amount) { System.out.println("微信支付:" + amount); } @Override public String getType() { return "wechat"; } } // 策略工厂 @Service public class PaymentService { private final Map strategyMap; // 构造器注入所有策略 public PaymentService(List strategies) { this.strategyMap = strategies.stream() .collect(Collectors.toMap( PaymentStrategy::getType, Function.identity() )); } public void pay(String type, int amount) { PaymentStrategy strategy = strategyMap.get(type); if (strategy == null) { throw new IllegalArgumentException("不支持的支付方式"); } strategy.pay(amount); } } ``` --- ### 6. 装饰器模式 vs 代理模式 #### **装饰器模式** **目的**:动态地给对象添加功能 **示例**: ```java // 组件接口 interface Coffee { double cost(); } // 具体组件 class SimpleCoffee implements Coffee { @Override public double cost() { return 10; } } // 装饰器 class MilkDecorator implements Coffee { private final Coffee coffee; public MilkDecorator(Coffee coffee) { this.coffee = coffee; } @Override public double cost() { return coffee.cost() + 2; // 加奶 2 元 } } class SugarDecorator implements Coffee { private final Coffee coffee; public SugarDecorator(Coffee coffee) { this.coffee = coffee; } @Override public double cost() { return coffee.cost() + 1; // 加糖 1 元 } } // 使用 Coffee coffee = new SimpleCoffee(); coffee = new MilkDecorator(coffee); // 加奶 coffee = new SugarDecorator(coffee); // 加糖 System.out.println(coffee.cost()); // 10 + 2 + 1 = 13 ``` --- #### **代理模式** **目的**:控制对对象的访问 **静态代理**: ```java // 接口 interface OrderService { void createOrder(Order order); } // 真实对象 class OrderServiceImpl implements OrderService { @Override public void createOrder(Order order) { System.out.println("创建订单:" + order); } } // 代理对象 class OrderServiceProxy implements OrderService { private final OrderService orderService; public OrderServiceProxy(OrderService orderService) { this.orderService = orderService; } @Override public void createOrder(Order order) { // 前置增强 System.out.println("权限检查"); // 调用真实对象 orderService.createOrder(order); // 后置增强 System.out.println("日志记录"); } } // 使用 OrderService proxy = new OrderServiceProxy(new OrderServiceImpl()); proxy.createOrder(new Order()); ``` --- **动态代理(JDK)**: ```java class ProxyHandler implements InvocationHandler { private final Object target; public ProxyHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前置增强 System.out.println("权限检查"); // 调用真实对象 Object result = method.invoke(target, args); // 后置增强 System.out.println("日志记录"); return result; } } // 使用 OrderService realService = new OrderServiceImpl(); OrderService proxyService = (OrderService) Proxy.newProxyInstance( realService.getClass().getClassLoader(), realService.getClass().getInterfaces(), new ProxyHandler(realService) ); proxyService.createOrder(new Order()); ``` --- #### **对比** | 特性 | 装饰器模式 | 代理模式 | |------|-----------|---------| | **目的** | 增强功能 | 控制访问 | | **关注点** | 功能扩展 | 访问控制 | | **透明性** | 对客户端透明 | 客户端可能知道代理存在 | | **示例** | Java I/O Streams | Spring AOP | --- ### 7. 实际项目应用 #### **Spring 中的设计模式** 1. **工厂模式**:`BeanFactory`、`ApplicationContext` 2. **单例模式**:Spring Bean(默认单例) 3. **代理模式**:AOP、事务管理 4. **观察者模式**:ApplicationEvent、ApplicationListener 5. **策略模式**:`Resource`(不同资源加载策略) 6. **模板方法模式**:`JdbcTemplate`、`RestTemplate` 7. **适配器模式**:`HandlerAdapter` 8. **责任链模式**:Filter Chain、Interceptor Chain --- ### 8. 阿里 P7 加分项 **深度理解**: - 理解设计模式的适用场景和权衡 - 理解设计模式与重构的关系 - 理解设计模式在开源框架中的应用 **实战经验**: - 有使用设计模式重构代码的经验 - 有设计模式误用的经验和教训 - 能根据业务特点选择合适的设计模式 **架构能力**: - 能设计可扩展、可维护的架构 - 能识别代码中的坏味道并重构 - 能在团队中推广设计模式最佳实践