23 种设计模式可以分为 三大类, 分别是 创建型、结构型、行为型。
1)创建型模式(Creational Patterns):
用于创建对象的模式,同时隐藏对象创建的逻辑,避免代码中出现大量new操作和复杂的创建逻辑。目的是解耦对象的创建和使用。
- 常用的有:单例模式、工厂模式、建造者模式。
- 不常见的有:原型模式。
2)结构型模式(Structural Patterns):
用于处理对象组合的结构,关注类与对象的组合。目的是通过组合对象或类的方式,形成更大的结构。
- 常用的有:适配器模式、桥接模式、组合模式、装饰器模式、代理模式。
- 不常见的有:外观模式(门面模式)、享元模式。
3)行为型模式(Behavioral Patterns):
用于定义对象如何相互协作以完成单个对象无法单独实现的任务,目的是定义类和对象间的通信方式。
- 常用的有:观察者模式、责任链模式、策略模式、模板模式、状态模式、迭代器模式。
- 不常见的有:备忘录模式、命令模式、中介者模式、访问者模式、解释器模式。
创建型模式:
单例模式
业务场景:数据库连接池、线程池
特点:
1、唯一性:类的实例在整个程序生命周期内只存在一个。
2、全局访问:提供一个全局访问点,让所有代码可以访问同一个实例。
3、延迟加载:可以延迟实例化,在需要时才创建实例(如使用懒汉式实现)。
示例:多种单例实现
- 饿汉式:简单安全但可能浪费资源
- 双重检查锁:延迟加载且线程安全
- 静态内部类:推荐的标准实现方式
- 枚举实现:最安全的实现(防止反射和序列化攻击)
import java.io.Serializable;
/**
* 单例模式多种实现方式演示
*/
public class SingletonDemo {
//------------------------- 饿汉式 -------------------------
/**
* 饿汉式(线程安全,类加载时初始化)
* 优点:实现简单,线程安全
* 缺点:可能造成资源浪费(如果实例未被使用)
*/
static class EagerSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {
// 防止反射创建实例
if (INSTANCE != null) {
throw new IllegalStateException("单例实例已存在");
}
}
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
//------------------------- 懒汉式(双重检查锁) -------------------------
/**
* 双重检查锁(DCL)实现(延迟加载,线程安全)
* 优点:延迟初始化,节省资源
* 注意:需要volatile防止指令重排序
*/
static class LazySingleton {
private static volatile LazySingleton INSTANCE;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (INSTANCE == null) {
synchronized (LazySingleton.class) {
if (INSTANCE == null) {
INSTANCE = new LazySingleton();
}
}
}
return INSTANCE;
}
}
//------------------------- 静态内部类 -------------------------
/**
* 静态内部类实现(推荐方式)
* 优点:兼顾线程安全和延迟加载
* 原理:利用类加载机制保证线程安全
*/
static class InnerClassSingleton {
private InnerClassSingleton() {}
private static class Holder {
static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance() {
return Holder.INSTANCE;
}
}
//------------------------- 枚举实现(最佳实践) -------------------------
/**
* 枚举实现(Effective Java推荐方式)
* 优点:防止反射攻击,自动处理序列化
* 缺点:无法延迟初始化
*/
enum EnumSingleton {
INSTANCE;
public void doSomething() {
System.out.println("枚举单例方法执行");
}
}
//------------------------- 防止序列化破坏的单例 -------------------------
/**
* 可序列化的安全单例
* 注意:需要添加readResolve方法防止反序列化创建新实例
*/
static class SerializableSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private static final SerializableSingleton INSTANCE = new SerializableSingleton();
private SerializableSingleton() {}
public static SerializableSingleton getInstance() {
return INSTANCE;
}
// 关键方法:防止反序列化创建新实例
private Object readResolve() {
return INSTANCE;
}
}
//------------------------- 测试代码 -------------------------
public static void main(String[] args) {
// 测试饿汉式
EagerSingleton eager1 = EagerSingleton.getInstance();
EagerSingleton eager2 = EagerSingleton.getInstance();
System.out.println("饿汉式单例测试: " + (eager1 == eager2)); // true
// 测试双重检查锁
LazySingleton lazy1 = LazySingleton.getInstance();
LazySingleton lazy2 = LazySingleton.getInstance();
System.out.println("双重检查锁测试: " + (lazy1 == lazy2)); // true
// 测试静态内部类
InnerClassSingleton inner1 = InnerClassSingleton.getInstance();
InnerClassSingleton inner2 = InnerClassSingleton.getInstance();
System.out.println("静态内部类测试: " + (inner1 == inner2)); // true
// 测试枚举单例
EnumSingleton.INSTANCE.doSomething();
System.out.println("枚举单例测试: " + (EnumSingleton.INSTANCE == EnumSingleton.INSTANCE)); // true
// 测试序列化安全单例
SerializableSingleton serial1 = SerializableSingleton.getInstance();
SerializableSingleton serial2 = SerializableSingleton.getInstance();
System.out.println("序列化安全测试: " + (serial1 == serial2)); // true
}
}
示例:数据库连接池:
在项目中,数据库连接池通常只需要一个实例来管理所有的数据库连接,避免频繁创建和销毁连接。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ConnectionPool {
private static final int POOL_SIZE = 10;
private static ConnectionPool instance;
private List<Connection> connectionPool;
private ConnectionPool() {
connectionPool = new ArrayList<>(POOL_SIZE);
initializePool();
}
public static synchronized ConnectionPool getInstance() {
if (instance == null) {
instance = new ConnectionPool();
}
return instance;
}
private void initializePool() {
for (int i = 0; i < POOL_SIZE; i++) {
try {
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
connectionPool.add(connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public synchronized Connection getConnection() {
if (connectionPool.isEmpty()) {
throw new RuntimeException("No available connections in the pool");
}
return connectionPool.remove(connectionPool.size() - 1);
}
/**
* 将连接归还到连接池中
* @param connection 当前连接
*/
public synchronized void releaseConnection(Connection connection) {
connectionPool.add(connection);
}
}
工厂方法模式
业务场景:日志记录器
示例:日志记录器
此实现遵循开闭原则(对扩展开放,对修改关闭),能够很好地应对日志记录需求的变化。
// 步骤1:定义日志记录器接口
interface Logger {
/**
* 记录日志的方法
* @param message 要记录的日志信息
*/
void log(String message);
}
// 步骤2:实现具体日志记录器
class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("文件日志记录: " + message);
}
}
class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("数据库日志记录: " + message);
}
}
class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("控制台日志记录: " + message);
}
}
// 步骤3:定义日志记录器工厂接口
interface LoggerFactory {
/**
* 创建日志记录器的工厂方法
* @return 具体的日志记录器实例
*/
Logger createLogger();
}
// 步骤4:实现具体工厂类
class FileLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
// 可以在此处添加文件日志记录器特有的初始化逻辑
return new FileLogger();
}
}
class DatabaseLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
// 可以在此处添加数据库连接等初始化逻辑
return new DatabaseLogger();
}
}
class ConsoleLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
// 控制台记录器通常不需要特殊初始化
return new ConsoleLogger();
}
}
// 步骤5:客户端使用示例
public class LoggerClient {
public static void main(String[] args) {
// 使用文件日志工厂
LoggerFactory fileFactory = new FileLoggerFactory();
Logger fileLogger = fileFactory.createLogger();
fileLogger.log("这是一个测试日志");
// 使用数据库日志工厂
LoggerFactory dbFactory = new DatabaseLoggerFactory();
Logger dbLogger = dbFactory.createLogger();
dbLogger.log("用户登录成功");
// 使用控制台日志工厂
LoggerFactory consoleFactory = new ConsoleLoggerFactory();
Logger consoleLogger = consoleFactory.createLogger();
consoleLogger.log("系统启动完成");
}
}
文件日志记录: 这是一个测试日志
数据库日志记录: 用户登录成功
控制台日志记录: 系统启动完成
建造者模式
业务场景:复杂对象的构造(HTML文档生成器)、链式调用(构建一个 HTTP 请求对象)
示例:HTML文档生成器
当对象的构造过程非常复杂,包含多个步骤或参数时,建造者模式可以帮助简化构造逻辑。
import java.util.ArrayList;
import java.util.List;
/**
* 产品类:HTML文档
*/
class HtmlDocument {
private String headTitle; // 头部标题
private List<String> bodyElements = new ArrayList<>(); // 主体元素集合
/**
* 添加头部标题
* @param title 标题文本
*/
public void setHeadTitle(String title) {
this.headTitle = title;
}
/**
* 向主体添加元素
* @param element HTML元素字符串
*/
public void addBodyElement(String element) {
bodyElements.add(element);
}
/**
* 生成完整HTML文档字符串
* @return 格式化后的HTML内容
*/
public String generate() {
StringBuilder sb = new StringBuilder();
sb.append("<html>\n");
sb.append("<head>\n");
sb.append("<title>").append(headTitle).append("</title>\n");
sb.append("</head>\n");
sb.append("<body>\n");
for (String element : bodyElements) {
sb.append(" ").append(element).append("\n");
}
sb.append("</body>\n");
sb.append("</html>");
return sb.toString();
}
}
/**
* 抽象建造者接口
*/
interface HtmlBuilder {
// 构建头部
void buildHeader(String title);
// 构建正文段落
void addParagraph(String text);
// 构建无序列表
void addUnorderedList(List<String> items);
// 构建水平线
void addHorizontalRule();
// 获取生成结果
HtmlDocument getResult();
}
/**
* 具体建造者:HTML文档生成器
*/
class HtmlDocumentBuilder implements HtmlBuilder {
private HtmlDocument document = new HtmlDocument();
@Override
public void buildHeader(String title) {
document.setHeadTitle(title);
}
@Override
public void addParagraph(String text) {
String element = "<p>" + text + "</p>";
document.addBodyElement(element);
}
@Override
public void addUnorderedList(List<String> items) {
StringBuilder sb = new StringBuilder("<ul>\n");
for (String item : items) {
sb.append(" <li>").append(item).append("</li>\n");
}
sb.append("</ul>");
document.addBodyElement(sb.toString());
}
@Override
public void addHorizontalRule() {
document.addBodyElement("<hr/>");
}
@Override
public HtmlDocument getResult() {
return document;
}
}
/**
* 指挥者(可选):封装常用构建流程
*/
class DocumentDirector {
public HtmlDocument buildReportDocument(HtmlBuilder builder) {
builder.buildHeader("销售报告");
builder.addParagraph("2025年度销售汇总:");
List<String> data = List.of("第一季度:¥1,200万",
"第二季度:¥1,500万",
"第三季度:¥1,800万");
builder.addUnorderedList(data);
builder.addHorizontalRule();
builder.addParagraph("数据截止日期:2025-12-31");
return builder.getResult();
}
}
/**
* 客户端使用示例
*/
public class HtmlGeneratorClient {
public static void main(String[] args) {
// 方式1:直接使用建造者
HtmlBuilder builder = new HtmlDocumentBuilder();
builder.buildHeader("欢迎页面");
builder.addParagraph("欢迎访问我们的网站!");
builder.addHorizontalRule();
HtmlDocument doc1 = builder.getResult();
System.out.println("简单页面:\n" + doc1.generate());
// 方式2:通过指挥者构建
DocumentDirector director = new DocumentDirector();
HtmlDocument reportDoc = director.buildReportDocument(new HtmlDocumentBuilder());
System.out.println("\n报告文档:\n" + reportDoc.generate());
}
}
简单页面:
<html>
<head>
<title>欢迎页面</title>
</head>
<body>
<p>欢迎访问我们的网站!</p>
<hr/>
</body>
</html>
报告文档:
<html>
<head>
<title>销售报告</title>
</head>
<body>
<p>2025年度销售汇总:</p>
<ul>
<li>第一季度:¥1,200万</li>
<li>第二季度:¥1,500万</li>
<li>第三季度:¥1,800万</li>
</ul>
<hr/>
<p>数据截止日期:2025-12-31</p>
</body>
</html>
结构型模式:
适配器模式
业务场景:旧系统的兼容升级
在实际业务中推荐优先使用对象适配器
- 符合组合优于继承的原则
- 更易扩展和维护
- 可以适配多个不同的旧系统组件
- 不会破坏原有继承体系
示例:旧系统日志记录器升级
特性 | 类适配器 | 对象适配器 |
---|---|---|
实现方式 | 继承旧类 | 组合旧类对象 |
灵活性 | 只能适配一个父类 | 可以适配多个不同类 |
旧系统方法覆盖 | 可以直接覆盖 | 需要通过委托调用 |
耦合度 | 较高(继承关系) | 较低(对象组合) |
推荐使用场景 | 当需要完全重写部分旧逻辑时 | 需要保持旧系统完整性的情况 |
import java.time.LocalDateTime;
/**
* 旧系统日志记录器(需要适配的类)
*/
class LegacyLogger {
/**
* 旧版日志记录方法
* @param severity 日志级别(1:信息 2:警告 3:错误)
* @param timestamp 时间戳(旧格式:字符串)
* @param message 日志内容
*/
public void log(int severity, String timestamp, String message) {
System.out.printf("[%s][%d] %s\n", timestamp, severity, message);
}
}
/**
* 新系统日志接口(目标接口)
*/
interface ModernLogger {
void info(String message);
void warn(String message);
void error(String message);
}
/**
* 类适配器(通过继承实现适配)
*/
class ClassLoggerAdapter extends LegacyLogger implements ModernLogger {
@Override
public void info(String message) {
super.log(1, LocalDateTime.now().toString(), "[INFO] " + message);
}
@Override
public void warn(String message) {
super.log(2, LocalDateTime.now().toString(), "[WARN] " + message);
}
@Override
public void error(String message) {
super.log(3, LocalDateTime.now().toString(), "[ERROR] " + message);
}
}
/**
* 对象适配器(通过组合实现适配)
*/
class ObjectLoggerAdapter implements ModernLogger {
private LegacyLogger legacyLogger;
public ObjectLoggerAdapter(LegacyLogger legacyLogger) {
this.legacyLogger = legacyLogger;
}
@Override
public void info(String message) {
legacyLogger.log(1, LocalDateTime.now().toString(), "[INFO] " + message);
}
@Override
public void warn(String message) {
legacyLogger.log(2, LocalDateTime.now().toString(), "[WARN] " + message);
}
@Override
public void error(String message) {
legacyLogger.log(3, LocalDateTime.now().toString(), "[ERROR] " + message);
}
}
/**
* 新增的现代日志实现(用于对比)
*/
class ModernLoggerImpl implements ModernLogger {
@Override
public void info(String message) {
System.out.printf("%s [INFO] %s\n", LocalDateTime.now(), message);
}
@Override
public void warn(String message) {
System.out.printf("%s [WARN] %s\n", LocalDateTime.now(), message);
}
@Override
public void error(String message) {
System.out.printf("%s [ERROR] %s\n", LocalDateTime.now(), message);
}
}
/**
* 客户端使用示例
*/
public class LoggerClient {
public static void main(String[] args) {
// 旧系统直接调用
LegacyLogger oldLogger = new LegacyLogger();
oldLogger.log(1, "2023-08-25T10:00:00", "System started");
// 使用类适配器
ModernLogger classAdapter = new ClassLoggerAdapter();
classAdapter.info("System initialized");
classAdapter.warn("Memory usage high");
classAdapter.error("Disk full!");
System.out.println("------------------------");
// 使用对象适配器
ModernLogger objectAdapter = new ObjectLoggerAdapter(new LegacyLogger());
objectAdapter.info("New user registered");
objectAdapter.warn("API response slow");
objectAdapter.error("Database connection failed");
System.out.println("------------------------");
// 现代实现
ModernLogger modern = new ModernLoggerImpl();
modern.info("Modern system ready");
modern.error("Critical failure detected");
}
}
[2023-08-25T10:00:00][1] System started
[2025-03-07T14:05:09.222224400][1] [INFO] System initialized
[2025-03-07T14:05:09.224219900][2] [WARN] Memory usage high
[2025-03-07T14:05:09.224219900][3] [ERROR] Disk full!
------------------------
[2025-03-07T14:05:09.225217700][1] [INFO] New user registered
[2025-03-07T14:05:09.225217700][2] [WARN] API response slow
[2025-03-07T14:05:09.226239700][3] [ERROR] Database connection failed
------------------------
2025-03-07T14:05:09.227237400 [INFO] Modern system ready
2025-03-07T14:05:09.227237400 [ERROR] Critical failure detected
装饰器模式
业务场景:动态为对象增加功能,如 Java IO 流
示例:咖啡订单系统
基础咖啡可以动态添加配料(装饰器),类似Java IO流层层包装的思想。
/**
* 装饰器模式示例:咖啡订单系统
* 关键结构:
* 1. 组件接口(Component)
* 2. 具体组件(ConcreteComponent)
* 3. 装饰器基类(Decorator)
* 4. 具体装饰器(ConcreteDecorator)
*/
// 1. 组件接口:定义咖啡的基本操作
interface Coffee {
String getDescription(); // 获取描述
double getCost(); // 获取价格
}
// 2. 具体组件:基础咖啡
class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "基础咖啡";
}
@Override
public double getCost() {
return 10.0;
}
}
// 3. 装饰器基类(实现组件接口,并持有组件引用)
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee; // 被装饰的咖啡对象
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
// 默认直接转发给被装饰对象
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
}
// 4. 具体装饰器:牛奶装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription() + " + 牛奶";
}
@Override
public double getCost() {
return decoratedCoffee.getCost() + 2.5;
}
}
// 4. 具体装饰器:糖浆装饰器
class SyrupDecorator extends CoffeeDecorator {
public SyrupDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription() + " + 糖浆";
}
@Override
public double getCost() {
return decoratedCoffee.getCost() + 1.8;
}
}
// 客户端使用示例
public class DecoratorPatternDemo {
public static void main(String[] args) {
// 基础咖啡
Coffee coffee = new SimpleCoffee();
System.out.println("基础咖啡:" + coffee.getDescription()
+ ",价格:" + coffee.getCost());
// 添加牛奶
Coffee milkCoffee = new MilkDecorator(coffee);
System.out.println("加料咖啡:" + milkCoffee.getDescription()
+ ",价格:" + milkCoffee.getCost());
// 添加牛奶+糖浆(多层装饰)
Coffee sweetMilkCoffee = new SyrupDecorator(milkCoffee);
System.out.println("加料咖啡:" + sweetMilkCoffee.getDescription()
+ ",价格:" + sweetMilkCoffee.getCost());
}
}
基础咖啡:基础咖啡,价格:10.0
加料咖啡:基础咖啡 + 牛奶,价格:12.5
加料咖啡:基础咖啡 + 牛奶 + 糖浆,价格:14.3
代理模式
业务场景:实现访问控制,如 RPC 调用
示例:敏感操作访问控制(保护代理)
控制访问,增强非业务功能(权限/日志),通常在编译期确定关系,可能隐藏真实对象创建过程
/**
* 代理模式示例:敏感操作访问控制(保护代理)
* 关键结构:
* 1. 服务接口(Subject)
* 2. 真实服务(RealSubject)
* 3. 代理类(Proxy)
*/
// 1. 服务接口:定义敏感操作
interface DataService {
void deleteData(String dataId, String userRole) throws Exception;
}
// 2. 真实服务:实际执行数据删除
class RealDataService implements DataService {
@Override
public void deleteData(String dataId, String userRole) {
System.out.println("正在删除数据:" + dataId);
// 真实数据库删除操作...
}
}
// 3. 代理类:控制访问权限
class DataServiceProxy implements DataService {
private RealDataService realService = new RealDataService();
@Override
public void deleteData(String dataId, String userRole) throws Exception {
// 前置权限校验
if (!"admin".equals(userRole)) {
throw new Exception("权限不足:需要管理员权限执行删除操作");
}
// 权限校验通过后调用真实服务
realService.deleteData(dataId, userRole);
// 后置日志记录(扩展功能)
System.out.println("[操作日志] 用户角色:" + userRole + " 删除了数据:" + dataId);
}
}
// 客户端使用示例
public class ProxyPatternDemo {
public static void main(String[] args) {
DataService service = new DataServiceProxy();
try {
// 管理员操作(允许执行)
service.deleteData("20230815_001", "admin");
// 普通用户操作(会被拦截)
service.deleteData("20230815_002", "user");
} catch (Exception e) {
System.out.println("操作异常:" + e.getMessage());
}
}
}
正在删除数据:20230815_001
[操作日志] 用户角色:admin 删除了数据:20230815_001
操作异常:权限不足:需要管理员权限执行删除操作
行为型模式:
观察者模式
业务场景:事件驱动系统,如 订阅 - 发布 系统
示例:模拟气象站数据更新通知多个显示板的场景
import java.util.ArrayList;
import java.util.List;
// 主题接口(被观察对象)
interface WeatherSubject {
void registerObserver(WeatherObserver o); // 注册观察者
void removeObserver(WeatherObserver o); // 移除观察者
void notifyObservers(); // 通知观察者
}
// 观察者接口
interface WeatherObserver {
void update(float temperature, float humidity, float pressure); // 更新方法
}
// 具体主题:气象数据站
class WeatherStation implements WeatherSubject {
private List<WeatherObserver> observers = new ArrayList<>();
private float temperature;
private float humidity;
private float pressure;
// 注册观察者
@Override
public void registerObserver(WeatherObserver o) {
observers.add(o);
}
// 移除观察者
@Override
public void removeObserver(WeatherObserver o) {
observers.remove(o);
}
// 通知所有观察者
@Override
public void notifyObservers() {
for (WeatherObserver observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
// 更新气象测量数据
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers(); // 数据变化时自动通知观察者
}
}
// 具体观察者:当前状况显示
class CurrentConditionsDisplay implements WeatherObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
System.out.printf("[当前状况] 温度:%.1f℃ 湿度:%.1f%% 气压:%.1fhPa\n",
temperature, humidity, pressure);
}
}
// 具体观察者:气象统计显示
class StatisticsDisplay implements WeatherObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
System.out.println("[统计显示] 正在更新历史数据...");
// 这里可以维护温度/湿度/压力的统计信息
}
}
// 具体观察者:天气预报显示
class ForecastDisplay implements WeatherObserver {
@Override
public void update(float temperature, float humidity, float pressure) {
System.out.println("[天气预报] 根据最新数据生成预测报告...");
// 这里可以实现天气预报算法
}
}
// 客户端使用
public class ObserverPatternDemo {
public static void main(String[] args) {
// 1. 创建主题对象
WeatherStation weatherStation = new WeatherStation();
// 2. 创建观察者对象
WeatherObserver currentDisplay = new CurrentConditionsDisplay();
WeatherObserver statsDisplay = new StatisticsDisplay();
WeatherObserver forecastDisplay = new ForecastDisplay();
// 3. 注册观察者
weatherStation.registerObserver(currentDisplay);
weatherStation.registerObserver(statsDisplay);
weatherStation.registerObserver(forecastDisplay);
// 4. 模拟气象数据更新(会自动通知所有观察者)
System.out.println("===== 第一次数据更新 =====");
weatherStation.setMeasurements(25.5f, 65.0f, 1013.0f);
System.out.println("\n===== 第二次数据更新 =====");
weatherStation.setMeasurements(26.2f, 68.5f, 1012.5f);
// 5. 移除一个观察者后再次更新
System.out.println("\n===== 移除统计显示后的更新 =====");
weatherStation.removeObserver(statsDisplay);
weatherStation.setMeasurements(24.8f, 70.0f, 1014.0f);
}
}
===== 第一次数据更新 =====
[当前状况] 温度:25.5℃ 湿度:65.0% 气压:1013.0hPa
[统计显示] 正在更新历史数据...
[天气预报] 根据最新数据生成预测报告...
===== 第二次数据更新 =====
[当前状况] 温度:26.2℃ 湿度:68.5% 气压:1012.5hPa
[统计显示] 正在更新历史数据...
[天气预报] 根据最新数据生成预测报告...
===== 移除统计显示后的更新 =====
[当前状况] 温度:24.8℃ 湿度:70.0% 气压:1014.0hPa
[天气预报] 根据最新数据生成预测报告...
责任链模式
业务场景:日志级别过滤、请求处理链
示例:请假审批流程
// 抽象处理者角色
abstract class Approver {
protected Approver nextHandler;
// 设置下一个处理者
public void setNext(Approver next) {
this.nextHandler = next;
}
// 处理请求的模板方法
public abstract boolean approve(int days);
}
// 具体处理者:组长
class GroupLeader extends Approver {
@Override
public boolean approve(int days) {
System.out.println("组长审批:" + days + "天请假");
if (days <= 1) {
System.out.println("组长批准申请");
return true;
} else {
System.out.println("组长审批不通过,转交经理");
return nextHandler != null && nextHandler.approve(days);
}
}
}
// 具体处理者:经理
class Manager extends Approver {
@Override
public boolean approve(int days) {
System.out.println("经理审批:" + days + "天请假");
if (days <= 3) {
System.out.println("经理批准申请");
return true;
} else {
System.out.println("经理审批不通过,转交总监");
return nextHandler != null && nextHandler.approve(days);
}
}
}
// 具体处理者:总监
class Director extends Approver {
@Override
public boolean approve(int days) {
System.out.println("总监审批:" + days + "天请假");
if (days <= 5) {
System.out.println("总监批准申请");
return true;
} else {
System.out.println("总监审批不通过,申请被驳回");
return false;
}
}
}
// 客户端测试代码
public class ChainPatternDemo {
public static void main(String[] args) {
// 创建处理链
Approver groupLeader = new GroupLeader();
Approver manager = new Manager();
Approver director = new Director();
groupLeader.setNext(manager);
manager.setNext(director);
// 测试不同请假天数的审批结果
testApproval(groupLeader, 1); // 应该通过
testApproval(groupLeader, 3); // 应该通过
testApproval(groupLeader, 4); // 应该通过
testApproval(groupLeader, 6); // 应该被驳回
}
private static void testApproval(Approver approver, int days) {
System.out.println("──────────────");
boolean result = approver.approve(days);
System.out.println("审批结果:" + (result ? "通过" : "驳回"));
System.out.println();
}
}
──────────────
组长审批:1天请假
组长批准申请
审批结果:通过
──────────────
组长审批:3天请假
组长审批不通过,转交经理
经理审批:3天请假
经理批准申请
审批结果:通过
──────────────
组长审批:4天请假
组长审批不通过,转交经理
经理审批:4天请假
经理审批不通过,转交总监
总监审批:4天请假
总监批准申请
审批结果:通过
──────────────
组长审批:6天请假
组长审批不通过,转交经理
经理审批:6天请假
经理审批不通过,转交总监
总监审批:6天请假
总监审批不通过,申请被驳回
审批结果:驳回
策略模式
业务场景:支付方式选择(如微信、支付宝、信用卡)
示例:支付系统
// 策略接口:定义支付算法的共同接口
interface PaymentStrategy {
void pay(double amount); // 支付抽象方法
}
// 具体策略类:微信支付
class WeChatPay implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.printf("微信支付成功:%.2f 元\n", amount);
// 这里可以接入微信支付SDK的具体实现
}
}
// 具体策略类:支付宝支付
class Alipay implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.printf("支付宝支付成功:%.2f 元\n", amount);
// 这里可以接入支付宝支付SDK的具体实现
}
}
// 具体策略类:信用卡支付
class CreditCardPay implements PaymentStrategy {
private String cardNumber;
private String cvv;
public CreditCardPay(String cardNumber, String cvv) {
this.cardNumber = cardNumber;
this.cvv = cvv;
}
@Override
public void pay(double amount) {
System.out.printf("信用卡尾号%s支付成功:%.2f 元\n",
cardNumber.substring(15), amount);
// 这里可以接入银行支付网关的具体实现
}
}
// 上下文类:负责使用策略
class PaymentProcessor {
private PaymentStrategy strategy; // 持有策略对象的引用
// 设置支付策略(关键方法)
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
// 执行支付操作
public void executePayment(double amount) {
if (strategy == null) {
System.out.println("请先选择支付方式");
return;
}
strategy.pay(amount);
}
}
// 客户端使用
public class StrategyPatternDemo {
public static void main(String[] args) {
// 创建支付处理器(上下文)
PaymentProcessor processor = new PaymentProcessor();
// 创建不同的支付策略
PaymentStrategy wechat = new WeChatPay();
PaymentStrategy alipay = new Alipay();
PaymentStrategy creditCard = new CreditCardPay("6225880134567890", "123");
// 使用微信支付
System.out.println("===== 使用微信支付 =====");
processor.setPaymentStrategy(wechat);
processor.executePayment(100.50);
// 切换支付宝支付
System.out.println("\n===== 切换支付宝支付 =====");
processor.setPaymentStrategy(alipay);
processor.executePayment(200.0);
// 切换信用卡支付
System.out.println("\n===== 切换信用卡支付 =====");
processor.setPaymentStrategy(creditCard);
processor.executePayment(500.0);
}
}
===== 使用微信支付 =====
微信支付成功:100.50 元
===== 切换支付宝支付 =====
支付宝支付成功:200.00 元
===== 切换信用卡支付 =====
信用卡尾号0支付成功:500.00 元