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()就是获取迭代器的方法,遍历方式完全统一。
 

四、设计模式核心原则(一句话总结,理解后更易活用)

 
  1. 开闭原则:对扩展开放,对修改关闭(新增功能用扩展,不修改原有代码);
  2. 单一职责:一个类 / 方法只做一件事(避免功能臃肿,便于维护);
  3. 依赖倒置:面向接口编程,不面向具体实现(降低耦合,提高灵活性);
  4. 里氏替换:子类可以完全替换父类,且不影响程序运行(保证继承的合理性);
  5. 迪米特法则:最少知道原则,一个对象只和直接关联的对象交互(降低耦合)。
 

五、总结

 
以上 8 种设计模式是 Java 开发中使用率最高、最实用的,各模式的核心价值可简单总结:
 
模式核心价值典型应用场景
单例模式 全局唯一实例,节省资源 工具类、连接池、配置管理器
工厂方法 解耦对象创建与使用 日志框架、对象工厂
装饰器模式 动态给对象添加功能 IO 流、日志增强
代理模式 控制对象访问,添加增强逻辑 权限校验、Spring AOP
观察者模式 一对多通知,发布 - 订阅 消息推送、事件监听
策略模式 算法可替换,消除 if-else 支付方式、排序算法
模板方法 固定算法骨架,扩展可变步骤 数据库操作、流程化业务
迭代器模式 统一遍历容器,隐藏底层实现 集合框架、自定义容器
 
使用技巧:设计模式不是 “必须用”,而是 “按需用”—— 当代码出现「耦合高、复用性低、维护困难」时,再考虑用设计模式优化,避免过度设计。
posted @ 2026-02-05 14:37  壹袋米  阅读(3)  评论(0)    收藏  举报