OOP 与设计
面向对象编程(OOP)与设计模式是构建可维护、可扩展系统的关键。本文档系统介绍 SOLID 设计原则、23 种设计模式以及面向对象编程思想,包含详细讲解、代码示例和实践案例。
📋 目录结构
🎯 一、设计原则
设计原则是指导软件设计的基本原则,是编写高质量代码的基础。
1.1 SOLID 原则
SOLID 是面向对象设计的五大基本原则。
1.1.1 单一职责原则(SRP)
定义: 一个类应该只有一个引起它变化的原因。
原则解析:
违反单一职责的示例:
// ❌ 不好的设计 - 一个类承担多个职责
public class User {
private String name;
private String email;
// 职责1:用户数据管理
public void setName(String name) { }
public void setEmail(String email) { }
// 职责2:数据验证
public boolean validateEmail(String email) { }
// 职责3:数据持久化
public void save() {
// 保存到数据库
}
// 职责4:发送邮件
public void sendEmail(String subject, String content) {
// 发送邮件
}
}遵循单一职责的示例:
// ✅ 好的设计 - 职责分离
// 职责1:用户数据模型
public class User {
private String name;
private String email;
public void setName(String name) { }
public void setEmail(String email) { }
// getters...
}
// 职责2:数据验证
public class UserValidator {
public boolean validateEmail(String email) {
// 邮箱验证逻辑
return email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
public boolean validateUser(User user) {
// 用户验证逻辑
return validateEmail(user.getEmail());
}
}
// 职责3:数据持久化
public class UserRepository {
public void save(User user) {
// 保存到数据库
}
public User findById(Long id) {
// 从数据库查询
return null;
}
}
// 职责4:邮件服务
public class EmailService {
public void sendEmail(String to, String subject, String content) {
// 发送邮件
}
}1.1.2 开闭原则(OCP)
定义: 软件实体应该对扩展开放,对修改关闭。
原则解析:
违反开闭原则的示例:
// ❌ 不好的设计 - 添加新功能需要修改现有代码
public class AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Rectangle) {
Rectangle rect = (Rectangle) shape;
return rect.getWidth() * rect.getHeight();
} else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
return Math.PI * circle.getRadius() * circle.getRadius();
}
// 添加新图形需要修改这里
return 0;
}
}遵循开闭原则的示例:
// ✅ 好的设计 - 通过扩展添加新功能
// 定义抽象接口
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;
}
@Override
public double calculateArea() {
return width * height;
}
}
// 圆形实现
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 AreaCalculator {
public double calculateArea(Shape shape) {
return shape.calculateArea(); // 无需修改,只需扩展
}
}
// 添加新图形 - 只需实现接口,无需修改现有代码
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;
}
}1.1.3 里氏替换原则(LSP)
定义: 子类对象应该能够替换其父类对象,而不影响程序的正确性。
原则解析:
违反里氏替换原则的示例:
// ❌ 不好的设计 - 子类不能完全替换父类
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; // 违反里氏替换原则
}
}
// 使用时会出问题
public void test(Rectangle rect) {
rect.setWidth(5);
rect.setHeight(4);
// 期望面积为 20,但如果传入 Square,面积为 16
assert rect.getArea() == 20; // 可能失败
}遵循里氏替换原则的示例:
// ✅ 好的设计 - 子类完全替换父类
abstract class Shape {
public abstract int getArea();
}
class Rectangle extends Shape {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public int getArea() {
return width * height;
}
}
class Square extends Shape {
private int side;
public Square(int side) {
this.side = side;
}
@Override
public int getArea() {
return side * side;
}
}
// 任何子类都可以替换父类
public void test(Shape shape) {
int area = shape.getArea(); // 无论传入 Rectangle 还是 Square 都能正确工作
}1.1.4 接口隔离原则(ISP)
定义: 客户端不应该依赖它不需要的接口。
原则解析:
违反接口隔离原则的示例:
// ❌ 不好的设计 - 接口太大
public interface Worker {
void work();
void eat();
void sleep();
}
// 机器人只需要工作,不需要吃饭睡觉
public class Robot implements Worker {
@Override
public void work() {
// 工作
}
@Override
public void eat() {
// 机器人不需要吃饭 - 违反接口隔离原则
throw new UnsupportedOperationException("Robot doesn't eat");
}
@Override
public void sleep() {
// 机器人不需要睡觉 - 违反接口隔离原则
throw new UnsupportedOperationException("Robot doesn't sleep");
}
}遵循接口隔离原则的示例:
// ✅ 好的设计 - 接口隔离
public interface Workable {
void work();
}
public interface Eatable {
void eat();
}
public interface Sleepable {
void sleep();
}
// 人类实现所有接口
public class Human implements Workable, Eatable, Sleepable {
@Override
public void work() { }
@Override
public void eat() { }
@Override
public void sleep() { }
}
// 机器人只实现需要的接口
public class Robot implements Workable {
@Override
public void work() { }
}1.1.5 依赖倒置原则(DIP)
定义: 高层模块不应该依赖低层模块,两者都应该依赖抽象。
原则解析:
违反依赖倒置原则的示例:
// ❌ 不好的设计 - 高层模块依赖低层模块
// 低层模块
public class MySQLDatabase {
public void save(String data) {
// 保存到 MySQL
}
}
// 高层模块直接依赖低层模块
public class UserService {
private MySQLDatabase database = new MySQLDatabase(); // 违反依赖倒置原则
public void saveUser(User user) {
database.save(user.toString());
}
}遵循依赖倒置原则的示例:
// ✅ 好的设计 - 依赖抽象
// 抽象接口
public interface Database {
void save(String data);
}
// 低层模块实现抽象接口
public class MySQLDatabase implements Database {
@Override
public void save(String data) {
// 保存到 MySQL
}
}
public class PostgreSQLDatabase implements Database {
@Override
public void save(String data) {
// 保存到 PostgreSQL
}
}
// 高层模块依赖抽象接口
public class UserService {
private Database database; // 依赖抽象,不依赖具体实现
public UserService(Database database) {
this.database = database;
}
public void saveUser(User user) {
database.save(user.toString());
}
}1.2 DRY 原则
定义: Don't Repeat Yourself - 不要重复自己。
实践示例:
// ❌ 违反 DRY 原则
public class UserService {
public void createUser(User user) {
// 验证逻辑
if (user.getEmail() == null || !user.getEmail().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email");
}
// 保存逻辑...
}
public void updateUser(User user) {
// 重复的验证逻辑
if (user.getEmail() == null || !user.getEmail().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
throw new IllegalArgumentException("Invalid email");
}
// 更新逻辑...
}
}
// ✅ 遵循 DRY 原则
public class UserValidator {
private static final String EMAIL_PATTERN = "^[A-Za-z0-9+_.-]+@(.+)$";
public void validateEmail(String email) {
if (email == null || !email.matches(EMAIL_PATTERN)) {
throw new IllegalArgumentException("Invalid email");
}
}
}
public class UserService {
private UserValidator validator = new UserValidator();
public void createUser(User user) {
validator.validateEmail(user.getEmail()); // 复用验证逻辑
// 保存逻辑...
}
public void updateUser(User user) {
validator.validateEmail(user.getEmail()); // 复用验证逻辑
// 更新逻辑...
}
}🎨 二、设计模式
设计模式是解决常见设计问题的可复用方案,是架构师必须掌握的核心技能。本节详细介绍23种设计模式,包含模式结构、时序图、应用场景和实际案例。
2.1 创建型模式
创建型模式关注对象的创建过程,提供灵活的对象创建机制。
创建型模式分类:
2.1.1 单例模式(Singleton)
定义: 确保一个类只有一个实例,并提供一个全局访问点。
模式结构:
模式说明:
实现方式对比:
| 实现方式 | 优点 | 缺点 | 线程安全 | 适用场景 |
|---|---|---|---|---|
| 饿汉式 | 简单、线程安全 | 提前加载、浪费内存 | ✅ | 资源占用小 |
| 懒汉式 | 延迟加载 | 需同步、性能稍差 | ✅(需同步) | 资源占用大 |
| 双重检查 | 性能好、线程安全 | 实现复杂 | ✅ | 推荐使用 |
| 枚举 | 最安全、简洁 | 不灵活 | ✅ | 最佳实践 |
实现方式详解:
1. 饿汉式单例(Eager Initialization)
/**
* 饿汉式单例
* 优点:简单、线程安全
* 缺点:类加载时就创建实例,可能造成资源浪费
*/
public class EagerSingleton {
// 类加载时就创建实例
private static final EagerSingleton instance = new EagerSingleton();
// 私有构造函数,防止外部创建实例
private EagerSingleton() {
System.out.println("EagerSingleton instance created");
}
// 全局访问点
public static EagerSingleton getInstance() {
return instance;
}
public void doSomething() {
System.out.println("Doing something...");
}
}2. 懒汉式单例(Lazy Initialization)
/**
* 懒汉式单例(线程不安全版本)
* 优点:延迟加载、节省资源
* 缺点:多线程环境下不安全
*/
public class LazySingletonUnsafe {
private static LazySingletonUnsafe instance;
private LazySingletonUnsafe() { }
// ❌ 线程不安全:多线程可能创建多个实例
public static LazySingletonUnsafe getInstance() {
if (instance == null) {
instance = new LazySingletonUnsafe();
}
return instance;
}
}
/**
* 懒汉式单例(同步方法版本)
* 优点:线程安全
* 缺点:每次访问都需要同步,性能差
*/
public class LazySingletonSynchronized {
private static LazySingletonSynchronized instance;
private LazySingletonSynchronized() { }
// ✅ 线程安全,但性能较差
public static synchronized LazySingletonSynchronized getInstance() {
if (instance == null) {
instance = new LazySingletonSynchronized();
}
return instance;
}
}3. 双重检查锁定(Double-Checked Locking)
/**
* 双重检查锁定单例(推荐)
* 优点:线程安全、性能好、延迟加载
* 缺点:实现稍复杂
*/
public class DoubleCheckedSingleton {
// 使用 volatile 保证可见性和有序性
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {
System.out.println("DoubleCheckedSingleton instance created");
}
public static DoubleCheckedSingleton getInstance() {
// 第一次检查:避免不必要的同步
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
// 第二次检查:确保只创建一个实例
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
public void doSomething() {
System.out.println("Doing something...");
}
}4. 枚举单例(Enum Singleton)- 最佳实践
/**
* 枚举单例(推荐,Java最佳实践)
* 优点:
* - 线程安全(JVM保证)
* - 序列化安全
* - 反射安全
* - 代码简洁
* 缺点:不够灵活(不能继承其他类)
*/
public enum EnumSingleton {
INSTANCE; // 唯一的实例
private String name;
// 枚举构造函数(私有)
EnumSingleton() {
this.name = "EnumSingleton";
System.out.println("EnumSingleton instance created");
}
public void doSomething() {
System.out.println("Doing something with " + name);
}
public void setName(String name) {
this.name = name;
}
}
// 使用
EnumSingleton singleton = EnumSingleton.INSTANCE;
singleton.doSomething();5. 静态内部类单例(Static Inner Class)
/**
* 静态内部类单例(推荐)
* 优点:
* - 延迟加载(调用getInstance时才加载)
* - 线程安全(JVM保证类加载的线程安全)
* - 实现简单
*/
public class StaticInnerClassSingleton {
private StaticInnerClassSingleton() {
System.out.println("StaticInnerClassSingleton instance created");
}
// 静态内部类
private static class SingletonHolder {
// 在内部类中创建实例
private static final StaticInnerClassSingleton instance =
new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
// 首次调用时才加载SingletonHolder,创建实例
return SingletonHolder.instance;
}
public void doSomething() {
System.out.println("Doing something...");
}
}应用场景:
- 配置管理器(全局唯一配置)
- 日志记录器(统一日志输出)
- 数据库连接池(共享连接池)
- 缓存管理器(全局缓存)
实际案例:
// 配置管理器单例
public enum ConfigManager {
INSTANCE;
private Properties config = new Properties();
ConfigManager() {
loadConfig();
}
private void loadConfig() {
try (InputStream is = getClass().getResourceAsStream("/config.properties")) {
config.load(is);
} catch (IOException e) {
throw new RuntimeException("Failed to load config", e);
}
}
public String getProperty(String key) {
return config.getProperty(key);
}
public String getProperty(String key, String defaultValue) {
return config.getProperty(key, defaultValue);
}
}
// 使用
String dbUrl = ConfigManager.INSTANCE.getProperty("db.url");注意事项:
- 单例模式会隐藏类之间的依赖关系
- 单例对象生命周期较长,可能导致资源泄漏
- 单例模式难以进行单元测试(难以mock)
- 多线程环境下要特别注意线程安全
2.1.2 工厂模式(Factory Method)
定义: 定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类中进行。
模式结构:
时序图:
完整实现示例:
/**
* 产品接口
*/
public interface Shape {
void draw();
double getArea();
double getPerimeter();
}
/**
* 具体产品:圆形
*/
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("Drawing Circle with radius: " + radius);
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * 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 void draw() {
System.out.println("Drawing Rectangle: " + width + " x " + height);
}
@Override
public double getArea() {
return width * height;
}
@Override
public double getPerimeter() {
return 2 * (width + height);
}
}
/**
* 抽象工厂(创建者)
*/
public abstract class ShapeFactory {
/**
* 工厂方法:由子类实现具体创建逻辑
*/
public abstract Shape createShape(double... params);
/**
* 模板方法:定义使用产品的流程
*/
public void processShape() {
// 创建产品
Shape shape = createShape();
// 使用产品
shape.draw();
System.out.println("Area: " + shape.getArea());
System.out.println("Perimeter: " + shape.getPerimeter());
}
/**
* 便捷方法:创建默认参数的图形
*/
protected abstract Shape createShape();
}
/**
* 具体工厂:圆形工厂
*/
public class CircleFactory extends ShapeFactory {
@Override
public Shape createShape(double... params) {
if (params.length > 0) {
return new Circle(params[0]);
}
return new Circle(1.0); // 默认半径
}
@Override
protected Shape createShape() {
return new Circle(5.0); // 默认半径5
}
}
/**
* 具体工厂:矩形工厂
*/
public class RectangleFactory extends ShapeFactory {
@Override
public Shape createShape(double... params) {
if (params.length >= 2) {
return new Rectangle(params[0], params[1]);
}
return new Rectangle(1.0, 1.0); // 默认1x1
}
@Override
protected Shape createShape() {
return new Rectangle(4.0, 6.0); // 默认4x6
}
}
// 使用示例
public class FactoryMethodDemo {
public static void main(String[] args) {
// 使用圆形工厂
ShapeFactory circleFactory = new CircleFactory();
circleFactory.processShape();
System.out.println("---");
// 使用矩形工厂
ShapeFactory rectangleFactory = new RectangleFactory();
rectangleFactory.processShape();
// 直接创建特定类型
Shape circle = circleFactory.createShape(10.0);
circle.draw();
}
}实际应用案例:数据库连接工厂
/**
* 数据库连接接口
*/
public interface DatabaseConnection {
void connect();
void execute(String sql);
void close();
boolean isConnected();
}
/**
* MySQL 连接实现
*/
public class MySQLConnection implements DatabaseConnection {
private String host;
private int port;
private String database;
private boolean connected = false;
public MySQLConnection(String host, int port, String database) {
this.host = host;
this.port = port;
this.database = database;
}
@Override
public void connect() {
System.out.println("Connecting to MySQL: " + host + ":" + port + "/" + database);
// 实际的连接逻辑...
this.connected = true;
}
@Override
public void execute(String sql) {
if (!connected) {
throw new IllegalStateException("Not connected to database");
}
System.out.println("Executing SQL on MySQL: " + sql);
}
@Override
public void close() {
System.out.println("Closing MySQL connection");
this.connected = false;
}
@Override
public boolean isConnected() {
return connected;
}
}
/**
* PostgreSQL 连接实现
*/
public class PostgreSQLConnection implements DatabaseConnection {
private String host;
private int port;
private String database;
private boolean connected = false;
public PostgreSQLConnection(String host, int port, String database) {
this.host = host;
this.port = port;
this.database = database;
}
@Override
public void connect() {
System.out.println("Connecting to PostgreSQL: " + host + ":" + port + "/" + database);
// 实际的连接逻辑...
this.connected = true;
}
@Override
public void execute(String sql) {
if (!connected) {
throw new IllegalStateException("Not connected to database");
}
System.out.println("Executing SQL on PostgreSQL: " + sql);
}
@Override
public void close() {
System.out.println("Closing PostgreSQL connection");
this.connected = false;
}
@Override
public boolean isConnected() {
return connected;
}
}
/**
* 数据库连接工厂接口
*/
public abstract class DatabaseConnectionFactory {
/**
* 工厂方法:创建数据库连接
*/
public abstract DatabaseConnection createConnection();
/**
* 模板方法:获取并返回连接
*/
public DatabaseConnection getConnection() {
DatabaseConnection connection = createConnection();
connection.connect();
return connection;
}
}
/**
* MySQL 连接工厂
*/
public class MySQLConnectionFactory extends DatabaseConnectionFactory {
private String host;
private int port;
private String database;
public MySQLConnectionFactory(String host, int port, String database) {
this.host = host;
this.port = port;
this.database = database;
}
@Override
public DatabaseConnection createConnection() {
return new MySQLConnection(host, port, database);
}
}
/**
* PostgreSQL 连接工厂
*/
public class PostgreSQLConnectionFactory extends DatabaseConnectionFactory {
private String host;
private int port;
private String database;
public PostgreSQLConnectionFactory(String host, int port, String database) {
this.host = host;
this.port = port;
this.database = database;
}
@Override
public DatabaseConnection createConnection() {
return new PostgreSQLConnection(host, port, database);
}
}
// 使用
public class DatabaseDemo {
public static void main(String[] args) {
// 创建MySQL工厂
DatabaseConnectionFactory mysqlFactory =
new MySQLConnectionFactory("localhost", 3306, "mydb");
DatabaseConnection mysqlConn = mysqlFactory.getConnection();
mysqlConn.execute("SELECT * FROM users");
mysqlConn.close();
// 创建PostgreSQL工厂
DatabaseConnectionFactory pgFactory =
new PostgreSQLConnectionFactory("localhost", 5432, "mydb");
DatabaseConnection pgConn = pgFactory.getConnection();
pgConn.execute("SELECT * FROM users");
pgConn.close();
}
}工厂模式的优势:
- ✅ 解耦:客户端不需要知道具体的产品类
- ✅ 扩展性好:添加新产品只需添加新的工厂类
- ✅ 符合开闭原则:对扩展开放,对修改关闭
工厂模式的缺点:
- ❌ 增加类的数量:每个产品都需要对应的工厂类
- ❌ 增加了系统的复杂度
2.1.3 建造者模式(Builder)
定义: 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
模式结构:
时序图:
传统建造者模式示例:
/**
* 产品:电脑
*/
public class Computer {
private String cpu;
private String memory;
private String storage;
private String graphicsCard;
private String motherboard;
// 私有构造函数,只能通过Builder构建
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.storage = builder.storage;
this.graphicsCard = builder.graphicsCard;
this.motherboard = builder.motherboard;
}
// Getters...
public String getCpu() { return cpu; }
public String getMemory() { return memory; }
public String getStorage() { return storage; }
public String getGraphicsCard() { return graphicsCard; }
public String getMotherboard() { return motherboard; }
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", storage='" + storage + '\'' +
", graphicsCard='" + graphicsCard + '\'' +
", motherboard='" + motherboard + '\'' +
'}';
}
/**
* 建造者
*/
public static class Builder {
private String cpu;
private String memory;
private String storage;
private String graphicsCard;
private String motherboard;
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder memory(String memory) {
this.memory = memory;
return this;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Builder graphicsCard(String graphicsCard) {
this.graphicsCard = graphicsCard;
return this;
}
public Builder motherboard(String motherboard) {
this.motherboard = motherboard;
return this;
}
public Computer build() {
// 可以在这里进行参数验证
validate();
return new Computer(this);
}
private void validate() {
if (cpu == null) {
throw new IllegalArgumentException("CPU is required");
}
if (memory == null) {
throw new IllegalArgumentException("Memory is required");
}
}
}
}
// 使用
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.memory("16GB DDR4")
.storage("512GB SSD")
.graphicsCard("NVIDIA RTX 3080")
.motherboard("ASUS Z590")
.build();
System.out.println(computer);简化版建造者模式(推荐):
/**
* 简化版建造者模式:链式调用
* 适用于:参数较多、可选参数多、需要验证参数
*/
public class User {
private final String name; // 必填
private final String email; // 必填
private final int age; // 必填
private final String phone; // 可选
private final String address; // 可选
private final String bio; // 可选
private User(Builder builder) {
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
this.bio = builder.bio;
}
// Getters...
public static class Builder {
private final String name; // 必填
private final String email; // 必填
private final int age; // 必填
private String phone; // 可选
private String address; // 可选
private String bio; // 可选
// 必填参数通过构造函数传入
public Builder(String name, String email, int age) {
this.name = name;
this.email = email;
this.age = age;
}
// 可选参数通过链式方法设置
public Builder phone(String phone) {
this.phone = phone;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder bio(String bio) {
this.bio = bio;
return this;
}
public User build() {
validate();
return new User(this);
}
private void validate() {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("Name is required");
}
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Valid email is required");
}
if (age < 0 || age > 150) {
throw new IllegalArgumentException("Valid age is required");
}
}
}
}
// 使用示例
User user1 = new User.Builder("John", "john@example.com", 30)
.phone("1234567890")
.address("123 Main St")
.bio("Software Engineer")
.build();
User user2 = new User.Builder("Alice", "alice@example.com", 25)
.phone("9876543210")
.build(); // 只设置必填和部分可选参数实际应用案例:HTTP 请求构建器
/**
* HTTP 请求构建器
*/
public class HttpRequest {
private final String method;
private final String url;
private final Map<String, String> headers;
private final Map<String, String> queryParams;
private final String body;
private final int timeout;
private HttpRequest(Builder builder) {
this.method = builder.method;
this.url = builder.url;
this.headers = new HashMap<>(builder.headers);
this.queryParams = new HashMap<>(builder.queryParams);
this.body = builder.body;
this.timeout = builder.timeout;
}
public static class Builder {
private String method = "GET";
private String url;
private Map<String, String> headers = new HashMap<>();
private Map<String, String> queryParams = new HashMap<>();
private String body;
private int timeout = 5000; // 默认5秒
public Builder url(String url) {
this.url = url;
return this;
}
public Builder method(String method) {
this.method = method.toUpperCase();
return this;
}
public Builder header(String key, String value) {
this.headers.put(key, value);
return this;
}
public Builder headers(Map<String, String> headers) {
this.headers.putAll(headers);
return this;
}
public Builder queryParam(String key, String value) {
this.queryParams.put(key, value);
return this;
}
public Builder queryParams(Map<String, String> params) {
this.queryParams.putAll(params);
return this;
}
public Builder body(String body) {
this.body = body;
return this;
}
public Builder timeout(int timeout) {
this.timeout = timeout;
return this;
}
public HttpRequest build() {
if (url == null || url.trim().isEmpty()) {
throw new IllegalArgumentException("URL is required");
}
return new HttpRequest(this);
}
}
// 执行请求
public HttpResponse execute() {
// 实际的HTTP请求逻辑
System.out.println("Executing " + method + " " + url);
System.out.println("Headers: " + headers);
System.out.println("Query Params: " + queryParams);
if (body != null) {
System.out.println("Body: " + body);
}
System.out.println("Timeout: " + timeout + "ms");
// 返回模拟响应
return new HttpResponse(200, "OK", "{}");
}
}
// 使用示例
HttpRequest request = new HttpRequest.Builder()
.url("https://api.example.com/users")
.method("POST")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer token123")
.queryParam("page", "1")
.queryParam("limit", "10")
.body("{\"name\":\"John\"}")
.timeout(10000)
.build();
HttpResponse response = request.execute();建造者模式的优势:
- ✅ 参数设置灵活,支持链式调用
- ✅ 可以设置默认值
- ✅ 参数验证集中管理
- ✅ 可以创建不可变对象
- ✅ 代码可读性好
建造者模式的缺点:
- ❌ 代码量增加(需要Builder类)
- ❌ 对于简单对象可能过度设计
2.2 结构型模式
结构型模式关注类和对象的组合,通过组合来获得更强大的功能。
结构型模式分类:
2.2.1 适配器模式(Adapter)
定义: 将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。
模式结构:
时序图:
适配器模式的三种形式:
1. 类适配器(继承实现)
/**
* 目标接口:期望的接口
*/
public interface MediaPlayer {
void play(String audioType, String fileName);
}
/**
* 被适配的类:不兼容的接口
*/
public class AdvancedMediaPlayer {
public void playVlc(String fileName) {
System.out.println("Playing vlc file: " + fileName);
}
public void playMp4(String fileName) {
System.out.println("Playing mp4 file: " + fileName);
}
}
/**
* 类适配器:通过继承实现适配
*/
public class MediaAdapter extends AdvancedMediaPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
playMp4(fileName);
} else {
System.out.println("Unsupported audio type: " + audioType);
}
}
}2. 对象适配器(组合实现)- 推荐
/**
* 目标接口
*/
public interface MediaPlayer {
void play(String audioType, String fileName);
}
/**
* 被适配的类
*/
public class VlcPlayer {
public void playVlc(String fileName) {
System.out.println("Playing vlc file: " + fileName);
}
}
public class Mp4Player {
public void playMp4(String fileName) {
System.out.println("Playing mp4 file: " + fileName);
}
}
/**
* 对象适配器:通过组合实现适配(推荐)
*/
public class MediaAdapter implements MediaPlayer {
private VlcPlayer vlcPlayer;
private Mp4Player mp4Player;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
vlcPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
mp4Player = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
vlcPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
mp4Player.playMp4(fileName);
} else {
System.out.println("Unsupported audio type: " + audioType);
}
}
}
/**
* 客户端:使用目标接口
*/
public class AudioPlayer implements MediaPlayer {
private MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// 内置支持 mp3
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing mp3 file: " + fileName);
}
// 使用适配器支持其他格式
else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("Invalid audio type: " + audioType);
}
}
}
// 使用
AudioPlayer player = new AudioPlayer();
player.play("mp3", "song.mp3");
player.play("mp4", "movie.mp4");
player.play("vlc", "video.vlc");实际应用案例:第三方支付接口适配
/**
* 目标接口:统一的支付接口
*/
public interface PaymentGateway {
void pay(BigDecimal amount, String orderId);
void refund(String orderId);
PaymentStatus getStatus(String orderId);
}
/**
* 支付宝支付(被适配的类)
*/
public class AlipayService {
public void alipayPayment(BigDecimal amount, String orderId) {
System.out.println("支付宝支付: 订单=" + orderId + ", 金额=" + amount);
// 实际的支付宝支付逻辑...
}
public void alipayRefund(String orderId) {
System.out.println("支付宝退款: 订单=" + orderId);
// 实际的支付宝退款逻辑...
}
public String alipayQueryStatus(String orderId) {
System.out.println("支付宝查询状态: 订单=" + orderId);
// 实际的查询逻辑...
return "SUCCESS";
}
}
/**
* 微信支付(被适配的类)
*/
public class WechatPayService {
public void wechatPayment(BigDecimal amount, String orderId) {
System.out.println("微信支付: 订单=" + orderId + ", 金额=" + amount);
// 实际的微信支付逻辑...
}
public void wechatRefund(String orderId) {
System.out.println("微信退款: 订单=" + orderId);
// 实际的微信退款逻辑...
}
public int wechatQueryStatus(String orderId) {
System.out.println("微信查询状态: 订单=" + orderId);
// 实际的查询逻辑...
return 1; // 1表示成功
}
}
/**
* 支付宝适配器
*/
public class AlipayAdapter implements PaymentGateway {
private AlipayService alipayService;
public AlipayAdapter(AlipayService alipayService) {
this.alipayService = alipayService;
}
@Override
public void pay(BigDecimal amount, String orderId) {
alipayService.alipayPayment(amount, orderId);
}
@Override
public void refund(String orderId) {
alipayService.alipayRefund(orderId);
}
@Override
public PaymentStatus getStatus(String orderId) {
String status = alipayService.alipayQueryStatus(orderId);
// 将支付宝的状态转换为统一的PaymentStatus
return "SUCCESS".equals(status) ? PaymentStatus.SUCCESS : PaymentStatus.FAILED;
}
}
/**
* 微信支付适配器
*/
public class WechatPayAdapter implements PaymentGateway {
private WechatPayService wechatPayService;
public WechatPayAdapter(WechatPayService wechatPayService) {
this.wechatPayService = wechatPayService;
}
@Override
public void pay(BigDecimal amount, String orderId) {
wechatPayService.wechatPayment(amount, orderId);
}
@Override
public void refund(String orderId) {
wechatPayService.wechatRefund(orderId);
}
@Override
public PaymentStatus getStatus(String orderId) {
int status = wechatPayService.wechatQueryStatus(orderId);
// 将微信的状态转换为统一的PaymentStatus
return status == 1 ? PaymentStatus.SUCCESS : PaymentStatus.FAILED;
}
}
// 统一的状态枚举
public enum PaymentStatus {
SUCCESS, FAILED, PENDING
}
// 使用
public class PaymentService {
private PaymentGateway paymentGateway;
public PaymentService(PaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
public void processPayment(BigDecimal amount, String orderId) {
paymentGateway.pay(amount, orderId);
}
public void processRefund(String orderId) {
paymentGateway.refund(orderId);
}
}
// 客户端代码
public class PaymentDemo {
public static void main(String[] args) {
// 使用支付宝
AlipayService alipayService = new AlipayService();
PaymentGateway alipayGateway = new AlipayAdapter(alipayService);
PaymentService paymentService = new PaymentService(alipayGateway);
paymentService.processPayment(new BigDecimal("100.00"), "ORDER001");
// 使用微信支付 - 不需要修改PaymentService代码
WechatPayService wechatPayService = new WechatPayService();
PaymentGateway wechatGateway = new WechatPayAdapter(wechatPayService);
PaymentService wechatPaymentService = new PaymentService(wechatGateway);
wechatPaymentService.processPayment(new BigDecimal("200.00"), "ORDER002");
}
}适配器模式的优势:
- ✅ 可以让不兼容的接口协同工作
- ✅ 提高了类的复用性
- ✅ 增加了类的透明性
- ✅ 符合开闭原则(可以添加新的适配器)
适配器模式的缺点:
- ❌ 增加了代码的复杂度
- ❌ 适配器链过长会影响性能
2.2.2 装饰器模式(Decorator)
定义: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。
模式结构:
时序图:
咖啡装饰器完整示例:
/**
* 组件接口:咖啡
*/
public interface Coffee {
double getCost();
String getDescription();
}
/**
* 具体组件:基础咖啡
*/
public class SimpleCoffee implements Coffee {
@Override
public double getCost() {
return 2.0; // 基础咖啡 2元
}
@Override
public String getDescription() {
return "Simple Coffee";
}
}
/**
* 装饰器抽象类
*/
public 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(); // 默认不改变描述
}
}
/**
* 具体装饰器:牛奶
*/
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return coffee.getCost() + 0.5; // 加牛奶 +0.5元
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Milk";
}
}
/**
* 具体装饰器:糖
*/
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return coffee.getCost() + 0.3; // 加糖 +0.3元
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Sugar";
}
}
/**
* 具体装饰器:奶油
*/
public class CreamDecorator extends CoffeeDecorator {
public CreamDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return coffee.getCost() + 0.8; // 加奶油 +0.8元
}
@Override
public String getDescription() {
return coffee.getDescription() + ", Cream";
}
}
// 使用示例
public class CoffeeShop {
public static void main(String[] args) {
// 基础咖啡
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + " - Cost: $" + coffee.getCost());
// 输出: Simple Coffee - Cost: $2.0
// 加牛奶
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " - Cost: $" + coffee.getCost());
// 输出: Simple Coffee, Milk - Cost: $2.5
// 再加糖
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " - Cost: $" + coffee.getCost());
// 输出: Simple Coffee, Milk, Sugar - Cost: $2.8
// 再加奶油
coffee = new CreamDecorator(coffee);
System.out.println(coffee.getDescription() + " - Cost: $" + coffee.getCost());
// 输出: Simple Coffee, Milk, Sugar, Cream - Cost: $3.6
// 可以任意组合装饰器
Coffee fancyCoffee = new CreamDecorator(
new SugarDecorator(
new MilkDecorator(
new SimpleCoffee()
)
)
);
System.out.println("Fancy: " + fancyCoffee.getDescription() + " - Cost: $" + fancyCoffee.getCost());
}
}实际应用案例:Java IO 流中的装饰器模式
/**
* Java IO 流就是装饰器模式的典型应用
* InputStream 是抽象组件
* FileInputStream 是具体组件
* BufferedInputStream、DataInputStream 等是装饰器
*/
// Java标准库示例(模拟)
public abstract class InputStream {
public abstract int read();
public void close() { }
}
public class FileInputStream extends InputStream {
private String fileName;
public FileInputStream(String fileName) {
this.fileName = fileName;
}
@Override
public int read() {
System.out.println("Reading from file: " + fileName);
return 0;
}
}
public class BufferedInputStream extends InputStream {
private InputStream inputStream;
private byte[] buffer = new byte[8192];
public BufferedInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() {
// 使用缓冲区读取,提高性能
System.out.println("Reading from buffer");
return inputStream.read();
}
}
public class DataInputStream extends InputStream {
private InputStream inputStream;
public DataInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() {
// 读取基本数据类型
System.out.println("Reading data type");
return inputStream.read();
}
public int readInt() {
// 读取整数
return 0;
}
}
// 使用装饰器模式组合功能
InputStream fileStream = new FileInputStream("data.txt");
InputStream bufferedStream = new BufferedInputStream(fileStream); // 添加缓冲功能
InputStream dataStream = new DataInputStream(bufferedStream); // 添加数据类型读取功能实际应用案例:Web 请求装饰器
/**
* HTTP请求处理接口
*/
public interface HttpRequestHandler {
HttpResponse handle(HttpRequest request);
}
/**
* 基础请求处理器
*/
public class BasicHttpRequestHandler implements HttpRequestHandler {
@Override
public HttpResponse handle(HttpRequest request) {
System.out.println("Processing request: " + request.getUrl());
return new HttpResponse(200, "OK", "Response body");
}
}
/**
* 请求处理装饰器基类
*/
public abstract class HttpRequestHandlerDecorator implements HttpRequestHandler {
protected HttpRequestHandler handler;
public HttpRequestHandlerDecorator(HttpRequestHandler handler) {
this.handler = handler;
}
@Override
public HttpResponse handle(HttpRequest request) {
return handler.handle(request);
}
}
/**
* 日志装饰器:添加日志功能
*/
public class LoggingDecorator extends HttpRequestHandlerDecorator {
private static final Logger logger = LoggerFactory.getLogger(LoggingDecorator.class);
public LoggingDecorator(HttpRequestHandler handler) {
super(handler);
}
@Override
public HttpResponse handle(HttpRequest request) {
logger.info("Request received: {} {}", request.getMethod(), request.getUrl());
long startTime = System.currentTimeMillis();
HttpResponse response = handler.handle(request);
long duration = System.currentTimeMillis() - startTime;
logger.info("Request processed in {}ms, status: {}", duration, response.getStatus());
return response;
}
}
/**
* 认证装饰器:添加认证功能
*/
public class AuthenticationDecorator extends HttpRequestHandlerDecorator {
public AuthenticationDecorator(HttpRequestHandler handler) {
super(handler);
}
@Override
public HttpResponse handle(HttpRequest request) {
String token = request.getHeader("Authorization");
if (token == null || !isValidToken(token)) {
return new HttpResponse(401, "Unauthorized", "Invalid or missing token");
}
return handler.handle(request);
}
private boolean isValidToken(String token) {
// 验证token逻辑
return token.startsWith("Bearer ");
}
}
/**
* 缓存装饰器:添加缓存功能
*/
public class CachingDecorator extends HttpRequestHandlerDecorator {
private Map<String, HttpResponse> cache = new HashMap<>();
public CachingDecorator(HttpRequestHandler handler) {
super(handler);
}
@Override
public HttpResponse handle(HttpRequest request) {
// 只缓存GET请求
if (!"GET".equals(request.getMethod())) {
return handler.handle(request);
}
String cacheKey = request.getUrl();
HttpResponse cachedResponse = cache.get(cacheKey);
if (cachedResponse != null) {
System.out.println("Returning cached response for: " + cacheKey);
return cachedResponse;
}
HttpResponse response = handler.handle(request);
// 只缓存成功的响应
if (response.getStatus() == 200) {
cache.put(cacheKey, response);
}
return response;
}
}
// 使用:可以任意组合装饰器
HttpRequestHandler handler = new BasicHttpRequestHandler();
handler = new LoggingDecorator(handler); // 添加日志
handler = new AuthenticationDecorator(handler); // 添加认证
handler = new CachingDecorator(handler); // 添加缓存
// 处理请求
HttpRequest request = new HttpRequest("GET", "/api/users");
HttpResponse response = handler.handle(request);装饰器模式 vs 继承:
装饰器模式的优势:
- ✅ 比继承更灵活,可以在运行时动态组合
- ✅ 遵循开闭原则,可以添加新装饰器而不修改现有代码
- ✅ 可以任意组合多个装饰器
- ✅ 装饰器可以独立使用
装饰器模式的缺点:
- ❌ 会产生很多小对象
- ❌ 装饰器链过长会影响性能
- ❌ 调试比较困难(多层包装)
2.3 行为型模式
行为型模式关注对象之间的通信和责任分配。
行为型模式分类:
2.3.1 观察者模式(Observer)
定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
模式结构:
时序图:
观察者模式完整实现:
/**
* 观察者接口
*/
public interface Observer {
/**
* 当主题状态改变时,观察者会收到通知
* @param event 事件对象,包含状态变化的信息
*/
void update(Event event);
}
/**
* 主题接口(被观察者)
*/
public interface Subject {
/**
* 添加观察者
*/
void attach(Observer observer);
/**
* 移除观察者
*/
void detach(Observer observer);
/**
* 通知所有观察者
*/
void notifyObservers();
/**
* 获取状态
*/
Object getState();
}
/**
* 事件对象:封装状态变化的信息
*/
public class Event {
private String type;
private Object data;
private long timestamp;
public Event(String type, Object data) {
this.type = type;
this.data = data;
this.timestamp = System.currentTimeMillis();
}
// Getters...
public String getType() { return type; }
public Object getData() { return data; }
public long getTimestamp() { return timestamp; }
}
/**
* 具体主题:新闻发布者
*/
public class NewsPublisher implements Subject {
private List<Observer> observers = new ArrayList<>();
private String news;
@Override
public void attach(Observer observer) {
if (!observers.contains(observer)) {
observers.add(observer);
System.out.println("Observer attached: " + observer.getClass().getSimpleName());
}
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
System.out.println("Observer detached: " + observer.getClass().getSimpleName());
}
@Override
public void notifyObservers() {
Event event = new Event("NEWS_UPDATE", news);
for (Observer observer : observers) {
observer.update(event);
}
}
@Override
public Object getState() {
return news;
}
/**
* 发布新闻,会自动通知所有观察者
*/
public void publishNews(String news) {
this.news = news;
System.out.println("Publishing news: " + news);
notifyObservers();
}
}
/**
* 具体观察者:邮件订阅者
*/
public class EmailSubscriber implements Observer {
private String email;
private List<String> receivedNews = new ArrayList<>();
public EmailSubscriber(String email) {
this.email = email;
}
@Override
public void update(Event event) {
String news = (String) event.getData();
receivedNews.add(news);
System.out.println("Email sent to " + email + ": " + news);
// 实际的邮件发送逻辑...
}
public List<String> getReceivedNews() {
return new ArrayList<>(receivedNews);
}
}
/**
* 具体观察者:短信订阅者
*/
public class SMSSubscriber implements Observer {
private String phoneNumber;
public SMSSubscriber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Override
public void update(Event event) {
String news = (String) event.getData();
System.out.println("SMS sent to " + phoneNumber + ": " + news);
// 实际的短信发送逻辑...
}
}
/**
* 具体观察者:推送通知订阅者
*/
public class PushNotificationSubscriber implements Observer {
private String deviceId;
public PushNotificationSubscriber(String deviceId) {
this.deviceId = deviceId;
}
@Override
public void update(Event event) {
String news = (String) event.getData();
System.out.println("Push notification sent to device " + deviceId + ": " + news);
// 实际的推送逻辑...
}
}
// 使用示例
public class ObserverDemo {
public static void main(String[] args) {
// 创建主题
NewsPublisher publisher = new NewsPublisher();
// 创建观察者
Observer emailSubscriber = new EmailSubscriber("user1@example.com");
Observer smsSubscriber = new SMSSubscriber("13800138000");
Observer pushSubscriber = new PushNotificationSubscriber("device123");
// 注册观察者
publisher.attach(emailSubscriber);
publisher.attach(smsSubscriber);
publisher.attach(pushSubscriber);
// 发布新闻,所有观察者都会收到通知
publisher.publishNews("Breaking News: Technology Update!");
System.out.println("---");
// 移除一个观察者
publisher.detach(smsSubscriber);
// 再次发布新闻,只有剩余的观察者收到通知
publisher.publishNews("Latest News: Market Update!");
}
}实际应用案例:订单状态通知系统
/**
* 订单状态枚举
*/
public enum OrderStatus {
PENDING, // 待处理
CONFIRMED, // 已确认
SHIPPED, // 已发货
DELIVERED, // 已送达
CANCELLED // 已取消
}
/**
* 订单事件
*/
public class OrderEvent extends Event {
private String orderId;
private OrderStatus oldStatus;
private OrderStatus newStatus;
public OrderEvent(String orderId, OrderStatus oldStatus, OrderStatus newStatus) {
super("ORDER_STATUS_CHANGED", newStatus);
this.orderId = orderId;
this.oldStatus = oldStatus;
this.newStatus = newStatus;
}
// Getters...
}
/**
* 订单(主题)
*/
public class Order implements Subject {
private String orderId;
private OrderStatus status;
private List<Observer> observers = new ArrayList<>();
public Order(String orderId) {
this.orderId = orderId;
this.status = OrderStatus.PENDING;
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
Event event = new OrderEvent(orderId, null, status);
for (Observer observer : observers) {
observer.update(event);
}
}
@Override
public Object getState() {
return status;
}
public void setStatus(OrderStatus newStatus) {
OrderStatus oldStatus = this.status;
this.status = newStatus;
System.out.println("Order " + orderId + " status changed: " + oldStatus + " -> " + newStatus);
notifyObservers(); // 状态改变时通知所有观察者
}
public String getOrderId() {
return orderId;
}
public OrderStatus getStatus() {
return status;
}
}
/**
* 邮件通知观察者
*/
public class EmailNotificationObserver implements Observer {
private String email;
public EmailNotificationObserver(String email) {
this.email = email;
}
@Override
public void update(Event event) {
if (event instanceof OrderEvent) {
OrderEvent orderEvent = (OrderEvent) event;
String message = String.format(
"Order %s status changed to %s",
orderEvent.getOrderId(),
orderEvent.getNewStatus()
);
sendEmail(email, "Order Status Update", message);
}
}
private void sendEmail(String to, String subject, String body) {
System.out.println("Sending email to " + to);
System.out.println("Subject: " + subject);
System.out.println("Body: " + body);
}
}
/**
* 短信通知观察者
*/
public class SMSNotificationObserver implements Observer {
private String phoneNumber;
public SMSNotificationObserver(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Override
public void update(Event event) {
if (event instanceof OrderEvent) {
OrderEvent orderEvent = (OrderEvent) event;
String message = String.format(
"Your order %s is now %s",
orderEvent.getOrderId(),
orderEvent.getNewStatus()
);
sendSMS(phoneNumber, message);
}
}
private void sendSMS(String to, String message) {
System.out.println("Sending SMS to " + to + ": " + message);
}
}
/**
* 库存管理观察者
*/
public class InventoryObserver implements Observer {
@Override
public void update(Event event) {
if (event instanceof OrderEvent) {
OrderEvent orderEvent = (OrderEvent) event;
// 订单确认时,扣减库存
if (orderEvent.getNewStatus() == OrderStatus.CONFIRMED) {
System.out.println("Deducting inventory for order: " + orderEvent.getOrderId());
}
// 订单取消时,恢复库存
if (orderEvent.getNewStatus() == OrderStatus.CANCELLED) {
System.out.println("Restoring inventory for order: " + orderEvent.getOrderId());
}
}
}
}
// 使用
public class OrderSystem {
public static void main(String[] args) {
// 创建订单
Order order = new Order("ORDER001");
// 创建观察者
Observer emailObserver = new EmailNotificationObserver("customer@example.com");
Observer smsObserver = new SMSNotificationObserver("13800138000");
Observer inventoryObserver = new InventoryObserver();
// 注册观察者
order.attach(emailObserver);
order.attach(smsObserver);
order.attach(inventoryObserver);
// 订单状态变化,所有观察者都会收到通知
order.setStatus(OrderStatus.CONFIRMED);
// 输出:
// Order ORDER001 status changed: PENDING -> CONFIRMED
// Sending email to customer@example.com
// Sending SMS to 13800138000
// Deducting inventory for order: ORDER001
order.setStatus(OrderStatus.SHIPPED);
// 输出:
// Order ORDER001 status changed: CONFIRMED -> SHIPPED
// Sending email to customer@example.com
// Sending SMS to 13800138000
order.setStatus(OrderStatus.DELIVERED);
// ...
}
}观察者模式 vs 发布订阅模式:
观察者模式的优势:
- ✅ 主题和观察者之间松耦合
- ✅ 支持广播通信
- ✅ 符合开闭原则(可以添加新观察者)
- ✅ 可以动态添加和删除观察者
观察者模式的缺点:
- ❌ 如果观察者很多,通知会花费很长时间
- ❌ 观察者之间如果有循环依赖,可能导致循环调用
- ❌ 观察者不知道其他观察者的存在
2.3.2 策略模式(Strategy)
定义: 定义一系列算法,把它们封装起来,并且使它们可以互换。策略模式让算法的变化独立于使用算法的客户端。
模式结构:
时序图:
策略模式完整实现:
/**
* 策略接口:支付策略
*/
public interface PaymentStrategy {
/**
* 支付方法
* @param amount 支付金额
* @return 支付结果
*/
PaymentResult pay(BigDecimal amount);
/**
* 获取支付方式名称
*/
String getPaymentMethod();
}
/**
* 支付结果
*/
public class PaymentResult {
private boolean success;
private String transactionId;
private String message;
public PaymentResult(boolean success, String transactionId, String message) {
this.success = success;
this.transactionId = transactionId;
this.message = message;
}
// Getters...
public boolean isSuccess() { return success; }
public String getTransactionId() { return transactionId; }
public String getMessage() { return message; }
}
/**
* 具体策略:信用卡支付
*/
public class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String cardHolder;
private String expiryDate;
private String cvv;
public CreditCardPayment(String cardNumber, String cardHolder, String expiryDate, String cvv) {
this.cardNumber = cardNumber;
this.cardHolder = cardHolder;
this.expiryDate = expiryDate;
this.cvv = cvv;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("Processing credit card payment...");
System.out.println("Card Number: " + maskCardNumber(cardNumber));
System.out.println("Card Holder: " + cardHolder);
System.out.println("Amount: " + amount);
// 实际的支付处理逻辑...
// 模拟支付处理
boolean success = processPayment(amount);
if (success) {
String transactionId = generateTransactionId();
return new PaymentResult(true, transactionId, "Credit card payment successful");
} else {
return new PaymentResult(false, null, "Credit card payment failed");
}
}
@Override
public String getPaymentMethod() {
return "Credit Card";
}
private boolean processPayment(BigDecimal amount) {
// 实际的支付处理逻辑
return true; // 模拟成功
}
private String generateTransactionId() {
return "CC-" + System.currentTimeMillis();
}
private String maskCardNumber(String cardNumber) {
if (cardNumber.length() > 4) {
return "****-****-****-" + cardNumber.substring(cardNumber.length() - 4);
}
return cardNumber;
}
}
/**
* 具体策略:PayPal支付
*/
public class PayPalPayment implements PaymentStrategy {
private String email;
private String password;
public PayPalPayment(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("Processing PayPal payment...");
System.out.println("Email: " + email);
System.out.println("Amount: " + amount);
// 实际的PayPal支付处理逻辑...
boolean success = processPayPalPayment(email, password, amount);
if (success) {
String transactionId = generateTransactionId();
return new PaymentResult(true, transactionId, "PayPal payment successful");
} else {
return new PaymentResult(false, null, "PayPal payment failed");
}
}
@Override
public String getPaymentMethod() {
return "PayPal";
}
private boolean processPayPalPayment(String email, String password, BigDecimal amount) {
// 实际的PayPal支付处理逻辑
return true; // 模拟成功
}
private String generateTransactionId() {
return "PP-" + System.currentTimeMillis();
}
}
/**
* 具体策略:支付宝支付
*/
public class AlipayPayment implements PaymentStrategy {
private String account;
public AlipayPayment(String account) {
this.account = account;
}
@Override
public PaymentResult pay(BigDecimal amount) {
System.out.println("Processing Alipay payment...");
System.out.println("Account: " + account);
System.out.println("Amount: " + amount);
// 实际的支付宝支付处理逻辑...
boolean success = processAlipayPayment(account, amount);
if (success) {
String transactionId = generateTransactionId();
return new PaymentResult(true, transactionId, "Alipay payment successful");
} else {
return new PaymentResult(false, null, "Alipay payment failed");
}
}
@Override
public String getPaymentMethod() {
return "Alipay";
}
private boolean processAlipayPayment(String account, BigDecimal amount) {
// 实际的支付宝支付处理逻辑
return true; // 模拟成功
}
private String generateTransactionId() {
return "AL-" + System.currentTimeMillis();
}
}
/**
* 上下文:购物车
*/
public class ShoppingCart {
private List<CartItem> items = new ArrayList<>();
private PaymentStrategy paymentStrategy;
public void addItem(CartItem item) {
items.add(item);
}
public void removeItem(CartItem item) {
items.remove(item);
}
public BigDecimal getTotal() {
return items.stream()
.map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public PaymentResult checkout() {
BigDecimal total = getTotal();
if (total.compareTo(BigDecimal.ZERO) <= 0) {
return new PaymentResult(false, null, "Cart is empty");
}
if (paymentStrategy == null) {
return new PaymentResult(false, null, "Payment strategy not set");
}
System.out.println("Total amount: " + total);
System.out.println("Payment method: " + paymentStrategy.getPaymentMethod());
return paymentStrategy.pay(total);
}
public List<CartItem> getItems() {
return new ArrayList<>(items);
}
}
// 使用示例
public class StrategyDemo {
public static void main(String[] args) {
// 创建购物车
ShoppingCart cart = new ShoppingCart();
cart.addItem(new CartItem("Item1", new BigDecimal("50.00"), 2));
cart.addItem(new CartItem("Item2", new BigDecimal("30.00"), 1));
// 使用信用卡支付
PaymentStrategy creditCardStrategy = new CreditCardPayment(
"1234-5678-9012-3456",
"John Doe",
"12/25",
"123"
);
cart.setPaymentStrategy(creditCardStrategy);
PaymentResult result1 = cart.checkout();
System.out.println("Result: " + result1.isSuccess() + " - " + result1.getMessage());
System.out.println("---");
// 切换支付方式:使用PayPal
PaymentStrategy payPalStrategy = new PayPalPayment(
"user@example.com",
"password123"
);
cart.setPaymentStrategy(payPalStrategy);
PaymentResult result2 = cart.checkout();
System.out.println("Result: " + result2.isSuccess() + " - " + result2.getMessage());
System.out.println("---");
// 切换支付方式:使用支付宝
PaymentStrategy alipayStrategy = new AlipayPayment("13800138000");
cart.setPaymentStrategy(alipayStrategy);
PaymentResult result3 = cart.checkout();
System.out.println("Result: " + result3.isSuccess() + " - " + result3.getMessage());
}
}实际应用案例:排序算法策略
/**
* 排序策略接口
*/
public interface SortStrategy<T extends Comparable<T>> {
void sort(List<T> list);
String getAlgorithmName();
}
/**
* 快速排序策略
*/
public class QuickSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
@Override
public void sort(List<T> list) {
System.out.println("Sorting using Quick Sort");
quickSort(list, 0, list.size() - 1);
}
@Override
public String getAlgorithmName() {
return "Quick Sort";
}
private void quickSort(List<T> list, int low, int high) {
if (low < high) {
int pivotIndex = partition(list, low, high);
quickSort(list, low, pivotIndex - 1);
quickSort(list, pivotIndex + 1, high);
}
}
private int partition(List<T> list, int low, int high) {
T pivot = list.get(high);
int i = low - 1;
for (int j = low; j < high; j++) {
if (list.get(j).compareTo(pivot) < 0) {
i++;
swap(list, i, j);
}
}
swap(list, i + 1, high);
return i + 1;
}
private void swap(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
/**
* 归并排序策略
*/
public class MergeSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
@Override
public void sort(List<T> list) {
System.out.println("Sorting using Merge Sort");
mergeSort(list, 0, list.size() - 1);
}
@Override
public String getAlgorithmName() {
return "Merge Sort";
}
private void mergeSort(List<T> list, int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
mergeSort(list, left, mid);
mergeSort(list, mid + 1, right);
merge(list, left, mid, right);
}
}
private void merge(List<T> list, int left, int mid, int right) {
// 合并逻辑
}
}
/**
* 冒泡排序策略
*/
public class BubbleSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
@Override
public void sort(List<T> list) {
System.out.println("Sorting using Bubble Sort");
int n = list.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (list.get(j).compareTo(list.get(j + 1)) > 0) {
swap(list, j, j + 1);
}
}
}
}
@Override
public String getAlgorithmName() {
return "Bubble Sort";
}
private void swap(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
/**
* 排序上下文
*/
public class Sorter<T extends Comparable<T>> {
private SortStrategy<T> strategy;
public Sorter(SortStrategy<T> strategy) {
this.strategy = strategy;
}
public void setStrategy(SortStrategy<T> strategy) {
this.strategy = strategy;
}
public void sort(List<T> list) {
long startTime = System.currentTimeMillis();
System.out.println("Using algorithm: " + strategy.getAlgorithmName());
strategy.sort(list);
long duration = System.currentTimeMillis() - startTime;
System.out.println("Sort completed in " + duration + "ms");
}
}
// 使用示例
public class SortDemo {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(64, 34, 25, 12, 22, 11, 90);
// 使用快速排序
Sorter<Integer> sorter = new Sorter<>(new QuickSortStrategy<>());
sorter.sort(new ArrayList<>(numbers));
// 输出: [11, 12, 22, 25, 34, 64, 90]
// 切换策略:使用归并排序
sorter.setStrategy(new MergeSortStrategy<>());
sorter.sort(new ArrayList<>(numbers));
// 切换策略:使用冒泡排序
sorter.setStrategy(new BubbleSortStrategy<>());
sorter.sort(new ArrayList<>(numbers));
}
}策略模式 vs if-else:
策略模式的优势:
- ✅ 算法可以自由切换
- ✅ 避免使用多重条件判断(if-else)
- ✅ 扩展性好,添加新策略很容易
- ✅ 符合开闭原则
策略模式的缺点:
- ❌ 客户端必须知道所有的策略类
- ❌ 策略类数量会增加
- ❌ 所有策略类都需要对外暴露
📊 设计模式总结
2.4 设计模式选择指南
选择设计模式的决策树:
2.5 常用设计模式对比
| 模式 | 类型 | 解决的问题 | 关键点 |
|---|---|---|---|
| 单例 | 创建型 | 确保唯一实例 | 私有构造函数 |
| 工厂 | 创建型 | 统一创建接口 | 抽象工厂方法 |
| 建造者 | 创建型 | 复杂对象构建 | 链式调用 |
| 适配器 | 结构型 | 接口不兼容 | 适配类 |
| 装饰器 | 结构型 | 动态添加功能 | 组合代替继承 |
| 观察者 | 行为型 | 一对多依赖 | 事件通知 |
| 策略 | 行为型 | 算法切换 | 封装算法 |
📝 总结
设计模式是解决常见设计问题的可复用方案,是架构师必须掌握的核心技能。
学习建议
- 理解原则:深入理解 SOLID 等设计原则
- 掌握模式:掌握常用设计模式并理解适用场景
- 实践应用:在项目中应用设计模式和原则
- 持续学习:关注新的设计模式和最佳实践
能力自检清单
- [ ] 理解并能够应用 SOLID 设计原则
- [ ] 掌握单例、工厂、建造者等创建型模式
- [ ] 掌握适配器、装饰器、代理等结构型模式
- [ ] 掌握观察者、策略、命令等行为型模式
- [ ] 能够在项目中识别和应用合适的设计模式
- [ ] 能够权衡设计模式的利弊,避免过度设计
上一章节:理论知识
下一章节:存储与数据库
返回目录:技术能力 | 架构师能力图谱
🎯 三、面向对象
面向对象编程的四大特性。
3.1 封装(Encapsulation)
定义: 隐藏对象的内部实现细节,只暴露必要的接口。
示例:
public class BankAccount {
private double balance; // 私有字段,外部无法直接访问
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
public double getBalance() {
return balance; // 只提供只读访问
}
}3.2 继承(Inheritance)
定义: 子类继承父类的属性和方法。
示例:
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void bark() {
System.out.println(name + " is barking");
}
}3.3 多态(Polymorphism)
定义: 同一个接口,不同的实现。
示例:
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;
}
}
// 多态使用
List<Shape> shapes = Arrays.asList(
new Circle(5),
new Rectangle(4, 6)
);
for (Shape shape : shapes) {
System.out.println(shape.calculateArea()); // 运行时多态
}3.4 抽象(Abstraction)
定义: 定义抽象接口,隐藏具体实现。
示例:
// 抽象类
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
// 抽象方法,子类必须实现
public abstract void makeSound();
// 具体方法,子类可以继承
public void sleep() {
System.out.println(name + " is sleeping");
}
}
// 具体实现
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " barks");
}
}📝 总结
OOP 与设计是架构师的核心能力,需要通过持续学习和实践不断提升。
学习路径
- 理解原则:深入理解 SOLID 等设计原则
- 掌握模式:掌握常用设计模式并灵活应用
- 实践应用:在项目中应用设计模式和原则