| title | 设计模式八股文 | ||
|---|---|---|---|
| date | 2024-08-31 | ||
| tags |
|
||
| categories | Interview |
设计模式是Java开发者必备的技能,也是面试中高频考点。从经典的23种GoF设计模式到Spring框架中的模式应用,从单例模式的7种写法到代理模式的动态实现,每一个模式都承载着前辈的智慧结晶。掌握设计模式,让你的代码更优雅、更健壮、更具扩展性!
设计模式面试要点:
- 设计原则(SOLID原则、迪米特法则、合成复用原则)
- 创建型模式(单例、工厂、建造者、原型、抽象工厂)
- 结构型模式(适配器、装饰器、代理、桥接、组合、外观、享元)
- 行为型模式(观察者、策略、模板方法、责任链、状态、命令)
- 实际应用(Spring中的模式、项目实战经验)
- 📏 设计原则:SOLID原则、开闭原则、里氏替换原则、依赖倒置原则、单一职责原则
- 🏗️ 创建型模式:单例模式、工厂模式、建造者模式、原型模式、抽象工厂模式
- 🔧 结构型模式:适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式、享元模式
- ⚡ 行为型模式:观察者模式、策略模式、模板方法模式、责任链模式、状态模式、命令模式、中介者模式
- 🌟 实际应用:Spring中的设计模式、项目实战案例、最佳实践
| 问题类型 | 回答框架 | 关键要点 | 深入扩展 |
|---|---|---|---|
| 概念解释 | 定义→目的→结构→应用 | 核心思想,解决问题 | 源码分析,实际项目 |
| 模式对比 | 相同点→不同点→使用场景→选择建议 | 多维度对比 | 性能差异,适用性 |
| 实现原理 | 背景→问题→解决方案→代码实现 | UML图,代码结构 | 源码实现,优缺点 |
| 应用实践 | 项目背景→遇到问题→选择模式→效果评估 | 实际案例 | 最佳实践,踩坑经验 |
核心思想:设计原则是设计模式的理论基础,指导我们写出高质量的代码,是所有设计模式遵循的基本准则。
"设计模式是软件开发中经过验证的,用于解决特定环境下重复出现问题的解决方案:
设计模式的本质:
- 是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结
- 提供了一种统一的术语和概念,便于开发者之间的沟通
- 提高代码的可重用性、可读性、可靠性和可维护性
GoF 23种设计模式:
- 创建型模式(5种):关注对象的创建
- 结构型模式(7种):关注类和对象的组合
- 行为型模式(11种):关注对象之间的通信
在项目中的应用:
- 单例模式:配置管理器、数据库连接池
- 工厂模式:对象创建、消息处理器选择
- 观察者模式:事件处理、消息通知
- 策略模式:支付方式选择、算法切换
设计模式不是万能的,要根据具体场景选择,避免过度设计。"
"设计原则是设计模式的理论基础,主要有SOLID五大原则:
SOLID原则:
1. 单一职责原则(Single Responsibility Principle, SRP):
- 一个类只应该有一个引起它变化的原因
- 每个类只负责一项职责,降低代码复杂度
- 例:User类只负责用户属性,UserService负责用户业务逻辑
2. 开闭原则(Open-Closed Principle, OCP):
- 对扩展开放,对修改关闭
- 通过抽象和多态实现功能扩展而不修改现有代码
- 例:策略模式中新增支付方式无需修改原有支付逻辑
3. 里氏替换原则(Liskov Substitution Principle, LSP):
- 子类对象能够替换父类对象而不影响程序正确性
- 子类必须能够完全替代父类,保持行为一致性
- 例:Rectangle和Square的继承关系设计
4. 接口隔离原则(Interface Segregation Principle, ISP):
- 客户端不应该依赖它不需要的接口
- 使用多个专门的接口比使用单一的总接口要好
- 例:将大接口拆分成多个小而专一的接口
5. 依赖倒置原则(Dependency Inversion Principle, DIP):
- 高层模块不应该依赖低层模块,两者都应该依赖抽象
- 抽象不应该依赖细节,细节应该依赖抽象
- 例:控制器依赖Service接口而不是具体实现类
其他重要原则:
- 合成复用原则:优先使用对象组合而非类继承
- 迪米特法则:一个对象应该对其他对象保持最少的了解
这些原则指导我们设计出松耦合、高内聚、可扩展的代码。"
在广告归因和回传系统中,我主要用到了以下几类设计模式:
- 工厂模式(Factory Pattern):负责不同媒体渠道回传服务的实例创建,具体要走什么回传,是扣量还是高质量等等,是在入参就可以决定的;
- 策略模式(Strategy Pattern):负责不同媒体回传逻辑、验签算法和请求格式;
- 模板方法模式(Template Method):抽象出回传的公共流程;
- 责任链模式(Chain of Responsibility):对每个回传请求按规则依次校验;
- 单例模式(Singleton Pattern):保证配置类、客户端池等资源唯一;
"开闭原则是面向对象设计的核心原则,对扩展开放,对修改关闭:
核心思想:
- 当需求变化时,应该通过扩展现有代码来实现变化
- 而不是修改现有的代码
- 通过抽象化来实现开闭原则
实现方式:
- 使用抽象类或接口来定义规范
- 具体实现通过继承或实现来扩展功能
- 依赖注入和多态来实现灵活的扩展
代码示例:
// 抽象支付接口
interface PaymentStrategy {
void pay(double amount);
}
// 具体支付实现
class AlipayPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("支付宝支付: " + amount);
}
}
class WechatPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("微信支付: " + amount);
}
}
// 支付上下文
class PaymentContext {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(double amount) {
strategy.pay(amount);
}
}新增银行卡支付时:
- 只需新增BankCardPayment类实现PaymentStrategy
- 无需修改PaymentContext或其他现有代码
- 完美体现了对扩展开放,对修改关闭
开闭原则是设计模式的基石,策略模式、工厂模式等都体现了这一原则。"
核心思想:封装对象的创建过程,使系统独立于如何创建、组合和表示对象。
"JDK中大量使用了设计模式,这些模式的应用体现了优秀的软件设计:
创建型模式:
- 单例模式:Runtime类、Calendar类确保全局唯一实例
- 工厂模式:Boolean.valueOf()、Integer.valueOf()等工厂方法
- 建造者模式:StringBuilder、StringBuffer的链式调用
结构型模式:
- 装饰器模式:Java IO流体系(BufferedReader装饰FileReader)
- 适配器模式:Arrays.asList()将数组适配为List
- 代理模式:动态代理机制(java.lang.reflect.Proxy)
行为型模式:
- 观察者模式:Swing/AWT事件机制、PropertyChangeSupport
- 策略模式:Collections.sort()的Comparator参数
- 模板方法模式:AbstractList、AbstractMap等抽象类
- 迭代器模式:Collection接口的iterator()方法
这些模式的应用让JDK的API设计更加灵活和可扩展。"
"单例模式确保一个类只有一个实例,并提供全局访问点:
单例模式定义:
- 保证一个类仅有一个实例,并提供一个访问它的全局访问点
- 控制实例数量,避免资源浪费和状态不一致
- 延迟初始化,需要时才创建实例
应用场景:
- 系统资源:数据库连接池、线程池、缓存管理器
- 配置对象:应用程序配置、系统设置管理
- 工具类:日志记录器、打印机管理器
- 硬件接口:设备驱动程序(如打印机驱动)
优缺点分析:
- 优点:节约内存、避免重复创建、全局访问点
- 缺点:违反单一职责、不利于测试、可能成为性能瓶颈"
💻 单例模式的7种实现方式:
推荐程度排序:枚举 > 静态内部类 > 双重校验锁 > 饿汉式 > 懒汉式
1. 懒汉式(线程不安全):
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton(); // 多线程下可能创建多个实例
}
return instance;
}
}2. 懒汉式(线程安全,同步效率低):
public class SynchronizedLazySingleton {
private static SynchronizedLazySingleton instance;
private SynchronizedLazySingleton() {}
public static synchronized SynchronizedLazySingleton getInstance() {
if (instance == null) {
instance = new SynchronizedLazySingleton();
}
return instance;
}
}3. 饿汉式(推荐):
public class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return INSTANCE;
}
}4. 饿汉式变种(静态代码块):
public class StaticBlockSingleton {
private static final StaticBlockSingleton INSTANCE;
static {
INSTANCE = new StaticBlockSingleton();
}
private StaticBlockSingleton() {}
public static StaticBlockSingleton getInstance() {
return INSTANCE;
}
}5. 静态内部类(强烈推荐):
public class InnerClassSingleton {
private InnerClassSingleton() {}
// 静态内部类,JVM保证线程安全,懒加载
private static class SingletonHolder {
private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE; // 触发内部类加载
}
}6. 枚举(最佳实现):
public enum EnumSingleton {
INSTANCE;
// 可以添加其他方法
public void doSomething() {
System.out.println("EnumSingleton doing something...");
}
public void anotherMethod() {
// 业务逻辑
}
}
// 使用方式
// EnumSingleton.INSTANCE.doSomething();7. 双重校验锁(DCL,推荐):
public class DoubleCheckedLockingSingleton {
// volatile防止指令重排序
private volatile static DoubleCheckedLockingSingleton instance;
private DoubleCheckedLockingSingleton() {}
public static DoubleCheckedLockingSingleton getInstance() {
// 第一次检查,避免不必要的同步
if (instance == null) {
synchronized (DoubleCheckedLockingSingleton.class) {
// 第二次检查,确保线程安全
if (instance == null) {
instance = new DoubleCheckedLockingSingleton();
}
}
}
return instance;
}
}💡 各种实现方式对比:
| 实现方式 | 线程安全 | 懒加载 | 性能 | 推荐度 | 特点 |
|---|---|---|---|---|---|
| 懒汉式 | ❌ | ✅ | 高 | ⭐ | 最简单但不安全 |
| 同步懒汉式 | ✅ | ✅ | 低 | ⭐⭐ | 安全但效率低 |
| 饿汉式 | ✅ | ❌ | 高 | ⭐⭐⭐ | 简单安全,可能浪费内存 |
| 静态内部类 | ✅ | ✅ | 高 | ⭐⭐⭐⭐⭐ | 完美解决方案 |
| 枚举 | ✅ | ❌ | 高 | ⭐⭐⭐⭐⭐ | 最简洁,防反射和序列化 |
| 双重校验锁 | ✅ | ✅ | 高 | ⭐⭐⭐⭐ | 复杂但高效 |
"单例模式的两大威胁是反射和序列化,需要采取防护措施:
反射攻击演示:
// 正常获取单例
Singleton instance1 = Singleton.getInstance();
// 反射破坏单例
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton instance2 = constructor.newInstance();
System.out.println(instance1 == instance2); // false,单例被破坏防御措施:
方案1:构造函数防护
public class AntiReflectionSingleton {
private static volatile AntiReflectionSingleton instance;
private static boolean initialized = false;
private AntiReflectionSingleton() {
synchronized (AntiReflectionSingleton.class) {
if (initialized) {
throw new RuntimeException("单例已存在,禁止反射创建");
}
initialized = true;
}
}
}方案2:枚举天然防御
public enum EnumSingleton {
INSTANCE;
// JVM层面防止反射调用枚举构造器
}序列化攻击演示:
// 序列化破坏单例
Singleton instance1 = Singleton.getInstance();
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton.ser"));
oos.writeObject(instance1);
// 反序列化创建新实例
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton.ser"));
Singleton instance2 = (Singleton) ois.readObject();
System.out.println(instance1 == instance2); // false,单例被破坏防御措施:实现readResolve方法
public class SerializationSafeSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private static volatile SerializationSafeSingleton instance;
private SerializationSafeSingleton() {}
public static SerializationSafeSingleton getInstance() {
if (instance == null) {
synchronized (SerializationSafeSingleton.class) {
if (instance == null) {
instance = new SerializationSafeSingleton();
}
}
}
return instance;
}
// 关键:反序列化时返回已有实例
private Object readResolve() {
return getInstance();
}
}终极解决方案:枚举单例
public enum UltimateSingleton {
INSTANCE;
public void doSomething() {
System.out.println("枚举单例天然防止反射和序列化攻击");
}
}枚举是实现单例的最佳方式:线程安全、懒加载、防反射、防序列化。"
💡 单例模式最佳实践:
- 优先选择枚举:代码简洁,天然安全
- 次选静态内部类:懒加载+高性能
- 避免反射攻击:构造器中添加检查
- 防序列化破坏:实现readResolve方法
- 考虑实际需求:是否真的需要全局唯一
"工厂模式是创建型设计模式的核心,主要解决对象创建的复杂性:
工厂模式的好处:
- 解耦创建和使用:客户端不需要知道具体对象的创建细节
- 封装变化:新增产品类型时,只需扩展工厂,无需修改客户端
- 统一管理:集中控制对象的创建逻辑,便于维护
- 提高复用性:相同的创建逻辑可以被多处复用
应用场景:
- 数据库连接:根据配置创建不同数据库的连接
- 日志框架:根据级别创建不同的日志处理器
- UI组件:根据操作系统创建对应的界面组件
- 支付系统:根据支付方式创建对应的支付处理器
JDK中的应用:
Boolean.valueOf(),Integer.valueOf()等工厂方法Calendar.getInstance()获取日历实例NumberFormat.getInstance()创建格式化器
工厂模式让系统更加灵活,符合开闭原则。"
"工厂模式有三种类型,复杂程度和应用场景各不相同:
简单工厂(Simple Factory):
- 一个工厂类根据参数创建不同产品
- 违反开闭原则,新增产品需要修改工厂类
- 适用于产品种类较少且稳定的场景
工厂方法(Factory Method):
- 每种产品对应一个具体工厂
- 符合开闭原则,新增产品只需新增工厂
- 适用于产品族较少但产品种类可能增加的场景
抽象工厂(Abstract Factory):
- 创建一系列相关的产品族
- 适用于有多个产品族,每个产品族有多个产品的场景
- 如:不同风格的UI组件(Windows风格、Mac风格)
选择建议:简单工厂适合小项目,工厂方法适合中型项目,抽象工厂适合复杂的产品体系。"
💻 代码示例对比:
简单工厂示例:
// 产品接口
interface Product {
void use();
}
// 具体产品
class ProductA implements Product {
public void use() { System.out.println("使用产品A"); }
}
class ProductB implements Product {
public void use() { System.out.println("使用产品B"); }
}
// 简单工厂
class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A": return new ProductA();
case "B": return new ProductB();
default: throw new IllegalArgumentException("未知产品类型");
}
}
}工厂方法示例:
// 抽象工厂
interface Factory {
Product createProduct();
}
// 具体工厂
class ProductAFactory implements Factory {
public Product createProduct() {
return new ProductA();
}
}
class ProductBFactory implements Factory {
public Product createProduct() {
return new ProductB();
}
}抽象工厂示例:
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂族
class WindowsFactory implements AbstractFactory {
public ProductA createProductA() { return new WindowsProductA(); }
public ProductB createProductB() { return new WindowsProductB(); }
}
class MacFactory implements AbstractFactory {
public ProductA createProductA() { return new MacProductA(); }
public ProductB createProductB() { return new MacProductB(); }
}核心思想:关注类和对象的组合,通过组合获得更强大的功能,解决如何将类或对象按某种布局组成更大的结构。
代理模式(Proxy Pattern) 是一种结构型设计模式,用于为目标对象提供一个代理对象,通过代理对象来控制对目标对象的访问。代理对象在客户端与目标对象之间起到中介的作用,可以对访问进行控制、增强或简化。
- 静态代理:在编译阶段,代理类已经被定义好。
- 动态代理
- 在运行时动态生成代理类,而不需要手动编写代理类代码。
- 动态代理通常基于 Java 反射 实现,最常用的两种动态代理技术是 JDK 动态代理 和 CGLIB 动态代理。
| 对比维度 | 静态代理 | 动态代理 |
|---|---|---|
| 代理类生成时间 | 代理类在 编译时 已经生成,由开发者手动编写代理类。 | 代理类在 运行时 动态生成,不需要手动编写代理类。 |
| 实现方式 | 手动创建一个实现目标类接口的代理类,通过代理类调用目标对象的方法。 | 使用反射机制(如 Proxy 或 CGLIB)在运行时生成代理类。 |
| 目标类要求 | 目标类必须实现接口。 | JDK 动态代理:目标类必须实现接口。 CGLIB 动态代理:目标类无需实现接口,但不能是 final 类。 |
| 灵活性 | 灵活性较低,每个目标类都需要一个对应的代理类,代码量较大。 | 灵活性高,一个代理类可以代理多个目标对象。 |
| 性能 | 性能略优于动态代理(因为无需反射机制)。 | 性能略低于静态代理(因依赖反射)。 但在 CGLIB 中,性能接近静态代理。 |
| 实现难度 | 实现简单,但代码量较多,维护麻烦。 | 实现复杂,但代码量少,易于维护。 |
| 扩展性 | 扩展性差,新增目标类时需要新增代理类。 | 扩展性好,新增目标类时无需新增代理类,只需修改动态代理逻辑。 |
| 对比维度 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 实现方式 | 基于 Java 反射机制 和接口实现,使用 java.lang.reflect.Proxy。 |
基于 字节码增强 技术,使用第三方库(如 CGLIB 或 ASM)。 |
| 代理对象要求 | 目标类必须实现 接口。 | 目标类 无需实现接口,可以代理普通类。 |
| 继承限制 | 无需继承,直接代理接口即可。 | 目标类不能是 final 类,代理的方法也不能是 final 方法(因为无法被重写)。 |
| 性能 | 性能略低(因反射调用方法效率较低)。 | 性能较高(直接生成字节码,调用方法接近普通方法调用)。 |
| 代码依赖 | 无需依赖外部库,属于 JDK 原生功能。 | 需要引入 CGLIB 或其他字节码增强库(如 ASM)。 |
| 应用场景 | 目标类实现了接口时适用。 | 目标类未实现接口或需要对具体类进行代理时适用。 |
| 实现复杂度 | 简单,使用 Proxy 类和 InvocationHandler 接口生成代理对象。 |
复杂,需要处理字节码增强逻辑(通常通过工具库封装)。 |
| Spring AOP 支持 | 默认情况下,Spring AOP 使用 JDK 动态代理(如果目标类实现了接口)。 | Spring 会使用 CGLIB 动态代理(如果目标类未实现接口)。 |
"装饰器模式动态地给对象添加新功能,是对象层次的扩展:
装饰器模式特点:
- 对象组合优于继承:通过包装而非继承扩展功能
- 运行时增强:可以动态添加或撤销装饰
- 层层嵌套:多个装饰器可以层层包装
- 透明性:装饰后的对象与原对象有相同接口
Java IO流的装饰器设计:
// 基础组件
InputStream fileStream = new FileInputStream("file.txt");
// 装饰器层层包装
InputStream bufferedStream = new BufferedInputStream(fileStream); // 添加缓冲功能
InputStream dataStream = new DataInputStream(bufferedStream); // 添加数据类型读取
// 等价于:new DataInputStream(new BufferedInputStream(new FileInputStream("file.txt")));作用层次:装饰器模式作用于对象层次,而非类层次
- 不改变原有类的结构
- 通过对象组合实现功能扩展
- 比继承更加灵活,避免类爆炸
装饰器模式让功能扩展变得优雅而灵活。"
核心思想:关注对象之间的通信,负责对象间的有效沟通和职责委派,解决类或对象之间的交互问题。
观察者模式是基于对象的状态变化和观察者的通讯,以便他们作出相应的操作。简单的例子就是一个天气系统,当天气变化时必须在展示给公众的视图中进行反映。这个视图对象是一个主体,而不同的视图是观察者。
"装饰器模式动态地给对象添加新功能,是对象层次的扩展:
装饰器模式特点:
- 对象组合优于继承:通过包装而非继承扩展功能
- 运行时增强:可以动态添加或撤销装饰
- 层层嵌套:多个装饰器可以层层包装
- 透明性:装饰后的对象与原对象有相同接口
Java IO流的装饰器设计:
// 基础组件
InputStream fileStream = new FileInputStream("file.txt");
// 装饰器层层包装
InputStream bufferedStream = new BufferedInputStream(fileStream); // 添加缓冲功能
InputStream dataStream = new DataInputStream(bufferedStream); // 添加数据类型读取
// 等价于:new DataInputStream(new BufferedInputStream(new FileInputStream("file.txt")));作用层次:装饰器模式作用于对象层次,而非类层次
- 不改变原有类的结构
- 通过对象组合实现功能扩展
- 比继承更加灵活,避免类爆炸
装饰器模式让功能扩展变得优雅而灵活。"
核心思想:设计模式在实际项目中的应用案例和最佳实践,包括Spring框架、项目实战经验和开发建议。
"Spring框架大量运用设计模式,体现了优秀的架构设计:
创建型模式:
- 单例模式:Spring Bean默认为单例,确保全局唯一性
- 工厂模式:BeanFactory是工厂的抽象,ApplicationContext是具体工厂
- 建造者模式:BeanDefinitionBuilder用于构建复杂的Bean定义
- 原型模式:prototype作用域的Bean通过克隆创建
结构型模式:
- 代理模式:AOP的核心实现,JDK动态代理和CGLIB代理
- 装饰器模式:BeanWrapper装饰Bean,添加属性访问能力
- 适配器模式:HandlerAdapter适配不同类型的Controller
- 外观模式:ApplicationContext提供统一的访问接口
行为型模式:
- 模板方法模式:JdbcTemplate、RestTemplate等模板类
- 策略模式:Bean实例化策略选择(单例vs原型)
- 观察者模式:ApplicationEvent和ApplicationListener
- 责任链模式:Filter链、Interceptor链的处理方式
Spring的设计模式应用体现了框架的灵活性和可扩展性。"
"在实际项目开发中,我经常使用以下设计模式:
业务场景应用:
- 策略模式:支付方式选择(支付宝、微信、银行卡支付策略)
- 工厂模式:消息处理器创建(短信、邮件、推送消息工厂)
- 模板方法模式:业务流程框架(订单处理、审批流程模板)
- 责任链模式:权限验证链、参数校验链、业务处理链
- 观察者模式:系统事件通知(用户注册后发送邮件、积分等)
系统设计应用:
- 单例模式:配置管理器、缓存管理器、日志记录器
- 建造者模式:复杂查询条件构建、报表生成器
- 适配器模式:第三方服务接口适配、遗留系统集成
- 代理模式:AOP切面编程、性能监控、事务管理
- 外观模式:微服务聚合接口、复杂子系统封装
设计模式让代码更易维护、扩展和理解,是高质量代码的基石。”
"GoF 23种设计模式按用途分为三大类,每类解决不同层面的问题:
⭐ 常用设计模式重点掌握:
创建型模式(5种):
- ⭐⭐⭐ 单例模式:确保类只有一个实例,全局访问点
- ⭐⭐⭐ 工厂方法:定义创建对象接口,子类决定实例化类型
- ⭐⭐ 建造者模式:分步构造复杂对象,相同过程创建不同表示
- ⭐⭐ 原型模式:通过克隆创建对象,避免复杂初始化
- ⭐ 抽象工厂:创建相关对象族,无需指定具体类
结构型模式(7种):
- ⭐⭐⭐ 代理模式:为对象提供代理,控制访问并增强功能
- ⭐⭐⭐ 装饰模式:动态添加对象功能,灵活扩展行为
- ⭐⭐ 适配器模式:转换接口,让不兼容类协同工作
- ⭐⭐ 外观模式:提供统一接口,简化子系统访问
- ⭐ 组合模式:树形结构,统一处理单个和组合对象
- 桥接模式:分离抽象和实现,两者可独立变化
- 享元模式:共享对象减少内存使用
行为型模式(11种):
- ⭐⭐⭐ 观察者模式:对象间一对多依赖,状态变化通知所有观察者
- ⭐⭐⭐ 策略模式:定义算法族,封装并可相互替换
- ⭐⭐ 模板方法:定义算法骨架,子类实现具体步骤
- ⭐⭐ 责任链模式:请求沿链传递,直到有对象处理
- ⭐ 状态模式:对象内部状态改变时改变行为
- 命令模式:请求封装为对象,支持撤销和重做
- 访问者模式:分离算法与数据结构,便于添加新操作
- 中介者模式:集中处理对象间复杂交互
- 备忘录模式:保存对象状态,支持恢复
- 解释器模式:为语言定义文法表示和解释器
- 迭代器模式:顺序访问聚合对象元素
设计模式不是银弹,但是优秀代码的重要组成部分。选择合适的模式,避免过度设计,在实际应用中不断练习和总结,才能真正掌握设计模式的精髓。记住:设计模式是为了解决问题而存在的,不要为了使用模式而使用模式。
- 理解问题背景:每个模式都是为了解决特定问题而产生的
- 掌握核心结构:理解模式的组成部分和它们之间的关系
- 练习代码实现:通过编写代码来加深理解
- 结合实际项目:在真实项目中寻找应用场景
- 避免过度设计:不要为了使用模式而使用模式
- 模式万能论:认为设计模式可以解决所有问题
- 过度抽象:为简单问题引入复杂的模式
- 死记硬背:只记住结构而不理解应用场景
- 盲目套用:不考虑具体情况强行使用某种模式
- 重点掌握单例、工厂、代理、观察者、策略等常用模式
- 理解设计原则,特别是开闭原则和单一职责原则
- 能够结合Spring框架说明模式的实际应用
- 准备1-2个项目中实际使用设计模式的案例
最终目标:让设计模式成为你编写高质量代码的有力工具!
