Java 常见设计模式(易理解版,含代码示例)
设计模式是解决软件开发中通用问题的标准化解决方案,核心是解耦、复用、提高代码可维护性,以下选取 Java 开发中最常用、最实用的 8 种设计模式,按「创建型 / 结构型 / 行为型」分类,每个模式均说明核心思想 + 适用场景 + 极简代码示例,示例无冗余逻辑,重点体现设计思路。
一、创建型模式(管理对象的创建过程,降低创建与使用的耦合)
1. 单例模式(Singleton)
核心思想
保证一个类在整个应用中只有一个实例,并提供全局唯一的访问入口(避免频繁创建销毁对象,节省资源)。
适用场景
工具类、数据库连接池、配置文件管理器、日志工厂等(需全局统一状态的场景)。
经典实现(懒汉式 - 双重检查锁,线程安全 + 懒加载,实际开发首选)
java 运行
// 单例类:数据库连接池示例 public class DbPool { // 1. 私有静态实例,volatile防止指令重排(保证实例初始化完成后再被访问) private static volatile DbPool instance; // 2. 私有构造方法,禁止外部new创建实例 private DbPool() { // 模拟初始化连接池 System.out.println("初始化数据库连接池,仅执行一次"); } // 3. 公共静态方法,全局访问入口 public static DbPool getInstance() { // 第一次检查:未创建时才进入同步代码块(提高效率) if (instance == null) { // 同步锁:保证线程安全 synchronized (DbPool.class) { // 第二次检查:防止多线程同时进入后重复创建 if (instance == null) { instance = new DbPool(); } } } return instance; } // 业务方法:模拟获取连接 public void getConnection() { System.out.println("获取数据库连接"); } } // 测试类 public class SingletonTest { public static void main(String[] args) { // 两次获取的是同一个实例 DbPool pool1 = DbPool.getInstance(); DbPool pool2 = DbPool.getInstance(); System.out.println(pool1 == pool2); // 输出:true(地址相同,单例生效) pool1.getConnection(); } }
关键要点
- 私有构造器 + 静态实例 + 静态访问方法是单例的核心;
- 双重检查锁(DCL)兼顾「懒加载」(用到时才创建)和「线程安全」,是生产环境最常用的单例实现。
2. 工厂方法模式(Factory Method)
核心思想
定义创建对象的接口,让子类决定具体创建哪个类的实例(将对象创建延迟到子类,解耦创建逻辑与业务逻辑)。
适用场景
需要根据不同条件创建不同对象,且对象类型有共同父类 / 接口(如日志框架:按配置创建文件日志 / 控制台日志实例)。
代码示例(日志工厂场景)
java
运行
1 // 步骤1:定义产品接口(所有日志对象的共同规范) 2 public interface Logger { 3 void log(String message); 4 } 5 6 // 步骤2:实现具体产品类 7 // 控制台日志 8 public class ConsoleLogger implements Logger { 9 @Override 10 public void log(String message) { 11 System.out.println("控制台日志:" + message); 12 } 13 } 14 // 文件日志 15 public class FileLogger implements Logger { 16 @Override 17 public void log(String message) { 18 System.out.println("文件日志:" + message); 19 } 20 } 21 22 // 步骤3:定义工厂接口(创建产品的抽象方法) 23 public interface LoggerFactory { 24 Logger createLogger(); 25 } 26 27 // 步骤4:实现具体工厂类(子类决定创建哪个产品) 28 // 控制台日志工厂 29 public class ConsoleLoggerFactory implements LoggerFactory { 30 @Override 31 public Logger createLogger() { 32 return new ConsoleLogger(); 33 } 34 } 35 // 文件日志工厂 36 public class FileLoggerFactory implements LoggerFactory { 37 @Override 38 public Logger createLogger() { 39 return new FileLogger(); 40 } 41 } 42 43 // 测试类 44 public class FactoryMethodTest { 45 public static void main(String[] args) { 46 // 创建控制台日志:工厂+产品一一对应,无需直接new具体产品 47 LoggerFactory factory1 = new ConsoleLoggerFactory(); 48 Logger logger1 = factory1.createLogger(); 49 logger1.log("用户登录成功"); // 输出:控制台日志:用户登录成功 50 51 // 创建文件日志:新增日志类型只需加「产品类+工厂类」,无需修改原有代码 52 LoggerFactory factory2 = new FileLoggerFactory(); 53 Logger logger2 = factory2.createLogger(); 54 logger2.log("数据更新失败"); // 输出:文件日志:数据更新失败 55 } 56 }
关键要点
- 核心是「工厂接口 + 产品接口」,符合「开闭原则」(新增功能不修改原有代码);
- 区别于简单工厂(一个工厂创建所有产品),工厂方法更灵活,适合产品类型较多的场景。
二、结构型模式(优化类 / 对象的组合方式,实现更灵活的功能扩展)
1. 装饰器模式(Decorator)
核心思想
动态地给对象添加额外功能,无需继承原类(继承是静态扩展,装饰器是动态扩展,更灵活)。
适用场景
需要为对象添加多个可选功能,且功能可自由组合(如 IO 流、日志增强、奶茶加配料)。
代码示例(奶茶加配料场景,贴近生活,易理解)
java
运行
1 2 // 步骤1:定义抽象组件(被装饰的核心对象) 3 public abstract class MilkTea { 4 // 奶茶描述 5 public abstract String getDescription(); 6 // 奶茶价格 7 public abstract double getPrice(); 8 } 9 10 // 步骤2:实现具体组件(基础奶茶,无配料) 11 // 原味奶茶(基础款) 12 public class OriginalMilkTea extends MilkTea { 13 @Override 14 public String getDescription() { 15 return "原味奶茶"; 16 } 17 @Override 18 public double getPrice() { 19 return 10.0; // 基础价10元 20 } 21 } 22 23 // 步骤3:定义装饰器抽象类(继承组件,持有组件引用,核心) 24 public abstract class MilkTeaDecorator extends MilkTea { 25 protected MilkTea milkTea; // 持有被装饰的奶茶对象 26 // 构造器传入被装饰对象 27 public MilkTeaDecorator(MilkTea milkTea) { 28 this.milkTea = milkTea; 29 } 30 } 31 32 // 步骤4:实现具体装饰器(具体配料,动态添加功能) 33 // 珍珠配料(装饰器1) 34 public class PearlDecorator extends MilkTeaDecorator { 35 public PearlDecorator(MilkTea milkTea) { 36 super(milkTea); 37 } 38 @Override 39 public String getDescription() { 40 // 原有描述 + 新增配料 41 return milkTea.getDescription() + " + 珍珠"; 42 } 43 @Override 44 public double getPrice() { 45 // 原有价格 + 配料价格 46 return milkTea.getPrice() + 2.0; // 珍珠2元 47 } 48 } 49 // 椰果配料(装饰器2) 50 public class CoconutDecorator extends MilkTeaDecorator { 51 public CoconutDecorator(MilkTea milkTea) { 52 super(milkTea); 53 } 54 @Override 55 public String getDescription() { 56 return milkTea.getDescription() + " + 椰果"; 57 } 58 @Override 59 public double getPrice() { 60 return milkTea.getPrice() + 1.5; // 椰果1.5元 61 } 62 } 63 64 // 测试类:自由组合配料(动态扩展) 65 public class DecoratorTest { 66 public static void main(String[] args) { 67 // 基础款:原味奶茶 68 MilkTea milkTea = new OriginalMilkTea(); 69 System.out.println(milkTea.getDescription() + " | 价格:" + milkTea.getPrice()); // 原味奶茶 | 10.0 70 71 // 动态加珍珠:原味奶茶 + 珍珠 72 milkTea = new PearlDecorator(milkTea); 73 System.out.println(milkTea.getDescription() + " | 价格:" + milkTea.getPrice()); // 原味奶茶+珍珠 | 12.0 74 75 // 再动态加椰果:原味奶茶 + 珍珠 + 椰果 76 milkTea = new CoconutDecorator(milkTea); 77 System.out.println(milkTea.getDescription() + " | 价格:" + milkTea.getPrice()); // 原味奶茶+珍珠+椰果 | 13.5 78 79 // 直接创建:原味奶茶 + 椰果(单独加) 80 MilkTea milkTea2 = new CoconutDecorator(new OriginalMilkTea()); 81 System.out.println(milkTea2.getDescription() + " | 价格:" + milkTea2.getPrice()); // 原味奶茶+椰果 | 11.5 82 } 83 }
关键要点
- 装饰器与被装饰对象实现同一接口 / 继承同一父类,保证使用方式一致;
- 装饰器持有被装饰对象的引用,通过「包装」实现功能叠加,支持无限层装饰(如再加布丁、仙草)。
2. 代理模式(Proxy)
核心思想
为一个对象提供替身,通过替身控制对原对象的访问(可在访问原对象前后添加额外逻辑,如权限校验、日志、缓存)。
适用场景
远程调用(RPC)、权限控制、日志记录、懒加载(如 MyBatis 的 Mapper 代理、Spring AOP 的底层实现)。
代码示例(静态代理,权限校验场景,易懂)
java
运行
1 // 步骤1:定义业务接口(原对象和代理对象共同实现) 2 public interface UserService { 3 // 用户查询功能 4 void queryUser(String userId); 5 } 6 7 // 步骤2:实现原对象(真实业务逻辑,核心功能) 8 public class UserServiceImpl implements UserService { 9 @Override 10 public void queryUser(String userId) { 11 // 真实业务:查询用户信息 12 System.out.println("查询用户ID:" + userId + " 的信息,执行数据库操作"); 13 } 14 } 15 16 // 步骤3:实现代理对象(替身,控制对原对象的访问) 17 public class UserServiceProxy implements UserService { 18 // 持有真实对象的引用 19 private UserService userService; 20 // 构造器传入真实对象 21 public UserServiceProxy(UserService userService) { 22 this.userService = userService; 23 } 24 @Override 25 public void queryUser(String userId) { 26 // 访问原对象前:添加额外逻辑(权限校验) 27 if (checkPermission()) { 28 System.out.println("权限校验通过,允许查询用户信息"); 29 // 调用真实对象的核心方法 30 userService.queryUser(userId); 31 // 访问原对象后:添加额外逻辑(日志记录) 32 System.out.println("查询用户信息完成,记录操作日志"); 33 } else { 34 System.out.println("权限校验失败,禁止查询用户信息"); 35 } 36 } 37 // 模拟权限校验逻辑 38 private boolean checkPermission() { 39 // 此处简化:默认管理员ID为"admin"可访问 40 return "admin".equals(Thread.currentThread().getName()); 41 } 42 } 43 44 // 测试类 45 public class ProxyTest { 46 public static void main(String[] args) { 47 // 真实业务对象 48 UserService realService = new UserServiceImpl(); 49 // 代理对象包装真实对象 50 UserService proxyService = new UserServiceProxy(realService); 51 52 // 1. 以管理员身份访问(线程名设为admin) 53 Thread thread1 = new Thread(() -> proxyService.queryUser("U001"), "admin"); 54 thread1.start(); // 输出:权限校验通过 → 查询用户 → 记录日志 55 56 System.out.println("-----分割线-----"); 57 58 // 2. 以普通用户身份访问(线程名设为user) 59 Thread thread2 = new Thread(() -> proxyService.queryUser("U001"), "user"); 60 thread2.start(); // 输出:权限校验失败,禁止查询 61 } 62 }
关键要点
- 静态代理:原对象和代理对象编译期确定,一一对应(适合简单场景);
- 动态代理(如 JDK 动态代理、CGLIB):运行期动态生成代理对象,无需手动编写代理类(Spring AOP 核心,适合批量代理场景);
- 核心:代理对象不做核心业务,只做「增强 / 控制」,真实业务由原对象执行。
三、行为型模式(规范对象之间的交互方式,提高交互的灵活性和可复用性)
1. 观察者模式(Observer)
核心思想
定义「一对多」的依赖关系,当被观察者(主题)的状态发生变化时,会自动通知所有依赖它的观察者,并更新观察者状态(发布 - 订阅模式的底层实现)。
适用场景
事件监听、消息通知、数据更新同步(如 GUI 界面刷新、微信公众号推送、订单状态变更通知)。
代码示例(微信公众号推送场景,贴近实际)
java
运行
1 import java.util.ArrayList; 2 import java.util.List; 3 4 // 步骤1:定义被观察者(主题)接口 5 public interface Subject { 6 // 注册观察者(关注公众号) 7 void registerObserver(Observer observer); 8 // 移除观察者(取消关注) 9 void removeObserver(Observer observer); 10 // 通知所有观察者(推送消息) 11 void notifyObservers(String message); 12 } 13 14 // 步骤2:定义观察者接口(订阅者) 15 public interface Observer { 16 // 接收通知并更新(接收公众号消息) 17 void update(String message); 18 } 19 20 // 步骤3:实现具体被观察者(微信公众号) 21 public class WeChatOfficialAccount implements Subject { 22 // 存储所有观察者(粉丝) 23 private List<Observer> observerList = new ArrayList<>(); 24 // 公众号名称 25 private String accountName; 26 27 public WeChatOfficialAccount(String accountName) { 28 this.accountName = accountName; 29 } 30 31 @Override 32 public void registerObserver(Observer observer) { 33 observerList.add(observer); 34 System.out.println(observer + " 关注了 " + accountName); 35 } 36 37 @Override 38 public void removeObserver(Observer observer) { 39 observerList.remove(observer); 40 System.out.println(observer + " 取消关注了 " + accountName); 41 } 42 43 @Override 44 public void notifyObservers(String message) { 45 System.out.println("\n" + accountName + " 推送新消息:" + message); 46 // 遍历所有观察者,通知更新 47 for (Observer observer : observerList) { 48 observer.update(message); 49 } 50 } 51 // 公众号发消息(触发通知) 52 public void publishMessage(String message) { 53 notifyObservers(message); 54 } 55 } 56 57 // 步骤4:实现具体观察者(微信用户) 58 public class WeChatUser implements Observer { 59 // 用户名 60 private String userName; 61 62 public WeChatUser(String userName) { 63 this.userName = userName; 64 } 65 66 @Override 67 public void update(String message) { 68 // 接收消息后的处理(此处简化为打印) 69 System.out.println(userName + " 收到消息:" + message); 70 } 71 72 @Override 73 public String toString() { 74 return userName; 75 } 76 } 77 78 // 测试类 79 public class ObserverTest { 80 public static void main(String[] args) { 81 // 创建被观察者:Java编程公众号 82 Subject javaAccount = new WeChatOfficialAccount("Java编程"); 83 84 // 创建观察者:3个微信用户 85 Observer user1 = new WeChatUser("张三"); 86 Observer user2 = new WeChatUser("李四"); 87 Observer user3 = new WeChatUser("王五"); 88 89 // 用户关注公众号(注册观察者) 90 javaAccount.registerObserver(user1); 91 javaAccount.registerObserver(user2); 92 javaAccount.registerObserver(user3); 93 94 // 公众号推送第一条消息 95 javaAccount.publishMessage("Java设计模式超详细讲解!"); 96 97 // 李四取消关注(移除观察者) 98 javaAccount.removeObserver(user2); 99 100 // 公众号推送第二条消息(李四不再接收) 101 javaAccount.publishMessage("Spring Boot最新教程上线!"); 102 } 103 }
输出结果
plaintext
张三 关注了 Java编程
李四 关注了 Java编程
王五 关注了 Java编程
Java编程 推送新消息:Java设计模式超详细讲解!
张三 收到消息:Java设计模式超详细讲解!
李四 收到消息:Java设计模式超详细讲解!
王五 收到消息:Java设计模式超详细讲解!
李四 取消关注了 Java编程
Java编程 推送新消息:Spring Boot最新教程上线!
张三 收到消息:Spring Boot最新教程上线!
王五 收到消息:Spring Boot最新教程上线!
关键要点
- 被观察者维护观察者列表,提供「注册 / 移除 / 通知」方法;
- 观察者实现「更新」方法,接收被观察者的状态变化;
- 核心:被观察者与观察者解耦,新增观察者只需实现 Observer 接口,无需修改被观察者代码(开闭原则)。
2. 策略模式(Strategy)
核心思想
定义一系列算法 / 策略,将每个算法封装成独立的类,使它们可以互相替换(算法与使用算法的客户端解耦,方便切换和扩展)。
适用场景
需要根据不同场景选择不同算法,且算法易变(如排序算法、支付方式、优惠活动计算)。
代码示例(支付方式选择场景,实际开发常用)
java
运行
1 2 3 // 步骤1:定义策略接口(所有支付算法的共同规范) 4 public interface PayStrategy { 5 // 支付方法:返回支付结果 6 String pay(double amount); 7 } 8 9 // 步骤2:实现具体策略类(不同的支付方式,封装独立算法) 10 // 支付宝支付 11 public class AlipayStrategy implements PayStrategy { 12 @Override 13 public String pay(double amount) { 14 return "使用支付宝支付 " + amount + " 元,支付成功!"; 15 } 16 } 17 // 微信支付 18 public class WeChatPayStrategy implements PayStrategy { 19 @Override 20 public String pay(double amount) { 21 return "使用微信支付 " + amount + " 元,支付成功!"; 22 } 23 } 24 // 银行卡支付 25 public class BankCardPayStrategy implements PayStrategy { 26 @Override 27 public String pay(double amount) { 28 return "使用银行卡支付 " + amount + " 元,支付成功!"; 29 } 30 } 31 32 // 步骤3:定义上下文类(客户端,使用策略的对象,持有策略引用) 33 public class PayContext { 34 // 持有策略接口引用(面向接口编程,支持任意策略) 35 private PayStrategy payStrategy; 36 // 构造器注入策略(动态切换) 37 public PayContext(PayStrategy payStrategy) { 38 this.payStrategy = payStrategy; 39 } 40 // 对外提供支付方法,调用策略的核心算法 41 public String doPay(double amount) { 42 return payStrategy.pay(amount); 43 } 44 // 提供set方法,支持运行时动态修改策略 45 public void setPayStrategy(PayStrategy payStrategy) { 46 this.payStrategy = payStrategy; 47 } 48 } 49 50 // 测试类:动态切换支付方式 51 public class StrategyTest { 52 public static void main(String[] args) { 53 double orderAmount = 99.0; // 订单金额99元 54 55 // 1. 使用支付宝支付 56 PayContext payContext = new PayContext(new AlipayStrategy()); 57 System.out.println(payContext.doPay(orderAmount)); // 支付宝支付99元 58 59 // 2. 运行时切换为微信支付 60 payContext.setPayStrategy(new WeChatPayStrategy()); 61 System.out.println(payContext.doPay(orderAmount)); // 微信支付99元 62 63 // 3. 运行时切换为银行卡支付 64 payContext.setPayStrategy(new BankCardPayStrategy()); 65 System.out.println(payContext.doPay(orderAmount)); // 银行卡支付99元 66 67 // 新增支付方式(如银联支付):只需加一个策略类,无需修改PayContext 68 // payContext.setPayStrategy(new UnionPayStrategy()); 69 } 70 }
关键要点
- 策略接口定义算法规范,具体策略类实现算法,算法之间互相独立;
- 上下文类(PayContext)不关心具体算法,只负责调用策略,面向接口编程;
- 新增算法只需实现策略接口,无需修改原有代码,符合「开闭原则」(区别于大量 if-else 判断)。
3. 模板方法模式(Template Method)
核心思想
在抽象父类中定义一个算法的骨架(模板方法),将算法中可变的步骤延迟到子类实现(固定算法结构,灵活定制可变步骤)。
适用场景
多个子类有共同的算法流程,仅部分步骤实现不同(如数据库操作、文件解析、奶茶制作流程)。
代码示例(数据库操作场景,开发常用,固定流程:连接→执行→关闭)
java
运行
1 2 3 // 步骤1:定义抽象父类(模板类,定义算法骨架) 4 public abstract class DbTemplate { 5 // 模板方法:定义数据库操作的固定流程(final修饰,防止子类重写) 6 public final String executeDbOperation(String sql) { 7 // 步骤1:连接数据库(固定步骤,父类实现) 8 connect(); 9 // 步骤2:执行SQL(可变步骤,子类实现) 10 String result = executeSql(sql); 11 // 步骤3:关闭数据库连接(固定步骤,父类实现) 12 close(); 13 // 返回执行结果 14 return result; 15 } 16 17 // 固定步骤1:连接数据库(父类实现,子类无需修改) 18 private void connect() { 19 System.out.println("连接数据库,加载驱动,建立连接..."); 20 } 21 22 // 可变步骤2:执行SQL(抽象方法,子类必须实现) 23 public abstract String executeSql(String sql); 24 25 // 固定步骤3:关闭连接(父类实现,子类无需修改) 26 private void close() { 27 System.out.println("关闭数据库连接,释放资源..."); 28 } 29 } 30 31 // 步骤2:实现具体子类(定制可变步骤) 32 // 查询操作子类 33 public class SelectDbOperation extends DbTemplate { 34 @Override 35 public String executeSql(String sql) { 36 System.out.println("执行查询SQL:" + sql); 37 return "查询成功,返回10条数据"; 38 } 39 } 40 // 插入操作子类 41 public class InsertDbOperation extends DbTemplate { 42 @Override 43 public String executeSql(String sql) { 44 System.out.println("执行插入SQL:" + sql); 45 return "插入成功,影响1行数据"; 46 } 47 } 48 49 // 测试类 50 public class TemplateMethodTest { 51 public static void main(String[] args) { 52 // 执行查询操作:调用模板方法,自动执行「连接→查询→关闭」 53 DbTemplate selectTemplate = new SelectDbOperation(); 54 String selectResult = selectTemplate.executeDbOperation("SELECT * FROM user"); 55 System.out.println("操作结果:" + selectResult); 56 57 System.out.println("-----分割线-----"); 58 59 // 执行插入操作:调用同一模板方法,自动执行「连接→插入→关闭」 60 DbTemplate insertTemplate = new InsertDbOperation(); 61 String insertResult = insertTemplate.executeDbOperation("INSERT INTO user(name) VALUES('张三')"); 62 System.out.println("操作结果:" + insertResult); 63 } 64 }
关键要点
- 模板方法用
final修饰,防止子类重写算法骨架,保证流程统一; - 固定步骤由父类实现(私有方法,子类不可见),可变步骤由抽象方法定义,子类强制实现;
- 核心:封装不变部分,扩展可变部分,减少代码冗余(多个子类复用父类的固定流程)。
4. 迭代器模式(Iterator)
核心思想
提供一个统一的迭代器对象,遍历集合 / 容器中的元素,无需暴露容器的底层实现(如数组、链表、HashMap),实现「遍历逻辑与容器实现解耦」。
适用场景
需要遍历不同类型的容器,且不想暴露容器内部结构(Java 集合框架的
Iterator就是迭代器模式的经典实现)。代码示例(自定义集合 + 迭代器,模拟 Java 的 Iterator)
java
运行
1 2 import java.util.ArrayList; 3 import java.util.List; 4 5 // 步骤1:定义迭代器接口(统一遍历方法) 6 public interface MyIterator<T> { 7 // 是否有下一个元素 8 boolean hasNext(); 9 // 获取下一个元素 10 T next(); 11 } 12 13 // 步骤2:定义容器接口(提供获取迭代器的方法) 14 public interface MyCollection<T> { 15 // 添加元素 16 void add(T t); 17 // 获取迭代器 18 MyIterator<T> iterator(); 19 } 20 21 // 步骤3:实现具体容器(底层用List实现,对外隐藏) 22 public class MyArrayList<T> implements MyCollection<T> { 23 // 底层容器(对外隐藏,不暴露) 24 private List<T> list = new ArrayList<>(); 25 26 @Override 27 public void add(T t) { 28 list.add(t); 29 } 30 31 // 返回自定义迭代器 32 @Override 33 public MyIterator<T> iterator() { 34 return new MyArrayListIterator(); 35 } 36 37 // 内部类:实现迭代器接口,封装遍历逻辑(仅容器内部可见) 38 private class MyArrayListIterator implements MyIterator<T> { 39 // 遍历索引 40 private int index = 0; 41 @Override 42 public boolean hasNext() { 43 return index < list.size(); 44 } 45 @Override 46 public T next() { 47 return list.get(index++); 48 } 49 } 50 } 51 52 // 测试类:统一方式遍历容器,无需关心底层实现 53 public class IteratorTest { 54 public static void main(String[] args) { 55 // 创建自定义容器 56 MyCollection<String> collection = new MyArrayList<>(); 57 // 添加元素 58 collection.add("Java"); 59 collection.add("设计模式"); 60 collection.add("迭代器模式"); 61 collection.add("示例"); 62 63 // 获取迭代器,统一遍历 64 MyIterator<String> iterator = collection.iterator(); 65 while (iterator.hasNext()) { 66 String element = iterator.next(); 67 System.out.println(element); // 依次输出:Java → 设计模式 → 迭代器模式 → 示例 68 } 69 70 // 若底层替换为数组/链表,只需修改MyArrayList的实现,遍历代码无需任何修改 71 } 72 }
关键要点
- 迭代器接口定义统一的遍历方法(hasNext/next),所有容器的迭代器都实现此接口;
- 容器只负责「存储元素」,迭代器负责「遍历元素」,遍历逻辑与容器解耦;
- Java 中所有集合(List/Set/Map)都实现了迭代器模式,
Collection.iterator()就是获取迭代器的方法,遍历方式完全统一。
四、设计模式核心原则(一句话总结,理解后更易活用)
- 开闭原则:对扩展开放,对修改关闭(新增功能用扩展,不修改原有代码);
- 单一职责:一个类 / 方法只做一件事(避免功能臃肿,便于维护);
- 依赖倒置:面向接口编程,不面向具体实现(降低耦合,提高灵活性);
- 里氏替换:子类可以完全替换父类,且不影响程序运行(保证继承的合理性);
- 迪米特法则:最少知道原则,一个对象只和直接关联的对象交互(降低耦合)。
五、总结
以上 8 种设计模式是 Java 开发中使用率最高、最实用的,各模式的核心价值可简单总结:
| 模式 | 核心价值 | 典型应用场景 |
|---|---|---|
| 单例模式 | 全局唯一实例,节省资源 | 工具类、连接池、配置管理器 |
| 工厂方法 | 解耦对象创建与使用 | 日志框架、对象工厂 |
| 装饰器模式 | 动态给对象添加功能 | IO 流、日志增强 |
| 代理模式 | 控制对象访问,添加增强逻辑 | 权限校验、Spring AOP |
| 观察者模式 | 一对多通知,发布 - 订阅 | 消息推送、事件监听 |
| 策略模式 | 算法可替换,消除 if-else | 支付方式、排序算法 |
| 模板方法 | 固定算法骨架,扩展可变步骤 | 数据库操作、流程化业务 |
| 迭代器模式 | 统一遍历容器,隐藏底层实现 | 集合框架、自定义容器 |
使用技巧:设计模式不是 “必须用”,而是 “按需用”—— 当代码出现「耦合高、复用性低、维护困难」时,再考虑用设计模式优化,避免过度设计。

浙公网安备 33010602011771号