🎭 Java设计模式详解:让代码优雅如诗的秘密武器
💡 开篇小故事:小李是一名刚入行的程序员,他写的代码就像一团乱麻,每次修改都要花很长时间。直到有一天,他遇到了设计模式这位"代码魔法师"...
🎯 引言:为什么需要设计模式?
想象一下,如果你要建造一座房子:
- 🏠 没有设计模式:就像用积木随意堆砌,看起来摇摇欲坠
- 🏗️ 有设计模式:就像有专业的建筑图纸,每个房间都有明确的功能和位置
设计模式就是软件开发的"建筑图纸",让我们的代码从"乱糟糟的毛坯房"变成"精装修的豪宅"!
📊 设计模式能解决什么问题?
问题类型 | 没有设计模式 | 使用设计模式 |
---|---|---|
代码重复 | 🔄 复制粘贴,改一处要改N处 | ✨ 一次编写,多处复用 |
扩展困难 | 😰 添加新功能要改老代码 | 🚀 新功能独立添加 |
维护困难 | 😵 看不懂,不敢改 | 📖 清晰易懂,放心修改 |
测试困难 | 🧪 测试代码比业务代码还多 | 🎯 职责分离,测试简单 |
🎪 第一部分:设计模式基础 - 代码世界的"武林秘籍"
1.1 🎭 什么是设计模式?
定义:设计模式就像是编程界的"武林秘籍",是前辈们总结出来的解决特定问题的"招式"。
核心思想:不是教你写代码,而是教你"思考代码"的方式!
🎬 生活类比:
- 设计模式就像做菜的"菜谱"
- 不同的菜谱解决不同的烹饪问题
- 学会了菜谱,你就能做出各种美味佳肴
1.2 🏷️ 设计模式的分类 - 三大门派
📊 设计模式分类:GoF设计模式按职责分为三大类:
- 🏭 创建型模式:负责对象的创建,就像工厂生产产品
- 🏗️ 结构型模式:负责对象的结构和组合,就像建筑师设计房屋
- 🎭 行为型模式:负责对象间的交互和通信,就像人与人之间的交流
🏆 GoF设计模式 - 软件开发的"圣经"
🎯 GoF是什么?
GoF 是 "Gang of Four"(四人帮) 的缩写,指的是四位软件工程大师:
- Erich Gamma - 瑞士苏黎世联邦理工学院教授
- Richard Helm - IBM研究员
- Ralph Johnson - 伊利诺伊大学香槟分校教授
- John Vlissides - IBM研究员(已故)
这四位大师在1994年合作出版了《Design Patterns: Elements of Reusable Object-Oriented Software》(设计模式:可复用面向对象软件的基础),这本书被誉为软件开发的"圣经",首次系统性地提出了23种设计模式的概念和实现方法。
🏆 历史意义:GoF设计模式的出现,标志着软件工程从"手工艺时代"进入了"工程化时代",为后来的软件架构设计奠定了理论基础。
📋 设计模式完整清单(GoF 23种设计模式)
🎯 快速导航:以下是所有23种GoF设计模式的完整列表,你可以根据需要跳转到具体模式的学习。
🏭 创建型模式(5种)
序号 | 设计模式 | 英文全称 | 使用频率 | 难度等级 |
---|---|---|---|---|
1 | 单例模式 | Singleton Pattern | ⭐⭐⭐⭐⭐ | ⭐⭐ |
2 | 工厂方法模式 | Factory Method Pattern | ⭐⭐⭐⭐ | ⭐⭐⭐ |
3 | 抽象工厂模式 | Abstract Factory Pattern | ⭐⭐⭐ | ⭐⭐⭐⭐ |
4 | 建造者模式 | Builder Pattern | ⭐⭐⭐ | ⭐⭐⭐ |
5 | 原型模式 | Prototype Pattern | ⭐⭐ | ⭐⭐ |
🏗️ 结构型模式(7种)
序号 | 设计模式 | 英文全称 | 使用频率 | 难度等级 |
---|---|---|---|---|
6 | 适配器模式 | Adapter Pattern | ⭐⭐⭐⭐ | ⭐⭐ |
7 | 装饰器模式 | Decorator Pattern | ⭐⭐⭐⭐ | ⭐⭐⭐ |
8 | 代理模式 | Proxy Pattern | ⭐⭐⭐⭐ | ⭐⭐⭐ |
9 | 外观模式 | Facade Pattern | ⭐⭐⭐ | ⭐⭐ |
10 | 桥接模式 | Bridge Pattern | ⭐⭐ | ⭐⭐⭐⭐ |
11 | 组合模式 | Composite Pattern | ⭐⭐⭐ | ⭐⭐⭐ |
12 | 享元模式 | Flyweight Pattern | ⭐⭐ | ⭐⭐⭐⭐ |
🎭 行为型模式(11种)
序号 | 设计模式 | 英文全称 | 使用频率 | 难度等级 |
---|---|---|---|---|
13 | 观察者模式 | Observer Pattern | ⭐⭐⭐⭐⭐ | ⭐⭐ |
14 | 策略模式 | Strategy Pattern | ⭐⭐⭐⭐⭐ | ⭐⭐ |
15 | 命令模式 | Command Pattern | ⭐⭐⭐ | ⭐⭐⭐ |
16 | 状态模式 | State Pattern | ⭐⭐⭐ | ⭐⭐⭐⭐ |
17 | 模板方法模式 | Template Method Pattern | ⭐⭐⭐⭐ | ⭐⭐ |
18 | 迭代器模式 | Iterator Pattern | ⭐⭐⭐⭐ | ⭐⭐ |
19 | 责任链模式 | Chain of Responsibility Pattern | ⭐⭐⭐ | ⭐⭐⭐ |
20 | 中介者模式 | Mediator Pattern | ⭐⭐ | ⭐⭐⭐⭐ |
21 | 访问者模式 | Visitor Pattern | ⭐⭐ | ⭐⭐⭐⭐⭐ |
22 | 备忘录模式 | Memento Pattern | ⭐⭐ | ⭐⭐⭐ |
23 | 解释器模式 | Interpreter Pattern | ⭐ | ⭐⭐⭐⭐⭐ |
💡 使用频率说明:
⭐⭐⭐⭐⭐:非常常用,必须掌握
⭐⭐⭐⭐:常用,建议掌握
⭐⭐⭐:中等使用频率
⭐⭐:较少使用
⭐:很少使用,了解即可
🎯 难度等级说明:⭐⭐:简单,容易理解
⭐⭐⭐:中等,需要一定理解
⭐⭐⭐⭐:较难,需要深入理解
⭐⭐⭐⭐⭐:很难,需要大量实践
1.3 💎 设计模式的价值 - 从"菜鸟"到"大神"的蜕变
🚫 没有设计模式 - "菜鸟代码"
csharp
// 😰 菜鸟小李的代码 - 硬编码,难以维护
public class PaymentService {
public void processPayment(String paymentType, double amount) {
if (paymentType.equals("alipay")) {
System.out.println("使用支付宝支付: " + amount);
} else if (paymentType.equals("wechat")) {
System.out.println("使用微信支付: " + amount);
} else if (paymentType.equals("bank")) {
System.out.println("使用银行卡支付: " + amount);
}
// 😱 如果要添加新的支付方式,又要改这里!
}
}
✨ 使用设计模式 - "大神代码"
java
// 🎯 大神小红的代码 - 策略模式,优雅扩展
public interface PaymentStrategy {
void pay(double amount);
}
public class AlipayStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用支付宝支付: " + amount);
}
}
public class WechatStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用微信支付: " + amount);
}
}
public class PaymentService {
private PaymentStrategy strategy;
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void processPayment(double amount) {
strategy.pay(amount);
}
}
// 🚀 添加新支付方式,只需要实现新策略,不需要修改现有代码!
public class BitcoinStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("使用比特币支付: " + amount);
}
}
1.4 🌟 设计模式的应用场景 - 真实世界的"魔法"
🏢 框架开发中的设计模式
框架 | 使用的设计模式 | 作用 |
---|---|---|
Spring | 🏭 工厂模式、🎭 代理模式 | 管理Bean、AOP切面 |
MyBatis | 🏗️ 建造者模式、🎭 代理模式 | 构建SQL、动态代理 |
JDK | 🎯 单例模式、🎭 策略模式 | 工具类、集合框架 |
💼 业务开发中的设计模式
业务场景 | 推荐设计模式 | 解决的问题 |
---|---|---|
支付系统 | 🎭 策略模式 | 多种支付方式 |
日志系统 | 👀 观察者模式 | 事件通知 |
缓存系统 | 🎨 装饰器模式 | 功能增强 |
1.5 📚 学习建议 - 从小白到大神的修炼之路
- 🎯 理解原理:不要死记硬背,要理解每个模式解决的问题
- 🛠️ 实践应用:在实际项目中尝试使用设计模式
- ⚖️ 避免过度设计:不是所有地方都需要使用设计模式
- 🎭 结合场景:根据具体场景选择合适的设计模式
🎪 第二部分:SOLID原则详解 - 代码世界的"武林心法"
💡 小故事继续:小李学会了设计模式后,代码质量提升了很多。但是他的师父告诉他:"徒儿,光有招式还不够,你还需要修炼心法!"
📚 SOLID原则创始人 :SOLID原则是由 Robert C. Martin(也被称为"Uncle Bob")在2000年提出的面向对象设计的五个基本原则。这些原则是面向对象编程和设计的基石。
📊 SOLID原则概览:
🎯 原则 📖 英文全称 🇨🇳 中文名称 💡 核心思想 S Single Responsibility Principle 单一职责原则 一个类只做一件事 O Open-Closed Principle 开闭原则 对扩展开放,对修改关闭 L Liskov Substitution Principle 里氏替换原则 子类可以替换父类 I Interface Segregation Principle 接口隔离原则 使用多个专门接口 D Dependency Inversion Principle 依赖倒置原则 依赖抽象而非具体
2.1 🎯 单一职责原则(SRP)- "一心一意"
2.1.1 定义与理解
定义:一个类应该只有一个引起它变化的原因。
核心思想:就像一个人,最好只专注做一件事,并且把它做好!
🎭 生活类比:
- 厨师只负责做菜
- 服务员只负责服务
- 收银员只负责收钱
- 如果一个人又要做菜又要收钱,就容易出错
2.1.2 🚫 违反SRP的示例 - "全能超人"
typescript
// 😰 违反SRP的类 - 一个类承担了太多职责
public class UserManager {
// 用户管理职责
public void createUser(User user) {
// 创建用户逻辑
}
public void updateUser(User user) {
// 更新用户逻辑
}
public void deleteUser(Long userId) {
// 删除用户逻辑
}
// 数据持久化职责
public void saveToDatabase(User user) {
// 数据库操作逻辑
}
public void loadFromDatabase(Long userId) {
// 数据库查询逻辑
}
// 日志记录职责
public void logUserAction(String action, User user) {
// 日志记录逻辑
}
// 邮件发送职责
public void sendWelcomeEmail(User user) {
// 邮件发送逻辑
}
// 😱 这个类承担了太多职责,违反了SRP!
}
2.1.3 ✨ 遵循SRP的重构 - "专业分工"
typescript
// 🎯 用户服务类 - 只负责用户业务逻辑
public class UserService {
private UserRepository userRepository;
private EmailService emailService;
private LogService logService;
public UserService(UserRepository userRepository,
EmailService emailService,
LogService logService) {
this.userRepository = userRepository;
this.emailService = emailService;
this.logService = logService;
}
public void createUser(User user) {
userRepository.save(user);
emailService.sendWelcomeEmail(user);
logService.logUserAction("CREATE", user);
}
public void updateUser(User user) {
userRepository.update(user);
logService.logUserAction("UPDATE", user);
}
public void deleteUser(Long userId) {
userRepository.delete(userId);
logService.logUserAction("DELETE", userId);
}
}
// 🗄️ 数据持久化类 - 只负责数据访问
public class UserRepository {
private DatabaseConnection dbConnection;
public void save(User user) {
// 数据库保存逻辑
}
public void update(User user) {
// 数据库更新逻辑
}
public void delete(Long userId) {
// 数据库删除逻辑
}
public User findById(Long userId) {
// 数据库查询逻辑
return null;
}
}
// 📧 邮件服务类 - 只负责邮件发送
public class EmailService {
public void sendWelcomeEmail(User user) {
// 邮件发送逻辑
}
public void sendPasswordResetEmail(User user) {
// 密码重置邮件逻辑
}
}
// 📝 日志服务类 - 只负责日志记录
public class LogService {
public void logUserAction(String action, Object data) {
// 日志记录逻辑
}
}
2.2 🔓 开闭原则(OCP)- "开放扩展,关闭修改"
2.2.1 定义与理解
定义:软件实体应该对扩展开放,对修改关闭。
核心思想:当需要添加新功能时,应该通过添加新的代码来实现,而不是修改现有的代码。
🎭 生活类比:
- 就像乐高积木,你可以添加新的积木块,但不需要修改现有的积木
- 就像手机APP,可以安装新应用,但不需要修改系统
2.2.2 🚫 违反OCP的示例 - "硬编码噩梦"
scss
// 😰 违反OCP的代码 - 需要修改现有代码来支持新功能
public class ShapeCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
return Math.PI * circle.getRadius() * circle.getRadius();
} else if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
return rectangle.getWidth() * rectangle.getHeight();
} else if (shape instanceof Triangle) {
Triangle triangle = (Triangle) shape;
return 0.5 * triangle.getBase() * triangle.getHeight();
}
return 0;
}
}
2.2.3 ✨ 遵循OCP的重构 - "优雅扩展"
arduino
// 🎯 遵循OCP的设计 - 通过接口实现扩展
public interface Shape {
double calculateArea();
}
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class Triangle implements Shape {
private double base;
private double height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double calculateArea() {
return 0.5 * base * height;
}
}
// 🚀 计算器类不需要修改就能支持新形状
public class ShapeCalculator {
public double calculateArea(Shape shape) {
return shape.calculateArea();
}
public double calculateTotalArea(List<Shape> shapes) {
return shapes.stream()
.mapToDouble(Shape::calculateArea)
.sum();
}
}
// 🎉 添加新形状,只需要实现接口,不需要修改现有代码!
public class Hexagon implements Shape {
private double side;
public Hexagon(double side) {
this.side = side;
}
@Override
public double calculateArea() {
return 3 * Math.sqrt(3) * side * side / 2;
}
}
2.3 🔄 里氏替换原则(LSP)- "子承父业"
2.3.1 定义与理解
定义:子类对象应该能够替换其父类对象,而程序的行为不会发生改变。
核心思想:继承必须确保超类所拥有的性质在子类中仍然成立。
🎭 生活类比:
- 就像电器插座,只要是标准接口,任何品牌的电器都能插上使用
- 就像USB接口,任何USB设备都能在USB接口上工作
2.3.2 🚫 违反LSP的示例 - "继承陷阱"
arduino
// 😰 违反LSP的继承关系
public class Rectangle {
protected double width;
protected double height;
public void setWidth(double width) {
this.width = width;
}
public void setHeight(double height) {
this.height = height;
}
public double getWidth() { return width; }
public double getHeight() { return height; }
public double calculateArea() {
return width * height;
}
}
// 正方形继承矩形 - 违反LSP
public class Square extends Rectangle {
@Override
public void setWidth(double width) {
this.width = width;
this.height = width; // 正方形宽高相等
}
@Override
public void setHeight(double height) {
this.width = height; // 正方形宽高相等
this.height = height;
}
}
// 🧪 测试代码 - 会出现问题
public class LSPViolationDemo {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setWidth(5);
rectangle.setHeight(4);
System.out.println("矩形面积: " + rectangle.calculateArea()); // 20
// 用正方形替换矩形
Rectangle square = new Square();
square.setWidth(5);
square.setHeight(4);
System.out.println("正方形面积: " + square.calculateArea()); // 16,行为改变了!
}
}
2.3.3 ✨ 遵循LSP的重构 - "接口分离"
arduino
// 🎯 遵循LSP的设计 - 使用组合而不是继承
public interface Shape {
double calculateArea();
}
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public void setWidth(double width) {
this.width = width;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class Square implements Shape {
private double side;
public Square(double side) {
this.side = side;
}
public void setSide(double side) {
this.side = side;
}
@Override
public double calculateArea() {
return side * side;
}
}
// 🧪 测试代码 - 行为一致
public class LSPComplianceDemo {
public static void main(String[] args) {
List<Shape> shapes = Arrays.asList(
new Rectangle(5, 4),
new Square(5)
);
for (Shape shape : shapes) {
System.out.println("面积: " + shape.calculateArea());
}
}
}
2.4 🎭 接口隔离原则(ISP)- "小而美"
2.4.1 定义与理解
定义:客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。
核心思想:使用多个专门的接口比使用单个总接口要好。
🎭 生活类比:
- 就像瑞士军刀,虽然功能多,但每个功能都不够专业
- 就像专业工具,每个工具都有专门的用途,用起来更顺手
2.4.2 🚫 违反ISP的示例 - "胖接口"
csharp
// 😰 违反ISP的胖接口
public interface Worker {
void work();
void eat();
void sleep();
void getSalary();
void takeVacation();
void attendMeeting();
void writeCode();
void designArchitecture();
void manageTeam();
}
// 程序员被迫实现不需要的方法
public class Programmer implements Worker {
@Override
public void work() {
System.out.println("编程工作");
}
@Override
public void eat() {
System.out.println("吃饭");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
@Override
public void getSalary() {
System.out.println("领取工资");
}
@Override
public void takeVacation() {
System.out.println("休假");
}
@Override
public void attendMeeting() {
System.out.println("参加会议");
}
@Override
public void writeCode() {
System.out.println("写代码");
}
@Override
public void designArchitecture() {
throw new UnsupportedOperationException("程序员不负责架构设计");
}
@Override
public void manageTeam() {
throw new UnsupportedOperationException("程序员不负责团队管理");
}
}
2.4.3 ✨ 遵循ISP的重构 - "接口分离"
csharp
// 🎯 遵循ISP的接口设计 - 接口分离
public interface Workable {
void work();
}
public interface Eatable {
void eat();
}
public interface Sleepable {
void sleep();
}
public interface Payable {
void getSalary();
}
public interface Vacationable {
void takeVacation();
}
public interface MeetingAttendable {
void attendMeeting();
}
public interface CodeWritable {
void writeCode();
}
public interface ArchitectureDesignable {
void designArchitecture();
}
public interface TeamManageable {
void manageTeam();
}
// 程序员只需要实现相关的接口
public class Programmer implements Workable, Eatable, Sleepable,
Payable, Vacationable, MeetingAttendable,
CodeWritable {
@Override
public void work() {
System.out.println("编程工作");
}
@Override
public void eat() {
System.out.println("吃饭");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
@Override
public void getSalary() {
System.out.println("领取工资");
}
@Override
public void takeVacation() {
System.out.println("休假");
}
@Override
public void attendMeeting() {
System.out.println("参加会议");
}
@Override
public void writeCode() {
System.out.println("写代码");
}
}
// 架构师实现更多接口
public class Architect implements Workable, Eatable, Sleepable,
Payable, Vacationable, MeetingAttendable,
CodeWritable, ArchitectureDesignable {
// 实现所有方法...
}
// 项目经理实现管理相关接口
public class ProjectManager implements Workable, Eatable, Sleepable,
Payable, Vacationable, MeetingAttendable,
TeamManageable {
// 实现相关方法...
}
2.5 🔄 依赖倒置原则(DIP)- "依赖抽象"
2.5.1 定义与理解
定义:
- 高层模块不应该依赖低层模块,两者都应该依赖抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。
核心思想:依赖抽象而不是具体实现。
🎭 生活类比:
- 就像电器插头,不依赖具体的插座品牌,只依赖标准接口
- 就像USB设备,不依赖具体的电脑品牌,只依赖USB标准
2.5.2 🚫 违反DIP的示例 - "硬编码依赖"
csharp
// 😰 违反DIP的代码 - 高层模块依赖低层模块
public class UserService {
private MySQLDatabase database; // 直接依赖具体实现
public UserService() {
this.database = new MySQLDatabase(); // 硬编码依赖
}
public void createUser(User user) {
database.save(user);
}
public User getUser(Long id) {
return database.findById(id);
}
}
2.5.3 ✨ 遵循DIP的重构 - "依赖抽象"
typescript
// 🎯 遵循DIP的设计 - 依赖抽象
public interface UserRepository {
void save(User user);
User findById(Long id);
}
public class MySQLUserRepository implements UserRepository {
@Override
public void save(User user) {
System.out.println("保存用户到MySQL数据库");
}
@Override
public User findById(Long id) {
System.out.println("从MySQL数据库查询用户");
return new User();
}
}
public class OracleUserRepository implements UserRepository {
@Override
public void save(User user) {
System.out.println("保存用户到Oracle数据库");
}
@Override
public User findById(Long id) {
System.out.println("从Oracle数据库查询用户");
return new User();
}
}
// 高层模块依赖抽象
public class UserService {
private UserRepository userRepository; // 依赖抽象
public UserService(UserRepository userRepository) { // 依赖注入
this.userRepository = userRepository;
}
public void createUser(User user) {
userRepository.save(user);
}
public User getUser(Long id) {
return userRepository.findById(id);
}
}
// 🚀 使用示例 - 可以轻松切换不同的实现
public class DIPDemo {
public static void main(String[] args) {
UserRepository mysqlRepo = new MySQLUserRepository();
UserService userService1 = new UserService(mysqlRepo);
UserRepository oracleRepo = new OracleUserRepository();
UserService userService2 = new UserService(oracleRepo);
}
}
🎪 第三部分:SOLID原则的综合应用 - 真实项目实战
3.1 🛒 电商系统设计示例 - 从理论到实践
💡 场景设定:小李现在要开发一个电商系统,他要用SOLID原则来设计一个优雅的订单处理系统。
java
// 🎯 遵循SOLID原则的电商系统设计
public interface OrderRepository {
Order save(Order order);
Order findById(Long id);
List<Order> findByUserId(Long userId);
}
public interface PaymentProcessor {
PaymentResult process(PaymentRequest request);
}
public interface InventoryManager {
boolean reserveItems(List<OrderItem> items);
void releaseItems(List<OrderItem> items);
}
public interface NotificationSender {
void sendOrderConfirmation(Order order);
void sendPaymentConfirmation(Order order);
}
// 🎯 订单服务 - 遵循SRP和DIP
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentProcessor paymentProcessor;
private final InventoryManager inventoryManager;
private final NotificationSender notificationSender;
public OrderService(OrderRepository orderRepository,
PaymentProcessor paymentProcessor,
InventoryManager inventoryManager,
NotificationSender notificationSender) {
this.orderRepository = orderRepository;
this.paymentProcessor = paymentProcessor;
this.inventoryManager = inventoryManager;
this.notificationSender = notificationSender;
}
public Order createOrder(OrderRequest request) {
Order order = new Order(request);
orderRepository.save(order);
if (!inventoryManager.reserveItems(order.getItems())) {
throw new InsufficientInventoryException();
}
PaymentRequest paymentRequest = new PaymentRequest(order);
PaymentResult result = paymentProcessor.process(paymentRequest);
if (result.isSuccess()) {
order.setStatus(OrderStatus.PAID);
orderRepository.save(order);
notificationSender.sendOrderConfirmation(order);
notificationSender.sendPaymentConfirmation(order);
} else {
inventoryManager.releaseItems(order.getItems());
throw new PaymentFailedException(result.getErrorMessage());
}
return order;
}
}
// 🗄️ 具体实现 - 遵循OCP和LSP
@Repository
public class JpaOrderRepository implements OrderRepository {
private final OrderJpaRepository jpaRepository;
public JpaOrderRepository(OrderJpaRepository jpaRepository) {
this.jpaRepository = jpaRepository;
}
@Override
public Order save(Order order) {
return jpaRepository.save(order);
}
@Override
public Order findById(Long id) {
return jpaRepository.findById(id).orElse(null);
}
@Override
public List<Order> findByUserId(Long userId) {
return jpaRepository.findByUserId(userId);
}
}
@Service
public class AlipayPaymentProcessor implements PaymentProcessor {
@Override
public PaymentResult process(PaymentRequest request) {
// 支付宝支付逻辑
return new PaymentResult(true, "支付成功");
}
}
@Service
public class EmailNotificationSender implements NotificationSender {
@Override
public void sendOrderConfirmation(Order order) {
// 发送订单确认邮件
}
@Override
public void sendPaymentConfirmation(Order order) {
// 发送支付确认邮件
}
}
3.2 🎭 设计模式与SOLID原则的结合 - "招式"与"心法"的完美融合
typescript
// 🎯 策略模式 + DIP - 折扣计算
public interface DiscountStrategy {
double calculateDiscount(Order order);
}
public class VIPDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(Order order) {
return order.getTotalAmount() * 0.1; // VIP 10%折扣
}
}
public class SeasonalDiscountStrategy implements DiscountStrategy {
@Override
public double calculateDiscount(Order order) {
return order.getTotalAmount() * 0.05; // 季节性5%折扣
}
}
// 🏭 工厂模式 + OCP - 支付处理器工厂
public interface PaymentProcessorFactory {
PaymentProcessor createProcessor(String type);
}
public class PaymentProcessorFactoryImpl implements PaymentProcessorFactory {
@Override
public PaymentProcessor createProcessor(String type) {
switch (type) {
case "alipay":
return new AlipayPaymentProcessor();
case "wechat":
return new WechatPaymentProcessor();
case "bank":
return new BankPaymentProcessor();
default:
throw new IllegalArgumentException("不支持的支付类型");
}
}
}
// 👀 观察者模式 + ISP - 订单事件监听
public interface OrderEventListener {
void onOrderCreated(Order order);
void onOrderPaid(Order order);
void onOrderCancelled(Order order);
}
public class InventoryEventListener implements OrderEventListener {
@Override
public void onOrderCreated(Order order) {
// 处理库存相关逻辑
}
@Override
public void onOrderPaid(Order order) {
// 处理库存相关逻辑
}
@Override
public void onOrderCancelled(Order order) {
// 处理库存相关逻辑
}
}
public class NotificationEventListener implements OrderEventListener {
@Override
public void onOrderCreated(Order order) {
// 发送通知
}
@Override
public void onOrderPaid(Order order) {
// 发送通知
}
@Override
public void onOrderCancelled(Order order) {
// 发送通知
}
}
🎉 总结:从小白到大神的修炼之路
🏆 设计模式的价值:
- 🎯 提供解决方案:为常见设计问题提供标准化解决方案
- ✨ 提高代码质量:使代码更加清晰、可维护
- 🤝 促进团队协作:统一的语言和模式便于团队沟通
- ⚡ 提高开发效率:避免重复造轮子
🎯 SOLID原则的价值:
- 🔧 提高可维护性:清晰的代码结构,易于理解和修改
- 🚀 提高可扩展性:遵循开闭原则,易于添加新功能
- 🧪 提高可测试性:职责分离,便于单元测试
- 🎭 提高灵活性:依赖抽象而不是具体实现
📚 实践建议:
- 🧠 理解原理:不要死记硬背,要理解每个原则和模式的核心思想
- ⚖️ 适度使用:不是所有地方都需要使用设计模式,避免过度设计
- 🎭 结合场景:根据具体业务场景选择合适的设计模式
- 🔄 持续改进:在实际项目中不断实践和改进
🗺️ 学习路径建议 - 从小白到大神的修炼计划
🥉 初级阶段(入门)
目标 :理解基本概念,掌握常用模式 时间:2-3个月
必学设计模式 :单例模式、观察者模式、策略模式、工厂方法模式、装饰器模式 必学SOLID原则:单一职责原则(SRP)、开闭原则(OCP)
🥈 中级阶段(进阶)
目标 :深入理解,熟练应用 时间:3-6个月
进阶设计模式 :适配器模式、代理模式、模板方法模式、状态模式、抽象工厂模式 进阶SOLID原则:里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)
🥇 高级阶段(精通)
目标 :灵活运用,创新应用 时间:6-12个月
高级设计模式 :桥接模式、组合模式、命令模式、责任链模式、访问者模式 实战应用:框架开发、架构设计、重构实践
🏆 大师阶段(创新)
目标 :创造新的设计模式,指导他人 时间:持续学习
高级技能:模式组合、模式创新、知识传播、代码审查
📖 推荐学习资源
📚 经典书籍
- 《设计模式:可复用面向对象软件的基础》- GoF四人帮著
- 《Head First设计模式》- 通俗易懂的入门书
- 《重构:改善既有代码的设计》- Martin Fowler著
- 《代码整洁之道》- Robert C. Martin著
🌐 在线资源
- GitHub - Design Patterns - 开源设计模式项目集合
- Stack Overflow - Design Patterns - 设计模式相关问题讨论
- Refactoring Guru - 设计模式图解教程(英文)
- 菜鸟教程 - 设计模式 - 中文设计模式教程
- Java设计模式 - Java设计模式详细教程
- YouTube - Design Patterns Playlist - 设计模式视频教程
- Spring Framework 官方文档 - Spring框架中的设计模式应用
🛠️ 实践工具
- IntelliJ IDEA - 强大的Java IDE,内置重构工具
- SonarQube - 代码质量分析工具
- Draw.io - 免费的UML图表绘制工具
- JUnit - Java单元测试框架
- Mockito - Java Mock测试框架
- PlantUML - 文本生成UML图表的工具
🎬 小李的成长故事结局:
💡 故事结尾:经过一段时间的学习和实践,小李的代码质量得到了显著提升。他的代码不再是"乱糟糟的毛坯房",而是变成了"精装修的豪宅"。同事们都说:"小李的代码写得真优雅!"小李笑着说:"这都是设计模式和SOLID原则的功劳!"
🎯 记住:设计模式和SOLID原则不是目的,而是手段。我们的目标是写出优雅、可维护、可扩展的代码。就像武林高手,招式是基础,心法是根本,两者结合才能成为真正的"代码大师"!
通过深入理解设计模式和SOLID原则,我们可以编写出更加优雅、可维护的代码,为项目的长期发展奠定良好的基础。让我们一起在编程的道路上不断修炼,成为真正的"代码艺术家"! 🎨✨
本文使用 markdown.com.cn 排版