什么是设计模式? 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
设计模式的起源 设计模式的概念最早由建筑大师 Christopher Alexander 在建筑领域提出。1994年,Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,这四位作者也被称为”四人帮”(Gang of Four,简称 GoF)。
为什么要学习设计模式?
提升代码质量 : 设计模式提供了经过验证的解决方案,可以避免常见的设计陷阱
增强代码可维护性 : 使用设计模式能让代码结构更清晰,更易于维护和扩展
提高开发效率 : 面对常见问题时,可以直接套用成熟的模式,无需从零开始
统一团队语言 : 设计模式提供了一套标准的技术术语,便于团队沟通
深入理解框架源码 : Spring、MyBatis 等主流框架大量使用了设计模式
设计模式的六大原则 在学习具体的设计模式之前,我们需要先了解面向对象设计的基本原则。这些原则是设计模式的理论基础。
1. 单一职责原则 (Single Responsibility Principle, SRP) 定义 : 一个类应该只有一个引起它变化的原因。
解释 : 一个类只负责一项职责,如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制这个类完成其他职责的能力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class User { private String name; private String email; public void setName (String name) { this .name = name; } public String getName () { return name; } public boolean validateEmail (String email) { } public void saveToDatabase () { } public void sendEmail () { } } class User { private String name; private String email; } class UserValidator { public boolean validateEmail (String email) { } } class UserRepository { public void save (User user) { } } class EmailService { public void sendEmail (User user) { } }
2. 开闭原则 (Open-Closed Principle, OCP) 定义 : 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
解释 : 当需求变化时,应该通过扩展来实现变化,而不是通过修改已有的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class AreaCalculator { public double calculateArea (Object shape) { if (shape instanceof Circle) { Circle circle = (Circle) shape; return Math.PI * circle.radius * circle.radius; } else if (shape instanceof Rectangle) { Rectangle rect = (Rectangle) shape; return rect.width * rect.height; } return 0 ; } } interface Shape { double calculateArea () ; } class Circle implements Shape { private double radius; @Override public double calculateArea () { return Math.PI * radius * radius; } } class Rectangle implements Shape { private double width; private double height; @Override public double calculateArea () { return width * height; } } class Triangle implements Shape { private double base; private double height; @Override public double calculateArea () { return 0.5 * base * height; } }
3. 里氏替换原则 (Liskov Substitution Principle, LSP) 定义 : 所有引用基类的地方必须能透明地使用其子类的对象。
解释 : 子类可以扩展父类的功能,但不能改变父类原有的功能。子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
里氏是一个人名(Liskov,翻译为利斯科夫,简化为里氏)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Rectangle { protected int width; protected int height; public void setWidth (int width) { this .width = width; } public void setHeight (int height) { this .height = height; } public int getArea () { return width * height; } } class Square extends Rectangle { @Override public void setWidth (int width) { this .width = width; this .height = width; } @Override public void setHeight (int height) { this .width = height; this .height = height; } } void test (Rectangle rect) { rect.setWidth(5 ); rect.setHeight(10 ); assert rect.getArea() == 50 ; }
4. 接口隔离原则 (Interface Segregation Principle, ISP) 定义 : 客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。
解释 : 建立单一接口,不要建立庞大臃肿的接口。接口应该尽量细化,同时接口中的方法应该尽量少。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 interface Worker { void work () ; void eat () ; void sleep () ; } class HumanWorker implements Worker { public void work () { } public void eat () { } public void sleep () { } } class RobotWorker implements Worker { public void work () { } public void eat () { } public void sleep () { } } interface Workable { void work () ; } interface Eatable { void eat () ; } interface Sleepable { void sleep () ; } class HumanWorker implements Workable , Eatable, Sleepable { public void work () { } public void eat () { } public void sleep () { } } class RobotWorker implements Workable { public void work () { } }
5. 依赖倒置原则 (Dependency Inversion Principle, DIP) 定义 : 高层模块不应该依赖低层模块,两者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。
解释 : 面向接口编程,不要面向实现编程。
所属两者都应该依赖其抽象,再大白话补充一下,想象一个电源插座系统:
抽象:国标插座接口(统一的标准)
高层模块:你的手机充电器(依赖国标插座)
低层模块:墙上的插座(实现国标标准)
“两者都依赖抽象”:
充电器按照国标插座的标准设计插头(高层依赖抽象)
墙上的插座按照国标标准设计插孔(低层依赖抽象)
只要都遵守国标,任何充电器都能插任何插座
如果没有这个”抽象”(国标):
每个充电器的插头形状不一样
每个插座的插孔形状不一样
完全无法通用!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class MySQLDatabase { public void connect () { } } class UserService { private MySQLDatabase database = new MySQLDatabase (); public void saveUser (User user) { database.connect(); } } interface Database { void connect () ; } class MySQLDatabase implements Database { public void connect () { } } class PostgreSQLDatabase implements Database { public void connect () { } } class UserService { private Database database; public UserService (Database database) { this .database = database; } public void saveUser (User user) { database.connect(); } }
6. 迪米特法则 (Law of Demeter, LoD) 定义 : 一个对象应该对其他对象有最少的了解,又称最少知识原则 。
解释 : 一个类对自己依赖的类知道的越少越好,降低类之间的耦合度。
依赖地越多,耦合得越重。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Customer { public Wallet getWallet () { } } class Wallet { public Money getMoney () { } } class Cashier { public void charge (Customer customer, double amount) { Wallet wallet = customer.getWallet(); Money money = wallet.getMoney(); } } class Customer { private Wallet wallet; public void pay (double amount) { wallet.pay(amount); } } class Cashier { public void charge (Customer customer, double amount) { customer.pay(amount); } }
设计模式分类 GoF 将23种设计模式按照目的分为三大类:
创建型模式 (Creational Patterns) 创建型模式关注对象的创建过程,将对象的创建和使用分离,降低系统的耦合度。
单例模式 (Singleton Pattern)
工厂方法模式 (Factory Method Pattern)
抽象工厂模式 (Abstract Factory Pattern)
建造者模式 (Builder Pattern)
原型模式 (Prototype Pattern)
结构型模式 (Structural Patterns) 结构型模式关注类和对象的组合,通过继承和组合来获得更强大的功能。
适配器模式 (Adapter Pattern)
桥接模式 (Bridge Pattern)
组合模式 (Composite Pattern)
装饰器模式 (Decorator Pattern)
外观模式 (Facade Pattern)
享元模式 (Flyweight Pattern)
代理模式 (Proxy Pattern)
行为型模式 (Behavioral Patterns) 行为型模式关注对象之间的通信,明确对象之间的职责划分。
责任链模式 (Chain of Responsibility Pattern)
命令模式 (Command Pattern)
解释器模式 (Interpreter Pattern)
迭代器模式 (Iterator Pattern)
中介者模式 (Mediator Pattern)
备忘录模式 (Memento Pattern)
观察者模式 (Observer Pattern)
状态模式 (State Pattern)
策略模式 (Strategy Pattern)
模板方法模式 (Template Method Pattern)
访问者模式 (Visitor Pattern)
常用设计模式详解 GoF 的 23 种设计模式按照目的可以分为三大类:创建型模式 (5种)、结构型模式 (7种)、行为型模式 (11种)。下面我们按照分类详细介绍这些模式。
创建型模式 (Creational Patterns) 创建型模式关注对象的创建过程,将对象的创建和使用分离,降低系统的耦合度。
单例模式 (Singleton Pattern - 创建型) 定义 : 确保一个类只有一个实例,并提供一个全局访问点。
应用场景 :
实现方式 :
懒汉式(线程不安全) 1 2 3 4 5 6 7 8 9 10 11 12 public class Singleton { private static Singleton instance; private Singleton () {} public static Singleton getInstance () { if (instance == null ) { instance = new Singleton (); } return instance; } }
饿汉式(线程安全) 1 2 3 4 5 6 7 8 9 public class Singleton { private static final Singleton instance = new Singleton (); private Singleton () {} public static Singleton getInstance () { return instance; } }
双重检查锁定(推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Singleton { 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; } }
静态内部类(推荐) 1 2 3 4 5 6 7 8 9 10 11 public class Singleton { private Singleton () {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton (); } public static Singleton getInstance () { return SingletonHolder.INSTANCE; } }
核心原理:
(1) 延迟加载(Lazy Loading)
- SingletonHolder 是一个静态内部类
- 类加载时机:静态内部类不会在外部类加载时就加载,只有在首次主动使用时才会被加载
- 当第一次调用 Singleton.getInstance() 时,JVM 才会加载 SingletonHolder 类
- 此时才会初始化 INSTANCE 变量,创建 Singleton 实例
(2) 线程安全性
- JVM 类加载机制保证:类的初始化阶段是线程安全的
- JVM 会保证一个类的 <clinit>() 方法(类初始化方法)在多线程环境下被正确加锁和同步
- 这意味着 INSTANCE 的初始化天然是线程安全的,无需额外的 synchronized
原理示意: // 第一次调用 getInstance() Singleton.getInstance() ↓ 访问 SingletonHolder.INSTANCE ↓ 触发 SingletonHolder 类加载 ↓ JVM 加锁,执行 () 方法 ↓ 创建 Singleton 实例并赋值给 INSTANCE ↓ 返回 INSTANCE
// 后续调用 getInstance()
Singleton.getInstance()
↓
直接返回已创建的 SingletonHolder.INSTANCE
优点:
✅ 延迟加载(懒加载)
✅ 天然线程安全
✅ 实现简洁
枚举(最佳实践) 1 2 3 4 5 6 7 public enum Singleton { INSTANCE; public void doSomething () { } }
核心原理:
(1) JVM 层面的保证
枚举在 JVM 中被编译后,实际上会生成类似这样的代码:
public final class Singleton extends Enum { public static final Singleton INSTANCE;
static {
INSTANCE = new Singleton("INSTANCE", 0);
}
private Singleton(String name, int ordinal) {
super(name, ordinal);
}
}
(2) 三大保证
① 线程安全
枚举实例在类加载时创建,JVM 保证 () 方法的线程安全
枚举值是 public static final 的,天然线程安全
② 防止反射攻击 // 尝试通过反射创建枚举实例会抛出异常 Constructor constructor = Singleton.class.getDeclaredConstructor(); constructor.setAccessible(true); Singleton instance = constructor.newInstance(); // 抛出 IllegalArgumentException: Cannot reflectively create enum objects
JVM 在 Constructor.newInstance() 方法中特别处理了枚举: if ((clazz.getModifiers() & Modifier.ENUM) != 0) throw new IllegalArgumentException(“Cannot reflectively create enum objects”);
③ 防止序列化破坏 // 即使序列化再反序列化,也保证是同一个实例 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“singleton.ser”)); oos.writeObject(Singleton.INSTANCE); oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“singleton.ser”)); Singleton instance = (Singleton) ois.readObject();
System.out.println(instance == Singleton.INSTANCE); // true
枚举的反序列化有特殊处理,ObjectInputStream 会通过枚举名称查找已存在的实例,而不是创建新实例。
实际应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Component public class ConfigManager { } public class Logger { private static volatile Logger instance; private Logger () {} public static Logger getInstance () { if (instance == null ) { synchronized (Logger.class) { if (instance == null ) { instance = new Logger (); } } } return instance; } public void log (String message) { System.out.println("[" + LocalDateTime.now() + "] " + message); } }
工厂模式 (Factory Pattern - 创建型) 定义 : 定义一个创建对象的接口,让子类决定实例化哪一个类。
应用场景 :
对象创建逻辑复杂
需要根据不同条件创建不同对象
隐藏对象的创建细节
简单工厂模式 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 interface Product { void use () ; } class ProductA implements Product { @Override public void use () { System.out.println("使用产品 A" ); } } class ProductB implements Product { @Override 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 ("未知产品类型" ); } } } Product product = SimpleFactory.createProduct("A" );product.use();
工厂方法模式 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 interface Product { void use () ; } class ProductA implements Product { @Override public void use () { System.out.println("使用产品 A" ); } } class ProductB implements Product { @Override public void use () { System.out.println("使用产品 B" ); } } interface Factory { Product createProduct () ; } class FactoryA implements Factory { @Override public Product createProduct () { return new ProductA (); } } class FactoryB implements Factory { @Override public Product createProduct () { return new ProductB (); } } Factory factory = new FactoryA ();Product product = factory.createProduct();product.use();
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 Connection conn = DriverManager.getConnection(url, user, password);@Configuration public class BeanFactory { @Bean public UserService userService () { return new UserServiceImpl (); } }
建造者模式 (Builder Pattern - 创建型) 定义 : 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
应用场景 :
对象有很多属性,部分必填部分可选
对象创建过程复杂,需要多个步骤
避免构造函数参数过多
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 class Computer { private String cpu; private String memory; private String hardDisk; private String graphics; private String monitor; private String keyboard; private Computer (Builder builder) { this .cpu = builder.cpu; this .memory = builder.memory; this .hardDisk = builder.hardDisk; this .graphics = builder.graphics; this .monitor = builder.monitor; this .keyboard = builder.keyboard; } public static class Builder { private String cpu; private String memory; private String hardDisk = "500G" ; private String graphics = "集成显卡" ; private String monitor = "普通显示器" ; private String keyboard = "普通键盘" ; public Builder (String cpu, String memory) { this .cpu = cpu; this .memory = memory; } public Builder hardDisk (String hardDisk) { this .hardDisk = hardDisk; return this ; } public Builder graphics (String graphics) { this .graphics = graphics; return this ; } public Builder monitor (String monitor) { this .monitor = monitor; return this ; } public Builder keyboard (String keyboard) { this .keyboard = keyboard; return this ; } public Computer build () { return new Computer (this ); } } @Override public String toString () { return "Computer{" + "cpu='" + cpu + '\'' + ", memory='" + memory + '\'' + ", hardDisk='" + hardDisk + '\'' + ", graphics='" + graphics + '\'' + ", monitor='" + monitor + '\'' + ", keyboard='" + keyboard + '\'' + '}' ; } } Computer computer1 = new Computer .Builder("Intel i7" , "16G" ) .hardDisk("1T SSD" ) .graphics("RTX 3080" ) .monitor("4K 显示器" ) .keyboard("机械键盘" ) .build(); Computer computer2 = new Computer .Builder("Intel i5" , "8G" ) .hardDisk("512G SSD" ) .build(); System.out.println(computer1); System.out.println(computer2);
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 StringBuilder sb = new StringBuilder () .append("Hello" ) .append(" " ) .append("World" ); @Builder public class User { private String name; private int age; private String email; } User user = User.builder() .name("张三" ) .age(25 ) .email("zhangsan@example.com" ) .build(); Request request = new Request .Builder() .url("https://api.example.com" ) .header("Authorization" , "Bearer token" ) .post(body) .build();
结构型模式 (Structural Patterns) 结构型模式关注类和对象的组合,通过继承和组合来获得更强大的功能。
适配器模式 (Adapter Pattern - 结构型) 定义 : 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
应用场景 :
形象比喻 : 就像电源转换插头 ,把中国的两孔插头转换成美国的三孔插座标准。
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 interface MediaPlayer { void play (String audioType, String fileName) ; } class AdvancedMediaPlayer { public void playVlc (String fileName) { System.out.println("播放 VLC 文件: " + fileName); } public void playMp4 (String fileName) { System.out.println("播放 MP4 文件: " + fileName); } } class MediaAdapter implements MediaPlayer { private AdvancedMediaPlayer advancedPlayer; public MediaAdapter (String audioType) { this .advancedPlayer = new AdvancedMediaPlayer (); } @Override public void play (String audioType, String fileName) { if ("vlc" .equalsIgnoreCase(audioType)) { advancedPlayer.playVlc(fileName); } else if ("mp4" .equalsIgnoreCase(audioType)) { advancedPlayer.playMp4(fileName); } } } class AudioPlayer implements MediaPlayer { private MediaAdapter adapter; @Override public void play (String audioType, String fileName) { if ("mp3" .equalsIgnoreCase(audioType)) { System.out.println("播放 MP3 文件: " + fileName); } else if ("vlc" .equalsIgnoreCase(audioType) || "mp4" .equalsIgnoreCase(audioType)) { adapter = new MediaAdapter (audioType); adapter.play(audioType, fileName); } else { System.out.println("不支持的格式: " + audioType); } } } MediaPlayer player = new AudioPlayer ();player.play("mp3" , "song.mp3" ); player.play("mp4" , "video.mp4" ); player.play("vlc" , "movie.vlc" );
实际应用 :
1 2 3 4 5 Reader reader = new InputStreamReader (new FileInputStream ("file.txt" ));
装饰器模式 (Decorator Pattern - 结构型) 定义 : 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。
应用场景 :
需要动态地给对象添加功能
需要大量的子类扩展时
IO 流的包装
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 interface Coffee { double getCost () ; String getDescription () ; } class SimpleCoffee implements Coffee { @Override public double getCost () { return 10.0 ; } @Override public String getDescription () { return "普通咖啡" ; } } abstract class CoffeeDecorator implements Coffee { protected Coffee coffee; public CoffeeDecorator (Coffee coffee) { this .coffee = coffee; } @Override public double getCost () { return coffee.getCost(); } @Override public String getDescription () { return coffee.getDescription(); } } class MilkDecorator extends CoffeeDecorator { public MilkDecorator (Coffee coffee) { super (coffee); } @Override public double getCost () { return super .getCost() + 2.0 ; } @Override public String getDescription () { return super .getDescription() + " + 牛奶" ; } } class SugarDecorator extends CoffeeDecorator { public SugarDecorator (Coffee coffee) { super (coffee); } @Override public double getCost () { return super .getCost() + 1.0 ; } @Override public String getDescription () { return super .getDescription() + " + 糖" ; } } class ChocolateDecorator extends CoffeeDecorator { public ChocolateDecorator (Coffee coffee) { super (coffee); } @Override public double getCost () { return super .getCost() + 3.0 ; } @Override public String getDescription () { return super .getDescription() + " + 巧克力" ; } } Coffee coffee = new SimpleCoffee ();System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元" ); coffee = new MilkDecorator (coffee); System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元" ); coffee = new SugarDecorator (coffee); System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元" ); coffee = new ChocolateDecorator (coffee); System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元" );
实际应用 :
1 2 3 4 5 6 7 InputStream in = new FileInputStream ("file.txt" );in = new BufferedInputStream (in); in = new DataInputStream (in); BeanWrapper wrapper = new BeanWrapperImpl (user);
代理模式 (Proxy Pattern - 结构型) 定义 : 为其他对象提供一种代理以控制对这个对象的访问。
应用场景 :
远程代理(RPC)
虚拟代理(延迟加载)
保护代理(权限控制)
智能引用(日志、缓存等)
静态代理 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 interface UserService { void saveUser (String username) ; } class UserServiceImpl implements UserService { @Override public void saveUser (String username) { System.out.println("保存用户: " + username); } } class UserServiceProxy implements UserService { private UserService userService; public UserServiceProxy (UserService userService) { this .userService = userService; } @Override public void saveUser (String username) { System.out.println("[代理] 权限检查" ); System.out.println("[代理] 开始事务" ); userService.saveUser(username); System.out.println("[代理] 提交事务" ); System.out.println("[代理] 记录日志" ); } } UserService userService = new UserServiceImpl ();UserService proxy = new UserServiceProxy (userService);proxy.saveUser("张三" );
动态代理(JDK) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;interface UserService { void saveUser (String username) ; void deleteUser (String username) ; } class UserServiceImpl implements UserService { @Override public void saveUser (String username) { System.out.println("保存用户: " + username); } @Override public void deleteUser (String username) { System.out.println("删除用户: " + username); } } class ServiceInvocationHandler implements InvocationHandler { private Object target; public ServiceInvocationHandler (Object target) { this .target = target; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("[动态代理] 方法调用前: " + method.getName()); Object result = method.invoke(target, args); System.out.println("[动态代理] 方法调用后: " + method.getName()); return result; } } UserService userService = new UserServiceImpl ();UserService proxy = (UserService) Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new ServiceInvocationHandler (userService) ); proxy.saveUser("张三" ); proxy.deleteUser("李四" );
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 @Service public class UserService { @Transactional public void saveUser (User user) { } } UserMapper mapper = sqlSession.getMapper(UserMapper.class);
外观模式 (Facade Pattern - 结构型) 也叫做门面模式 定义 : 为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。
应用场景 :
简化复杂系统的接口
为多个子系统提供统一入口
解耦客户端和子系统
形象比喻 : 就像酒店前台 ,你不需要直接联系客房部、餐饮部、保洁部,只需要告诉前台你的需求,前台会协调各部门为你服务。
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 class Stereo { public void on () { System.out.println("音响打开" ); } public void off () { System.out.println("音响关闭" ); } public void setVolume (int volume) { System.out.println("音量设置为: " + volume); } } class Projector { public void on () { System.out.println("投影仪打开" ); } public void off () { System.out.println("投影仪关闭" ); } public void setInput (String input) { System.out.println("投影仪输入设置为: " + input); } } class Lights { public void dim (int level) { System.out.println("灯光调暗至: " + level + "%" ); } public void on () { System.out.println("灯光打开" ); } } class DvdPlayer { public void on () { System.out.println("DVD 播放器打开" ); } public void off () { System.out.println("DVD 播放器关闭" ); } public void play (String movie) { System.out.println("播放电影: " + movie); } } class HomeTheaterFacade { private Stereo stereo; private Projector projector; private Lights lights; private DvdPlayer dvdPlayer; public HomeTheaterFacade () { this .stereo = new Stereo (); this .projector = new Projector (); this .lights = new Lights (); this .dvdPlayer = new DvdPlayer (); } public void watchMovie (String movie) { System.out.println("准备观影..." ); lights.dim(10 ); projector.on(); projector.setInput("DVD" ); stereo.on(); stereo.setVolume(5 ); dvdPlayer.on(); dvdPlayer.play(movie); System.out.println("开始播放!" ); } public void endMovie () { System.out.println("关闭影院..." ); dvdPlayer.off(); stereo.off(); projector.off(); lights.on(); System.out.println("影院已关闭" ); } } HomeTheaterFacade homeTheater = new HomeTheaterFacade ();homeTheater.watchMovie("阿凡达" ); homeTheater.endMovie();
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Logger logger = LoggerFactory.getLogger(MyClass.class);logger.info("这是日志" ); ApplicationContext context = new ClassPathXmlApplicationContext ("beans.xml" );public class DbUtils { public static void executeUpdate (String sql, Object... params) { } }
行为型模式 (Behavioral Patterns) 行为型模式关注对象之间的通信,明确对象之间的职责划分。
策略模式 (Strategy Pattern - 行为型) 定义 : 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。
应用场景 :
多个算法只在行为上稍有不同
需要动态切换算法
避免使用多重条件判断
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 interface PaymentStrategy { void pay (double amount) ; } class CreditCardPayment implements PaymentStrategy { private String cardNumber; public CreditCardPayment (String cardNumber) { this .cardNumber = cardNumber; } @Override public void pay (double amount) { System.out.println("使用信用卡 " + cardNumber + " 支付 " + amount + " 元" ); } } class AlipayPayment implements PaymentStrategy { private String account; public AlipayPayment (String account) { this .account = account; } @Override public void pay (double amount) { System.out.println("使用支付宝账户 " + account + " 支付 " + amount + " 元" ); } } class WeChatPayment implements PaymentStrategy { private String openId; public WeChatPayment (String openId) { this .openId = openId; } @Override public void pay (double amount) { System.out.println("使用微信 " + openId + " 支付 " + amount + " 元" ); } } class ShoppingCart { private PaymentStrategy paymentStrategy; public void setPaymentStrategy (PaymentStrategy paymentStrategy) { this .paymentStrategy = paymentStrategy; } public void checkout (double amount) { if (paymentStrategy == null ) { throw new IllegalStateException ("未选择支付方式" ); } paymentStrategy.pay(amount); } } ShoppingCart cart = new ShoppingCart ();cart.setPaymentStrategy(new AlipayPayment ("user@example.com" )); cart.checkout(100.0 ); cart.setPaymentStrategy(new CreditCardPayment ("1234-5678-9012-3456" )); cart.checkout(200.0 );
实际应用 :
1 2 3 4 5 6 7 List<String> list = Arrays.asList("apple" , "banana" , "cherry" ); Collections.sort(list, Comparator.naturalOrder()); Collections.sort(list, Comparator.reverseOrder()); Collections.sort(list, Comparator.comparing(String::length));
观察者模式 (Observer Pattern - 行为型) 定义 : 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
应用场景 :
事件处理系统
消息订阅系统
MVC 架构中的模型-视图关系
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import java.util.ArrayList;import java.util.List;interface Observer { void update (String message) ; } interface Subject { void attach (Observer observer) ; void detach (Observer observer) ; void notifyObservers () ; } class NewsPublisher implements Subject { private List<Observer> observers = new ArrayList <>(); private String latestNews; @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(latestNews); } } public void publishNews (String news) { this .latestNews = news; System.out.println("发布新闻: " + news); notifyObservers(); } } class NewsReader implements Observer { private String name; public NewsReader (String name) { this .name = name; } @Override public void update (String message) { System.out.println(name + " 收到新闻: " + message); } } NewsPublisher publisher = new NewsPublisher ();Observer reader1 = new NewsReader ("张三" );Observer reader2 = new NewsReader ("李四" );Observer reader3 = new NewsReader ("王五" );publisher.attach(reader1); publisher.attach(reader2); publisher.attach(reader3); publisher.publishNews("重大新闻:设计模式很重要!" ); publisher.detach(reader2); publisher.publishNews("最新消息:观察者模式已掌握!" );
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 @Component public class UserEventListener { @EventListener public void handleUserCreated (UserCreatedEvent event) { System.out.println("用户创建: " + event.getUsername()); } }
模板方法模式 (Template Method Pattern - 行为型) 定义 : 在一个方法中定义算法的骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
应用场景 :
多个类有相同的处理流程(相同的生命周期),但具体步骤不同
框架设计(定义流程,由用户实现细节)
代码复用
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 abstract class DataProcessor { public final void process () { readData(); processData(); saveData(); } protected abstract void readData () ; protected abstract void processData () ; protected void saveData () { System.out.println("保存处理后的数据" ); } } class CsvDataProcessor extends DataProcessor { @Override protected void readData () { System.out.println("从 CSV 文件读取数据" ); } @Override protected void processData () { System.out.println("处理 CSV 数据" ); } } class XmlDataProcessor extends DataProcessor { @Override protected void readData () { System.out.println("从 XML 文件读取数据" ); } @Override protected void processData () { System.out.println("处理 XML 数据" ); } } DataProcessor csvProcessor = new CsvDataProcessor ();csvProcessor.process(); DataProcessor xmlProcessor = new XmlDataProcessor ();xmlProcessor.process();
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class JdbcTemplate { public <T> T query (String sql, ResultSetExtractor<T> rse) { Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); T result = rse.extractData(rs); closeResources(); return result; } } public abstract class HttpServlet { public void service (HttpServletRequest req, HttpServletResponse resp) { String method = req.getMethod(); if (method.equals("GET" )) { doGet(req, resp); } else if (method.equals("POST" )) { doPost(req, resp); } } protected abstract void doGet (HttpServletRequest req, HttpServletResponse resp) ; protected abstract void doPost (HttpServletRequest req, HttpServletResponse resp) ; }
责任链模式 (Chain of Responsibility Pattern - 行为型) 定义 : 为请求创建一个接收者对象的链,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把请求传给下一个接收者,依此类推。
应用场景 :
多个对象可以处理同一请求,但具体由哪个对象处理在运行时动态决定
需要动态指定处理请求的对象集合
过滤器链、拦截器链
实现示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 abstract class ApprovalHandler { protected ApprovalHandler nextHandler; protected String name; public ApprovalHandler (String name) { this .name = name; } public void setNextHandler (ApprovalHandler nextHandler) { this .nextHandler = nextHandler; } public abstract void handleRequest (int amount) ; } class Supervisor extends ApprovalHandler { public Supervisor () { super ("主管" ); } @Override public void handleRequest (int amount) { if (amount <= 1000 ) { System.out.println(name + " 批准了 " + amount + " 元的报销申请" ); } else if (nextHandler != null ) { System.out.println(name + " 无权批准,转交上级处理" ); nextHandler.handleRequest(amount); } } } class Manager extends ApprovalHandler { public Manager () { super ("经理" ); } @Override public void handleRequest (int amount) { if (amount <= 5000 ) { System.out.println(name + " 批准了 " + amount + " 元的报销申请" ); } else if (nextHandler != null ) { System.out.println(name + " 无权批准,转交上级处理" ); nextHandler.handleRequest(amount); } } } class Director extends ApprovalHandler { public Director () { super ("总监" ); } @Override public void handleRequest (int amount) { if (amount <= 10000 ) { System.out.println(name + " 批准了 " + amount + " 元的报销申请" ); } else if (nextHandler != null ) { System.out.println(name + " 无权批准,转交上级处理" ); nextHandler.handleRequest(amount); } } } class CEO extends ApprovalHandler { public CEO () { super ("CEO" ); } @Override public void handleRequest (int amount) { System.out.println(name + " 批准了 " + amount + " 元的报销申请" ); } } ApprovalHandler supervisor = new Supervisor ();ApprovalHandler manager = new Manager ();ApprovalHandler director = new Director ();ApprovalHandler ceo = new CEO ();supervisor.setNextHandler(manager); manager.setNextHandler(director); director.setNextHandler(ceo); supervisor.handleRequest(500 ); supervisor.handleRequest(3000 ); supervisor.handleRequest(8000 ); supervisor.handleRequest(20000 );
实际应用 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class MyFilter implements Filter { @Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) { System.out.println("过滤器处理" ); chain.doFilter(request, response); } } @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain (HttpSecurity http) throws Exception { return http .csrf().disable() .authorizeRequests() .anyRequest().authenticated() .and() .build(); } } @Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) }) public class MyInterceptor implements Interceptor { @Override public Object intercept (Invocation invocation) throws Throwable { Object result = invocation.proceed(); return result; } }
设计模式在实际项目中的应用 Spring 框架中的设计模式
单例模式 : Spring Bean 默认是单例的
工厂模式 : BeanFactory 和 ApplicationContext
代理模式 : AOP 实现
模板方法模式 : JdbcTemplate、RestTemplate
观察者模式 : Spring Event 事件机制
适配器模式 : HandlerAdapter
策略模式 : Resource 接口的不同实现
MyBatis 中的设计模式
工厂模式 : SqlSessionFactory
建造者模式 : SqlSessionFactoryBuilder
代理模式 : Mapper 接口的动态代理
模板方法模式 : BaseExecutor
装饰器模式 : Cache 的包装
JDK 中的设计模式
单例模式 : Runtime.getRuntime()
工厂模式 : Calendar.getInstance()
装饰器模式 : IO 流
适配器模式 : InputStreamReader
迭代器模式 : Iterator
观察者模式 : Observable 和 Observer
策略模式 : Comparator