单例模式(Singleton Pattern)
模式概述
主打一个 "独苗政策":确保一个类这辈子只生一个实例,还得给全局留个 "访问入口",谁要都给同一个。
SpringBoot 实战场景
SpringBoot 里的 Bean 默认就是 "独苗"!由 Spring 容器统一创建、管理,保证全项目上下用的都是同一个对象 ------ 比如你在 Controller 和 Service 里注入的 UserService,压根就是同一个 "打工人"。
代码示例
bash
@Service
public class UserService {
// 私有构造器:防着外人随便new,主打一个"垄断"
private UserService() {
System.out.println("UserService实例上线打工啦~");
}
// Bean默认就是单例,不用额外配置
@Autowired
private UserRepository userRepository;
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
}
@RestController
public class UserController {
// 注入的是UserService的"独苗"实例
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
实战优势
省内存: 不用反复 new 对象,减少 "内存垃圾"
好管理: 共享资源(比如数据库连接)统一掌控,不混乱
易追踪: 全项目就一个实例,排查问题不用到处找
工厂方法模式(Factory Method Pattern)
模式概述
相当于 "对象生产流水线":定义一个 "造对象" 的接口,具体造哪种对象,让子类自己说了算 ------ 父类只负责 "发号施令",不插手具体 "生产"。
SpringBoot 实战场景
SpringBoot 的 BeanFactory 就是典型的 "工厂老板"!专门负责创建和管理 Bean 实例,你要啥 Bean,跟它说一声,它就给你造(或拿)一个,不用你自己 new。
代码示例
bash
// 支付处理器接口:相当于"生产规范"
public interface PaymentProcessor {
void processPayment(double amount);
}
// 具体实现1:信用卡支付(流水线1号)
@Component("creditCard")
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("正在用信用卡支付 $" + amount + ",刷起来~");
}
}
// 具体实现2:PayPal支付(流水线2号)
@Component("paypal")
public class PayPalProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("正在用PayPal支付 $" + amount + ",境外消费走起~");
}
}
// 支付工厂:"流水线调度中心"
@Component
public class PaymentProcessorFactory {
// 自动注入所有PaymentProcessor实现,存成Map(key是@Component的value)
@Autowired
private Map<String, PaymentProcessor> processors;
// 按需"调流水线"
public PaymentProcessor getProcessor(String type) {
PaymentProcessor processor = processors.get(type);
if (processor == null) {
throw new IllegalArgumentException("没找到[" + type + "]类型的支付方式,别瞎输!");
}
return processor;
}
}
// 订单服务:用工厂拿支付处理器
@Service
public class OrderService {
@Autowired
private PaymentProcessorFactory processorFactory;
public void placeOrder(String paymentType, double amount) {
// 要啥支付方式,让工厂给你找
PaymentProcessor processor = processorFactory.getProcessor(paymentType);
processor.processPayment(amount);
// 后续订单处理...
}
}
实战优势
解耦: 调用方(OrderService)不用知道具体是哪种支付,只管 "付钱"
易扩展: 新增支付方式(比如微信支付),只需要加个实现类,不用改旧代码(符合 "开闭原则")
统一管理: 对象创建逻辑全放工厂里,不乱套
抽象工厂模式(Abstract Factory Pattern)
模式概述
"超级工厂" 升级版:不止造一个对象,而是造一整套 "相关联的对象家族"------ 比如造数据库,不仅造连接(Connection),还造事务(Transaction),保证一套对象 "配套能用"。
SpringBoot 实战场景
SpringBoot 的多环境配置、数据源创建,全靠它!比如开发环境用 MySQL,生产环境用 PostgreSQL,切换环境时,一套 "数据库相关对象"(连接、事务)全切换,不用改代码。
代码示例(多数据源切换)
bash
// 抽象产品1:数据库连接
public interface Connection {
void connect();
void executeQuery(String query);
void close();
}
// 抽象产品2:数据库事务
public interface Transaction {
void begin();
void commit();
void rollback();
}
// 抽象工厂:定义"造一套产品"的规范
public interface DatabaseFactory {
Connection createConnection();
Transaction createTransaction();
}
// 具体工厂1:MySQL工厂(造MySQL的连接和事务)
@Component("mysqlFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "mysql") // 配置文件里db.type=mysql时生效
public class MySQLDatabaseFactory implements DatabaseFactory {
@Override
public Connection createConnection() {
return new MySQLConnection();
}
@Override
public Transaction createTransaction() {
return new MySQLTransaction();
}
}
// 具体工厂2:PostgreSQL工厂(造PostgreSQL的连接和事务)
@Component("postgresFactory")
@ConditionalOnProperty(name = "db.type", havingValue = "postgres") // 配置文件里db.type=postgres时生效
public class PostgresDatabaseFactory implements DatabaseFactory {
@Override
public Connection createConnection() {
return new PostgresConnection();
}
@Override
public Transaction createTransaction() {
return new PostgresTransaction();
}
}
// 具体产品实现:MySQL连接(省略MySQLTransaction、PostgresConnection等实现)
public class MySQLConnection implements Connection {
@Override
public void connect() {
System.out.println("正在连接MySQL数据库,冲!");
}
@Override
public void executeQuery(String query) {
System.out.println("在MySQL上执行SQL:" + query);
}
@Override
public void close() {
System.out.println("关闭MySQL连接,拜拜~");
}
}
// 使用抽象工厂
@Service
public class QueryService {
private final DatabaseFactory databaseFactory;
// 注入指定的工厂(比如mysqlFactory)
@Autowired
public QueryService(@Qualifier("mysqlFactory") DatabaseFactory databaseFactory) {
this.databaseFactory = databaseFactory;
}
public void executeQuery(String query) {
Connection connection = databaseFactory.createConnection();
Transaction transaction = databaseFactory.createTransaction();
try {
connection.connect();
transaction.begin();
connection.executeQuery(query);
transaction.commit(); // 成功就提交
} catch (Exception e) {
transaction.rollback(); // 失败就回滚
} finally {
connection.close(); // 不管成功失败,都关连接
}
}
}
实战优势
成套创建:相关对象一起造,保证兼容性(比如 MySQL 连接配 MySQL 事务,不会乱配)
环境切换方便:改个配置文件,整套数据源就切换,不用改业务代码
扩展性强:新增数据库类型(比如 Oracle),只需要加一个具体工厂和对应的产品实现
建造者模式(Builder Pattern)
模式概述
"复杂对象组装大师":把复杂对象的 "构建过程" 和 "最终样子" 分开,同一个构建过程,能组装出不同的 "成品"------ 比如拼乐高,同样的步骤,能拼出不同的造型。
SpringBoot 实战场景
SpringBoot 的配置类、链式 API(比如 Lambda 表达式里的链式调用),全是它的身影!比如构建一个复杂的邮件对象(有收件人、抄送、附件、主题等),用建造者模式一步步组装,清晰又不易出错。
代码示例(邮件发送场景)
bash
// 产品类:邮件对象
@Data
public class EmailMessage {
private String from; // 发件人
private List<String> to; // 收件人
private List<String> cc; // 抄送
private String subject; // 主题
private String body; // 正文
private boolean html; // 是否是HTML格式
private List<String> attachments; // 附件
private LocalDateTime scheduledTime; // 定时发送时间
// 私有构造器:只能通过Builder创建
private EmailMessage() {}
// 建造者类:专门负责"组装"邮件
public static class Builder {
private EmailMessage message;
public Builder() {
message = new EmailMessage();
message.to = new ArrayList<>();
message.cc = new ArrayList<>();
message.attachments = new ArrayList<>();
}
// 链式调用:每一步都返回自己,方便连续设置
public Builder from(String from) {
message.from = from;
return this;
}
public Builder to(String to) {
message.to.add(to);
return this;
}
public Builder cc(String cc) {
message.cc.add(cc);
return this;
}
public Builder subject(String subject) {
message.subject = subject;
return this;
}
public Builder body(String body) {
message.body = body;
return this;
}
public Builder html(boolean html) {
message.html = html;
return this;
}
public Builder attachment(String attachment) {
message.attachments.add(attachment);
return this;
}
public Builder scheduledTime(LocalDateTime scheduledTime) {
message.scheduledTime = scheduledTime;
return this;
}
// 组装完成,返回最终邮件对象(还会做参数校验)
public EmailMessage build() {
if (message.from == null || message.to.isEmpty() || message.subject == null) {
throw new IllegalStateException("发件人、收件人、主题是必填项,别偷懒!");
}
return message;
}
}
}
// 邮件服务:用建造者组装邮件
@Service
public class EmailService {
public void sendWelcomeEmail(User user) {
// 一步步组装邮件,像拼乐高一样简单
EmailMessage message = new EmailMessage.Builder()
.from("noreply@example.com")
.to(user.getEmail())
.subject("欢迎加入我们的平台~")
.body("<h1>欢迎你," + user.getName() + "!</h1><p>感谢注册,一起搞事情~</p>")
.html(true) // 支持HTML格式
.build();
sendEmail(message);
}
private void sendEmail(EmailMessage message) {
// 发送邮件逻辑
System.out.println("正在发送邮件:" + message);
}
}
实战优势
参数可控:一步步设置参数,不用记一堆构造器参数的顺序(再也不用面对new Email(from, to, cc, subject, ...)的噩梦)
可读性强:链式调用像 "说话" 一样,一看就知道在组装什么
支持多配置:同一个 Builder,能组装出不同参数的对象(比如有的邮件有附件,有的没有)
原型模式(Prototype Pattern)
模式概述
"对象复制粘贴大师":不重新 new 对象,而是通过 "复制" 一个现有对象(原型)来创建新对象 ------ 适合那些 "创建成本高" 的对象(比如初始化要查数据库、加载大量配置)。
SpringBoot 实战场景
SpringBoot 的prototype Bean scope 就是它的实现!每次注入prototype类型的 Bean,都会创建一个新实例 ------ 相当于 "复制" 了原型对象,再按需修改。
代码示例(报表配置场景)
bash
// 报表配置类(支持克隆,相当于"原型")
@Component
@Scope("prototype") // 标记为原型Bean,每次注入都new一个新的
public class ReportConfiguration implements Cloneable {
private String reportType; // 报表类型
private List<String> columns; // 报表列
private String sortBy; // 排序字段
private boolean ascending; // 是否升序
private String dateRange; // 日期范围
// 默认构造器:设置基础配置(原型的默认样子)
public ReportConfiguration() {
this.reportType = "summary";
this.columns = new ArrayList<>(Arrays.asList("id", "name", "date"));
this.sortBy = "date";
this.ascending = false;
this.dateRange = "last7days";
}
// 克隆方法:深拷贝(避免列表等引用类型"共用")
@Override
public ReportConfiguration clone() {
try {
ReportConfiguration clone = (ReportConfiguration) super.clone();
clone.columns = new ArrayList<>(this.columns); // 深拷贝列表
return clone;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
// getter和setter方法(省略)
}
// 报表工厂:用原型模式创建报表配置
@Service
public class ReportFactory {
// 注入原型Bean(每次注入都是新的,但这里用来当"默认模板")
@Autowired
private ReportConfiguration defaultConfig;
// 存储预定义的报表模板(复制原型后修改的)
private Map<String, ReportConfiguration> templates = new HashMap<>();
// 项目启动时初始化模板(复制原型,再自定义)
@PostConstruct
public void initTemplates() {
// 财务报表模板:复制默认原型,再修改配置
ReportConfiguration financialTemplate = defaultConfig.clone();
financialTemplate.setReportType("financial");
financialTemplate.setColumns(Arrays.asList("id", "amount", "transaction_date", "category"));
financialTemplate.setSortBy("amount");
templates.put("financial", financialTemplate);
// 用户活动报表模板:同样复制原型,再修改
ReportConfiguration activityTemplate = defaultConfig.clone();
activityTemplate.setReportType("activity");
activityTemplate.setColumns(Arrays.asList("user_id", "action", "timestamp", "ip_address"));
activityTemplate.setSortBy("timestamp");
templates.put("activity", activityTemplate);
}
// 根据模板创建新配置(复制模板,再按需修改)
public ReportConfiguration createFromTemplate(String templateName) {
ReportConfiguration template = templates.get(templateName);
if (template == null) {
throw new IllegalArgumentException("没找到[" + templateName + "]模板,别瞎输!");
}
return template.clone();
}
// 创建默认配置(直接复制原型)
public ReportConfiguration createDefault() {
return defaultConfig.clone();
}
}
// 报表控制器:使用原型模式生成报表
@RestController
@RequestMapping("/reports")
public class ReportController {
@Autowired
private ReportFactory reportFactory;
@GetMapping("/financial")
public String generateFinancialReport(@RequestParam Map<String, String> params) {
// 拿财务报表模板,再根据请求参数自定义
ReportConfiguration config = reportFactory.createFromTemplate("financial");
// 比如根据请求参数修改日期范围
if (params.containsKey("dateRange")) {
config.setDateRange(params.get("dateRange"));
}
// 生成报表...
return "财务报表生成成功,配置:" + config;
}
}
实战优势
省时间:不用反复执行初始化逻辑(比如查数据库),复制一下就好
模板复用:预定义模板,后续创建新对象只需 "复制 + 微调"
减少子类:不用为了不同配置创建一堆子类,复制原型就能实现差异化
适配器模式(Adapter Pattern)
模式概述
"接口翻译官":把一个类的接口,转换成另一个接口客户端能接受的样子 ------ 相当于手机充电器的转接头,Type-C 接口的充电器,用转接头就能给 iPhone 充电。
SpringBoot 实战场景
SpringBoot 的 MVC 框架、第三方接口集成,全靠它 "搭桥"!比如老系统的支付接口(参数是 accountNumber、amount),新系统要用新接口(参数是 PaymentRequest),用适配器转一下,老接口就能在新系统里用。
代码示例(新旧支付系统对接)
bash
// 老支付系统接口( legacy = 老旧的,难用的 )
public interface LegacyPaymentService {
boolean processPayment(String accountNumber, double amount, String currency);
String getTransactionStatus(String transactionId);
}
// 老支付系统实现(祖传代码,不能动)
@Service("legacyPaymentService")
public class LegacyPaymentServiceImpl implements LegacyPaymentService {
@Override
public boolean processPayment(String accountNumber, double amount, String currency) {
System.out.println("用老系统处理支付,别嫌慢~");
// 老系统的支付逻辑(祖传代码,不敢改)
return true;
}
@Override
public String getTransactionStatus(String transactionId) {
// 老系统查支付状态的逻辑
return "COMPLETED";
}
}
// 新支付系统接口(现代、优雅)
public interface ModernPaymentGateway {
PaymentResponse pay(PaymentRequest request);
TransactionStatus checkStatus(String reference);
}
// 新系统的请求/响应模型(优雅的DTO)
@Data
public class PaymentRequest {
private String customerId;
private BigDecimal amount;
private String currencyCode;
private String paymentMethod;
private Map<String, String> metadata;
}
@Data
public class PaymentResponse {
private String referenceId;
private boolean successful;
private String message;
}
public enum TransactionStatus {
PENDING, PROCESSING, COMPLETED, FAILED, REFUNDED
}
// 适配器:把老接口"翻译"成新接口(转接头核心)
@Component
public class LegacyPaymentAdapter implements ModernPaymentGateway {
private final LegacyPaymentService legacyService;
@Autowired
public LegacyPaymentAdapter(LegacyPaymentService legacyService) {
this.legacyService = legacyService;
}
@Override
public PaymentResponse pay(PaymentRequest request) {
// 第一步:把新请求参数,转换成老接口需要的参数
boolean result = legacyService.processPayment(
request.getCustomerId(), // 新的customerId = 老的accountNumber
request.getAmount().doubleValue(), // 新的BigDecimal = 老的double
request.getCurrencyCode() // 新的currencyCode = 老的currency
);
// 第二步:把老接口的返回值,转换成新接口的返回值
PaymentResponse response = new PaymentResponse();
response.setSuccessful(result);
response.setReferenceId(UUID.randomUUID().toString());
response.setMessage(result ? "支付成功~" : "支付失败,再试试!");
return response;
}
@Override
public TransactionStatus checkStatus(String reference) {
// 把老接口的状态字符串,转换成新接口的枚举
String status = legacyService.getTransactionStatus(reference);
switch (status) {
case "COMPLETED":
return TransactionStatus.COMPLETED;
case "FAILED":
return TransactionStatus.FAILED;
case "IN_PROGRESS":
return TransactionStatus.PROCESSING;
default:
return TransactionStatus.PENDING;
}
}
}
// 新系统的 checkout 服务(只用新接口,不知道老系统的存在)
@Service
public class CheckoutService {
private final ModernPaymentGateway paymentGateway;
@Autowired
public CheckoutService(ModernPaymentGateway paymentGateway) {
this.paymentGateway = paymentGateway;
}
public void processCheckout(Cart cart, String customerId) {
// 用新接口的请求模型,组装参数
PaymentRequest request = new PaymentRequest();
request.setCustomerId(customerId);
request.setAmount(cart.getTotal());
request.setCurrencyCode("USD");
// 调用新接口(底层其实是老系统在干活,但是新系统不知道)
PaymentResponse response = paymentGateway.pay(request);
if (response.isSuccessful()) {
// 支付成功逻辑
} else {
// 支付失败逻辑
}
}
}
实战优势
复用老代码:不用重写祖传代码,加个适配器就能在新系统里用
平滑过渡:新旧系统并行运行,慢慢迁移,不影响业务
解耦:新系统不用关心老接口的细节,只管调用新接口
装饰器模式(Decorator Pattern)
模式概述
"对象的穿衣大师":动态给对象加 "新技能",不用改原对象的代码 ------ 相当于给手机贴钢化膜(加保护)、装手机壳(加颜值),手机本身没变,但多了新功能。
SpringBoot 实战场景
SpringBoot 的@Cacheable、@Transactional注解,全是它的杰作!比如一个普通的查询方法,加个@Cacheable,就多了 "缓存" 功能;加个@Transactional,就多了 "事务" 功能 ------ 原方法代码一点没改。
代码示例(通知服务增强)
bash
// 基础接口:通知服务(核心功能:发通知)
public interface NotificationService {
void send(String message, String recipient);
}
// 基础实现:邮件通知(核心功能的实现)
@Service
@Primary
public class EmailNotificationService implements NotificationService {
@Override
public void send(String message, String recipient) {
System.out.println("给[" + recipient + "]发邮件:" + message);
// 实际发邮件的逻辑
}
}
// 装饰器基类:所有装饰器都要继承它(相当于"衣服的基础款")
public abstract class NotificationDecorator implements NotificationService {
protected NotificationService wrapped; // 被装饰的对象(比如EmailNotificationService)
public NotificationDecorator(NotificationService wrapped) {
this.wrapped = wrapped;
}
}
// 装饰器1:日志装饰器(给通知加"日志记录"技能)
@Component
public class LoggingNotificationDecorator extends NotificationDecorator {
private final Logger logger = LoggerFactory.getLogger(LoggingNotificationDecorator.class);
public LoggingNotificationDecorator(NotificationService wrapped) {
super(wrapped);
}
@Override
public void send(String message, String recipient) {
logger.info("准备给[" + recipient + "]发通知啦~");
long startTime = System.currentTimeMillis();
wrapped.send(message, recipient); // 调用被装饰对象的核心功能
long endTime = System.currentTimeMillis();
logger.info("给[" + recipient + "]发通知完成,耗时[" + (endTime - startTime) + "]ms");
}
}
// 装饰器2:重试装饰器(给通知加"失败重试"技能)
@Component
public class RetryNotificationDecorator extends NotificationDecorator {
private final Logger logger = LoggerFactory.getLogger(RetryNotificationDecorator.class);
private final int maxRetries; // 最大重试次数(从配置文件读取)
public RetryNotificationDecorator(
@Qualifier("loggingNotificationDecorator") NotificationService wrapped,
@Value("${notification.max-retries:3}") int maxRetries) {
super(wrapped);
this.maxRetries = maxRetries;
}
@Override
public void send(String message, String recipient) {
int attempts = 0;
boolean sent = false;
while (!sent && attempts < maxRetries) {
try {
attempts++;
wrapped.send(message, recipient); // 调用上一个装饰器的功能(日志+核心)
sent = true;
} catch (Exception e) {
logger.warn("第[" + attempts + "]次发通知失败:" + e.getMessage());
if (attempts >= maxRetries) {
logger.error("重试次数用完了,发通知彻底失败!");
throw e;
}
// 指数退避:重试间隔越来越长(100ms、200ms、400ms...)
try {
Thread.sleep( Math.pow(2, attempts) * 100L);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
}
// 装饰器3:加密装饰器(给通知加"消息加密"技能)
@Component
public class EncryptionNotificationDecorator extends NotificationDecorator {
public EncryptionNotificationDecorator(
@Qualifier("retryNotificationDecorator") NotificationService wrapped) {
super(wrapped);
}
@Override
public void send(String message, String recipient) {
String encryptedMessage = encrypt(message); // 加密消息
wrapped.send(encryptedMessage, recipient); // 调用上一个装饰器的功能(重试+日志+核心)
}
private String encrypt(String message) {
// 简单加密逻辑(实际项目用更安全的加密方式)
return "ENCRYPTED[" + message + "]";
}
}
// 装饰器配置:把装饰器链起来(加密→重试→日志→核心)
@Configuration
public class NotificationConfig {
@Bean
public NotificationService loggingNotificationDecorator(
@Qualifier("emailNotificationService") NotificationService emailService) {
return new LoggingNotificationDecorator(emailService);
}
@Bean
public NotificationService retryNotificationDecorator(
@Qualifier("loggingNotificationDecorator") NotificationService loggingDecorator,
@Value("${notification.max-retries:3}") int maxRetries) {
return new RetryNotificationDecorator(loggingDecorator, maxRetries);
}
@Bean
public NotificationService encryptionNotificationDecorator(
@Qualifier("retryNotificationDecorator") NotificationService retryDecorator) {
return new EncryptionNotificationDecorator(retryDecorator);
}
// 最终的Bean:装饰器链的最外层(加密装饰器)
@Bean
@Primary
public NotificationService notificationService(
@Qualifier("encryptionNotificationDecorator") NotificationService encryptionDecorator) {
return encryptionDecorator;
}
}
// 使用装饰后的服务(注入的是装饰器链,拥有所有技能)
@Service
public class UserService {
private final NotificationService notificationService;
@Autowired
public UserService(NotificationService notificationService) {
this.notificationService = notificationService;
}
public void notifyUser(User user, String message) {
// 一次调用,触发所有装饰器功能:加密→重试→日志→发邮件
notificationService.send(message, user.getEmail());
}
}
实战优势
动态增强:不用改原代码,就能给对象加新功能(符合 "开闭原则")
组合灵活:多个装饰器可以自由组合(比如有的场景需要 "日志 + 重试",有的需要 "加密 + 日志")
接口一致:装饰后的对象和原对象接口一样,调用方不用改代码
观察者模式(Observer Pattern)
模式概述
"消息广播员":定义一对多的关系,当一个对象(广播员)状态变化时,所有依赖它的对象(听众)都会收到通知,自动更新 ------ 相当于公众号发推文,所有关注的人都会收到消息。
SpringBoot 实战场景
SpringBoot 的事件机制(ApplicationEvent、ApplicationListener)就是它的实现!比如用户注册成功后,要发欢迎邮件、创建用户档案、添加营销订阅,这些操作都可以作为 "听众",监听 "用户注册" 这个事件。
代码示例(用户注册事件)
bash
// 自定义事件:用户注册事件(相当于"推文")
public class UserRegisteredEvent extends ApplicationEvent {
private final User user; // 事件携带的信息(注册的用户)
public UserRegisteredEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
// 事件发布者:用户注册服务(相当于"公众号")
@Service
public class UserRegistrationService {
private final ApplicationEventPublisher eventPublisher; // Spring提供的事件发布器
private final UserRepository userRepository;
@Autowired
public UserRegistrationService(
ApplicationEventPublisher eventPublisher,
UserRepository userRepository) {
this.eventPublisher = eventPublisher;
this.userRepository = userRepository;
}
@Transactional
public User registerUser(UserRegistrationDto registrationDto) {
// 1. 创建并保存用户(核心业务)
User user = new User();
user.setUsername(registrationDto.getUsername());
user.setEmail(registrationDto.getEmail());
user.setPassword(encodePassword(registrationDto.getPassword()));
user.setRegistrationDate(LocalDateTime.now());
User savedUser = userRepository.save(user);
// 2. 发布"用户注册成功"事件(发推文)
eventPublisher.publishEvent(new UserRegisteredEvent(this, savedUser));
return savedUser;
}
private String encodePassword(String password) {
// 密码加密逻辑(比如BCrypt)
return "{bcrypt}" + password;
}
}
// 事件监听器1:发送欢迎邮件(听众1)
@Component
public class WelcomeEmailListener implements ApplicationListener<UserRegisteredEvent> {
private final EmailService emailService;
@Autowired
public WelcomeEmailListener(EmailService emailService) {
this.emailService = emailService;
}
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 收到事件,执行发送欢迎邮件
emailService.sendWelcomeEmail(user);
}
}
// 事件监听器2:创建用户档案(听众2)
@Component
public class UserProfileInitializer implements ApplicationListener<UserRegisteredEvent> {
private final ProfileService profileService;
@Autowired
public UserProfileInitializer(ProfileService profileService) {
this.profileService = profileService;
}
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
User user = event.getUser();
// 收到事件,执行创建用户档案
profileService.createInitialProfile(user);
}
}
// 事件监听器3:添加营销订阅(听众3,用注解方式,更简洁)
@Component
public class MarketingSubscriptionHandler {
private final MarketingService marketingService;
@Autowired
public MarketingSubscriptionHandler(MarketingService marketingService) {
this.marketingService = marketingService;
}
// @EventListener:标记为事件监听器,监听UserRegisteredEvent
// @Async:异步执行,不阻塞主线程
@EventListener
@Async
public void handleUserRegistered(UserRegisteredEvent event) {
User user = event.getUser();
// 收到事件,执行添加营销订阅
marketingService.addUserToDefaultNewsletters(user);
}
}
// 配置异步事件:让@Async生效(异步执行监听器,提高性能)
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(25); // 队列容量
executor.setThreadNamePrefix("EventHandler-"); // 线程名前缀(方便排查问题)
executor.initialize();
return executor;
}
}
实战优势
解耦:发布者不用知道有哪些听众,只管发布事件;听众不用知道发布者的细节,只管监听事件
异步处理:支持异步执行监听器,不会阻塞主线程(比如添加营销订阅比较耗时,异步执行不影响用户注册的响应速度)
易扩展:新增一个操作(比如注册后送积分),只需要加一个监听器,不用改发布者的代码
策略模式(Strategy Pattern)
模式概述
"算法切换大师":定义一组算法,把每个算法都封装起来,让它们可以互相替换 ------ 相当于手机的 "拍照模式",普通模式、夜景模式、人像模式,按需切换,核心都是 "拍照"。
SpringBoot 实战场景
SpringBoot 的缓存策略、认证策略,全是它的应用!比如电商的折扣策略:新用户折扣、会员折扣、大额订单折扣,不同用户 / 订单用不同的折扣算法,随时可以切换。
代码示例(折扣策略)
bash
// 折扣策略接口:定义"折扣算法"的规范
public interface DiscountStrategy {
BigDecimal applyDiscount(BigDecimal amount, User user); // 计算折扣后金额
boolean isApplicable(User user, ShoppingCart cart); // 判断该策略是否适用
}
// 策略1:新用户折扣(注册30天内的用户)
@Component
public class NewUserDiscountStrategy implements DiscountStrategy {
@Value("${discount.new-user.percentage:10}")
private int discountPercentage; // 折扣比例(从配置文件读取,默认10%)
@Override
public BigDecimal applyDiscount(BigDecimal amount, User user) {
BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage)
.divide(BigDecimal.valueOf(100));
BigDecimal discount = amount.multiply(discountFactor);
return amount.subtract(discount); // 原价 - 折扣 = 折后价
}
@Override
public boolean isApplicable(User user, ShoppingCart cart) {
LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);
return user.getRegistrationDate().isAfter(thirtyDaysAgo); // 注册时间在30天内
}
}
// 策略2:会员折扣(VIP会员)
@Component
public class PremiumMemberDiscountStrategy implements DiscountStrategy {
@Value("${discount.premium-member.percentage:15}")
private int discountPercentage; // 会员折扣比例(默认15%)
@Override
public BigDecimal applyDiscount(BigDecimal amount, User user) {
BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage)
.divide(BigDecimal.valueOf(100));
BigDecimal discount = amount.multiply(discountFactor);
return amount.subtract(discount);
}
@Override
public boolean isApplicable(User user, ShoppingCart cart) {
return "PREMIUM".equals(user.getMembershipLevel()); // 会员等级是PREMIUM
}
}
// 策略3:大额订单折扣(订单金额超过阈值)
@Component
public class LargeOrderDiscountStrategy implements DiscountStrategy {
@Value("${discount.large-order.threshold:1000}")
private BigDecimal threshold; // 大额订单阈值(默认1000元)
@Value("${discount.large-order.percentage:5}")
private int discountPercentage; // 大额订单折扣比例(默认5%)
@Override
public BigDecimal applyDiscount(BigDecimal amount, User user) {
BigDecimal discountFactor = BigDecimal.valueOf(discountPercentage)
.divide(BigDecimal.valueOf(100));
BigDecimal discount = amount.multiply(discountFactor);
return amount.subtract(discount);
}
@Override
public boolean isApplicable(User user, ShoppingCart cart) {
return cart.getTotalAmount().compareTo(threshold) >= 0; // 订单金额>=阈值
}
}
// 策略上下文:折扣服务(负责选择合适的策略)
@Service
public class DiscountService {
private final List<DiscountStrategy> discountStrategies; // 自动注入所有折扣策略
@Autowired
public DiscountService(List<DiscountStrategy> discountStrategies) {
this.discountStrategies = discountStrategies;
}
// 计算最优折扣(选择折扣最大的策略)
public BigDecimal calculateDiscountedAmount(BigDecimal originalAmount, User user, ShoppingCart cart) {
DiscountStrategy bestStrategy = findBestDiscountStrategy(user, cart);
if (bestStrategy != null) {
return bestStrategy.applyDiscount(originalAmount, user);
}
return originalAmount; // 没有适用的策略,返回原价
}
// 查找最优策略(遍历所有策略,选折扣最大的)
private DiscountStrategy findBestDiscountStrategy(User user, ShoppingCart cart) {
BigDecimal originalAmount = cart.getTotalAmount();
BigDecimal bestDiscount = BigDecimal.ZERO;
DiscountStrategy bestStrategy = null;
for (DiscountStrategy strategy : discountStrategies) {
if (strategy.isApplicable(user, cart)) { // 先判断策略是否适用
BigDecimal discountedAmount = strategy.applyDiscount(originalAmount, user);
BigDecimal discount = originalAmount.subtract(discountedAmount); // 计算折扣金额
if (discount.compareTo(bestDiscount) > 0) { // 找到更大的折扣
bestDiscount = discount;
bestStrategy = strategy;
}
}
}
return bestStrategy;
}
}
实战优势
算法独立:每个算法都封装成单独的类,方便维护和修改
动态切换:可以根据不同的场景,动态选择不同的算法(比如新用户自动用新用户折扣)
消除 if-else:不用写一堆if (是新用户) { ... } else if (是会员) { ... }的代码
易扩展:新增折扣策略(比如节日折扣),只需要加一个策略类,不用改旧代码
模板方法模式(Template Method Pattern)
模式概述
"算法骨架师" :定义一个算法的骨架(步骤),把一些可变的步骤推迟到子类里实现 ------ 相当于做蛋糕的食谱:步骤是固定的(准备材料→混合→烘烤→装饰),但装饰步骤可以自己发挥(抹奶油、放水果)。
SpringBoot 实战场景
SpringBoot 的JdbcTemplate、RestTemplate,全是它的经典实现!比如JdbcTemplate的查询流程(获取连接→创建 Statement→执行查询→处理结果→关闭连接)是固定的,处理结果的步骤(比如把 ResultSet 转换成对象)留给用户自己实现。
代码示例(报表导出场景)
bash
// 抽象模板类:报表导出器(定义导出报表的固定步骤)
@Component
public abstract class AbstractReportExporter {
// 模板方法:定义导出报表的算法骨架(固定步骤,子类不能改)
public final void exportReport(ReportRequest request, OutputStream output) {
try {
// 步骤1:校验请求(固定)
validateRequest(request);
// 步骤2:获取数据(固定)
ReportData data = fetchData(request);
// 步骤3:处理数据(固定,子类可以重写)
ReportData processedData = processData(data);
// 步骤4:格式化数据(可变,子类必须实现)
byte[] formattedData = formatData(processedData);
// 步骤5:写入输出流(固定)
output.write(formattedData);
output.flush();
// 步骤6:记录日志(固定)
logExport(request, processedData);
} catch (Exception e) {
// 步骤7:处理异常(固定)
handleExportError(e, request);
}
}
// 固定方法:校验请求(子类不用管)
protected void validateRequest(ReportRequest request) {
if (request == null) {
throw new IllegalArgumentException("报表请求不能为null!");
}
if (request.getStartDate() == null || request.getEndDate() == null) {
throw new IllegalArgumentException("开始日期和结束日期是必填项!");
}
if (request.getStartDate().isAfter(request.getEndDate())) {
throw new IllegalArgumentException("开始日期不能晚于结束日期!");
}
}
// 抽象方法:获取数据(子类必须实现,因为不同报表的数据来源不同)
protected abstract ReportData fetchData(ReportRequest request);
// 钩子方法:处理数据(子类可以选择重写,默认不处理)
protected ReportData processData(ReportData data) {
return data; // 默认不处理,直接返回原数据
}
// 抽象方法:格式化数据(子类必须实现,因为不同格式的报表(PDF/Excel)格式化方式不同)
protected abstract byte[] formatData(ReportData data) throws IOException;
// 固定方法:记录日志(子类不用管)
protected void logExport(ReportRequest request, ReportData data) {
System.out.println("报表导出成功!时间范围:" +
request.getStartDate() + " 到 " + request.getEndDate() +
",记录数:" + data.getRecords().size());
}
// 固定方法:处理异常(子类不用管)
protected void handleExportError(Exception e, ReportRequest request) {
System.err.println("报表导出失败:" + e.getMessage());
throw new ReportExportException("报表导出失败,请重试!", e);
}
}
// 具体模板1:PDF报表导出器(实现抽象方法,处理PDF格式)
@Component("pdfExporter")
public class PdfReportExporter extends AbstractReportExporter {
@Autowired
private ReportRepository reportRepository;
@Override
protected ReportData fetchData(ReportRequest request) {
// PDF报表的数据来源(从数据库查询)
List<ReportRecord> records = reportRepository.findByDateRange(
request.getStartDate(), request.getEndDate());
return new ReportData(records, request.getStartDate(), request.getEndDate());
}
@Override
protected ReportData processData(ReportData data) {
// 重写钩子方法:对数据进行排序处理(PDF报表需要排序)
List<ReportRecord> processedRecords = data.getRecords().stream()
.sorted(Comparator.comparing(ReportRecord::getDate))
.collect(Collectors.toList());
return new ReportData(processedRecords, data.getStartDate(), data.getEndDate());
}
@Override
protected byte[] formatData(ReportData data) throws IOException {
// 实现PDF格式化逻辑(用iText库)
Document document = new Document();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
PdfWriter.getInstance(document, baos);
document.open();
// 添加报表标题
document.add(new Paragraph("报表(" + data.getStartDate() + " 到 " + data.getEndDate() + ")"));
// 创建PDF表格(3列:日期、描述、金额)
PdfPTable table = new PdfPTable(3);
table.addCell("日期");
table.addCell("描述");
table.addCell("金额");
// 填充数据
for (ReportRecord record : data.getRecords()) {
table.addCell(record.getDate().toString());
table.addCell(record.getDescription());
table.addCell(record.getAmount().toString());
}
document.add(table);
} finally {
if (document.isOpen()) {
document.close();
}
}
return baos.toByteArray();
}
}
// 具体模板2:Excel报表导出器(实现抽象方法,处理Excel格式)
@Component("excelExporter")
public class ExcelReportExporter extends AbstractReportExporter {
@Autowired
private ReportRepository reportRepository;
@Override
protected ReportData fetchData(ReportRequest request) {
// Excel报表的数据来源(和PDF一样,从数据库查询)
List<ReportRecord> records = reportRepository.findByDateRange(
request.getStartDate(), request.getEndDate());
return new ReportData(records, request.getStartDate(), request.getEndDate());
}
// 不重写processData方法,使用父类的默认实现(Excel报表不需要额外处理数据)
@Override
protected byte[] formatData(ReportData data) throws IOException {
// 实现Excel格式化逻辑(用POI库)
Workbook workbook = new XSSFWorkbook();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
Sheet sheet = workbook.createSheet("报表数据");
// 创建表头行
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("日期");
headerRow.createCell(1).setCellValue("描述");
headerRow.createCell(2).setCellValue("金额");
// 填充数据行
int rowNum = 1;
for (ReportRecord record : data.getRecords()) {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(record.getDate().toString());
row.createCell(1).setCellValue(record.getDescription());
row.createCell(2).setCellValue(record.getAmount().doubleValue());
}
// 自动调整列宽
for (int i = 0; i < 3; i++) {
sheet.autoSizeColumn(i);
}
workbook.write(baos);
} finally {
workbook.close();
}
return baos.toByteArray();
}
}
// 控制器:使用模板方法导出报表
@RestController
@RequestMapping("/reports")
public class ReportController {
@Autowired
@Qualifier("pdfExporter")
private AbstractReportExporter pdfExporter;
@Autowired
@Qualifier("excelExporter")
private AbstractReportExporter excelExporter;
// 导出PDF报表
@GetMapping(value = "/export/pdf", produces = MediaType.APPLICATION_PDF_VALUE)
public void exportPdf(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
HttpServletResponse response) throws IOException {
response.setHeader("Content-Disposition", "attachment; filename=report.pdf");
ReportRequest request = new ReportRequest();
request.setStartDate(startDate);
request.setEndDate(endDate);
pdfExporter.exportReport(request, response.getOutputStream());
}
// 导出Excel报表
@GetMapping(value = "/export/excel",
produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public void exportExcel(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate,
HttpServletResponse response) throws IOException {
response.setHeader("Content-Disposition", "attachment; filename=report.xlsx");
ReportRequest request = new ReportRequest();
request.setStartDate(startDate);
request.setEndDate(endDate);
excelExporter.exportReport(request, response.getOutputStream());
}
}
实战优势
代码复用:把固定的步骤(校验、日志、异常处理)提取到父类,子类只关注可变的步骤
控制扩展:父类定义算法骨架,子类只能在指定的扩展点(抽象方法、钩子方法)修改,不会破坏算法结构
符合 "开闭原则":新增报表格式(比如 Word),只需要加一个子类,不用改父类的代码
责任链模式(Chain of Responsibility Pattern)
模式概述
"请求接力赛":把多个处理器组成一条链,请求从链的开头出发,依次经过每个处理器,直到有一个处理器能处理它 ------ 相当于公司请假流程:员工→组长→部门经理→总经理,每个层级判断自己能不能批,不能批就交给下一级。
SpringBoot 实战场景
SpringBoot 的 Filter 链、Interceptor 链,全是它的实现!比如一个 HTTP 请求,会经过多个 Filter(登录校验 Filter、权限校验 Filter、日志 Filter),每个 Filter 处理完,再交给下一个 Filter,直到交给 DispatcherServlet。
代码示例(支付流程处理)
bash
// 抽象处理器:支付处理器(定义处理请求的方法和下一个处理器)
public abstract class PaymentHandler {
protected PaymentHandler nextHandler; // 下一个处理器(接力的人)
// 设置下一个处理器(组装责任链)
public void setNext(PaymentHandler handler) {
this.nextHandler = handler;
}
// 处理支付请求(子类必须实现)
public abstract PaymentResponse handle(PaymentRequest request);
}
// 处理器1:参数校验处理器(第一个接力的人,负责校验参数)
@Component
public class ValidationHandler extends PaymentHandler {
@Override
public PaymentResponse handle(PaymentRequest request) {
// 校验支付金额
if (request.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
return new PaymentResponse(false, "支付金额必须大于0!");
}
// 校验卡号
if (request.getCardNumber() == null || request.getCardNumber().isEmpty()) {
return new PaymentResponse(false, "银行卡号不能为空!");
}
// 校验卡号长度(13-19位)
if (request.getCardNumber().length() < 13 || request.getCardNumber().length() > 19) {
return new PaymentResponse(false, "银行卡号长度无效!");
}
// 校验有效期
if (request.getExpiryDate() == null) {
return new PaymentResponse(false, "银行卡有效期不能为空!");
}
if (request.getExpiryDate().isBefore(YearMonth.now())) {
return new PaymentResponse(false, "银行卡已过期!");
}
// 校验通过,交给下一个处理器
if (nextHandler != null) {
return nextHandler.handle(request);
}
return new PaymentResponse(true, "参数校验通过!");
}
}
// 处理器2:风控处理器(第二个接力的人,负责检测欺诈)
@Component
public class FraudDetectionHandler extends PaymentHandler {
@Autowired
private FraudDetectionService fraudService; // 风控服务
@Override
public PaymentResponse handle(PaymentRequest request) {
// 调用风控服务,检测是否有欺诈风险
FraudCheckResult checkResult = fraudService.checkForFraud(
request.getCardNumber(),
request.getAmount(),
request.getIpAddress());
if (checkResult.isFraudulent()) {
return new PaymentResponse(false, "交易存在欺诈风险:" + checkResult.getReason());
}
// 风控通过,交给下一个处理器
if (nextHandler != null) {
return nextHandler.handle(request);
}
return new PaymentResponse(true, "风控检测通过!");
}
}
// 处理器3:支付处理处理器(第三个接力的人,负责实际支付)
@Component
public class PaymentProcessingHandler extends PaymentHandler {
@Autowired
private PaymentGateway paymentGateway; // 支付网关(调用第三方支付接口)
@Override
public PaymentResponse handle(PaymentRequest request) {
// 调用支付网关,执行实际支付
PaymentGatewayResponse gatewayResponse = paymentGateway.processPayment(
request.getCardNumber(),
request.getExpiryDate(),
request.getCvv(),
request.getAmount());
if (!gatewayResponse.isSuccessful()) {
return new PaymentResponse(false, "支付失败:" + gatewayResponse.getMessage());
}
// 支付成功,交给下一个处理器
if (nextHandler != null) {
PaymentResponse nextResponse = nextHandler.handle(request);
// 如果下一个步骤失败(比如通知失败),需要退款
if (!nextResponse.isSuccess()) {
paymentGateway.refund(gatewayResponse.getTransactionId(), request.getAmount());
return nextResponse;
}
// 把支付网关返回的交易ID添加到响应中
nextResponse.setTransactionId(gatewayResponse.getTransactionId());
return nextResponse;
}
return new PaymentResponse(true, "支付处理成功!", gatewayResponse.getTransactionId());
}
}
// 处理器4:通知处理器(第四个接力的人,负责支付结果通知)
@Component
public class NotificationHandler extends PaymentHandler {
@Autowired
private NotificationService notificationService; // 通知服务(短信/邮件通知)
@Override
public PaymentResponse handle(PaymentRequest request) {
// 调用通知服务,给用户发送支付成功通知
notificationService.sendPaymentConfirmation(
request.getEmail(),
request.getAmount(),
LocalDateTime.now());
// 通知发送完成,交给下一个处理器(如果有的话)
if (nextHandler != null) {
return nextHandler.handle(request);
}
return new PaymentResponse(true, "支付完成且通知已发送!");
}
}
// 责任链配置:组装处理器链条
@Configuration
public class PaymentHandlerConfig {
@Bean
public PaymentHandler paymentHandlerChain(
ValidationHandler validationHandler,
FraudDetectionHandler fraudDetectionHandler,
PaymentProcessingHandler paymentProcessingHandler,
NotificationHandler notificationHandler) {
// 构建责任链:参数校验 → 风控检测 → 支付处理 → 结果通知
validationHandler.setNext(fraudDetectionHandler);
fraudDetectionHandler.setNext(paymentProcessingHandler);
paymentProcessingHandler.setNext(notificationHandler);
// 返回链条的第一个处理器(入口)
return validationHandler;
}
}
// 支付服务:触发责任链处理
@Service
public class PaymentService {
private final PaymentHandler paymentHandlerChain; // 注入组装好的责任链
@Autowired
public PaymentService(PaymentHandler paymentHandlerChain) {
this.paymentHandlerChain = paymentHandlerChain;
}
public PaymentResponse processPayment(PaymentRequest request) {
// 从责任链入口开始处理支付请求
return paymentHandlerChain.handle(request);
}
}
实战优势
解耦请求方与处理方:支付服务只需要调用责任链入口,不用知道具体有哪些处理器、每个处理器做什么。
灵活调整流程:新增 / 移除处理器(比如加 "优惠券抵扣处理器"),只需改配置,不用改业务代码;调整处理器顺序也很方便。
单一职责:每个处理器只做一件事(校验 / 风控 / 支付 / 通知),代码清晰、易维护。
扩展性强:后续要加新的处理步骤,直接写新的处理器类,接入链条即可,完全符合 "开闭原则"。
命令模式(Command Pattern)
模式概述
"请求封装大师":把一个请求(比如 "创建订单""扣减库存")封装成一个对象,将 "发请求的人" 和 "处理请求的人" 解耦 ------ 相当于餐厅里的菜单:顾客(请求方)只需要点菜单(命令对象),厨师(处理方)按菜单做菜,双方不用直接沟通。
SpringBoot 实战场景
SpringBoot 的事件处理、任务调度、事务回滚都常用它!比如订单下单流程:创建订单、扣减库存、处理支付,每个步骤封装成一个命令,既能按顺序执行,也能在出错时反向撤销(比如支付失败,就撤销 "扣减库存" 和 "创建订单")。
代码示例(订单下单流程)
bash
// 命令接口:定义执行和撤销行为
public interface Command {
void execute(); // 执行命令
void undo(); // 撤销命令
String getDescription(); // 获取命令描述(日志用)
}
// 具体命令1:创建订单命令
@Component
public class CreateOrderCommand implements Command {
private final OrderService orderService;
private final OrderRepository orderRepository;
private Order createdOrder; // 保存执行结果,用于撤销
private final Order orderToCreate; // 要创建的订单数据
// 通过构造器注入依赖和订单数据
public CreateOrderCommand(
OrderService orderService,
OrderRepository orderRepository,
Order orderToCreate) {
this.orderService = orderService;
this.orderRepository = orderRepository;
this.orderToCreate = orderToCreate;
}
@Override
public void execute() {
// 执行"创建订单"逻辑
createdOrder = orderService.createOrder(orderToCreate);
}
@Override
public void undo() {
// 撤销"创建订单":删除已创建的订单
if (createdOrder != null) {
orderRepository.delete(createdOrder);
createdOrder = null;
}
}
@Override
public String getDescription() {
return "创建订单(客户ID:" + orderToCreate.getCustomerId() + ")";
}
}
// 具体命令2:扣减库存命令
@Component
public class DeductInventoryCommand implements Command {
private final InventoryService inventoryService;
private final Long productId; // 商品ID
private final int quantity; // 扣减数量
private boolean executed = false; // 标记是否已执行,避免重复撤销
public DeductInventoryCommand(
InventoryService inventoryService,
Long productId,
int quantity) {
this.inventoryService = inventoryService;
this.productId = productId;
this.quantity = quantity;
}
@Override
public void execute() {
// 执行"扣减库存"逻辑
inventoryService.deductStock(productId, quantity);
executed = true;
}
@Override
public void undo() {
// 撤销"扣减库存":把库存加回去
if (executed) {
inventoryService.addStock(productId, quantity);
executed = false;
}
}
@Override
public String getDescription() {
return "扣减库存(商品ID:" + productId + ",数量:" + quantity + ")";
}
}
// 具体命令3:处理支付命令
@Component
public class ProcessPaymentCommand implements Command {
private final PaymentService paymentService;
private final PaymentRequest paymentRequest; // 支付请求数据
private String transactionId; // 保存支付交易ID,用于撤销(退款)
public ProcessPaymentCommand(
PaymentService paymentService,
PaymentRequest paymentRequest) {
this.paymentService = paymentService;
this.paymentRequest = paymentRequest;
}
@Override
public void execute() {
// 执行"处理支付"逻辑
PaymentResponse response = paymentService.processPayment(paymentRequest);
if (!response.isSuccess()) {
throw new PaymentFailedException("支付失败:" + response.getMessage());
}
transactionId = response.getTransactionId();
}
@Override
public void undo() {
// 撤销"处理支付":发起退款
if (transactionId != null) {
paymentService.refundPayment(transactionId);
transactionId = null;
}
}
@Override
public String getDescription() {
return "处理支付(订单ID:" + paymentRequest.getOrderId() + ",金额:" + paymentRequest.getAmount() + ")";
}
}
// 命令历史:记录已执行的命令(用于撤销)
@Component
public class CommandHistory {
// 用双端队列保存命令,支持先进后出(撤销时从最后一个命令开始)
private final Deque<Command> history = new ArrayDeque<>();
public void push(Command command) {
history.push(command);
}
public Command pop() {
return history.isEmpty() ? null : history.pop();
}
public boolean isEmpty() {
return history.isEmpty();
}
public List<Command> getExecutedCommands() {
return new ArrayList<>(history);
}
}
// 命令调用器:负责执行命令和处理撤销(核心调度)
@Service
public class CommandInvoker {
private final CommandHistory history;
private final TransactionTemplate transactionTemplate; // 事务模板,保证命令执行的原子性
@Autowired
public CommandInvoker(
CommandHistory history,
PlatformTransactionManager transactionManager) {
this.history = history;
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
// 执行单个命令(带事务)
public void executeCommand(Command command) {
transactionTemplate.execute(status -> {
try {
command.execute();
history.push(command); // 执行成功,记录到历史
return null;
} catch (Exception e) {
status.setRollbackOnly(); // 执行失败,回滚事务
throw e;
}
});
}
// 批量执行命令(按顺序执行,出错则批量撤销)
public void executeCommands(List<Command> commands) {
transactionTemplate.execute(status -> {
List<Command> executedCommands = new ArrayList<>();
try {
// 按顺序执行每个命令
for (Command command : commands) {
command.execute();
executedCommands.add(command);
}
// 所有命令执行成功,批量记录到历史
executedCommands.forEach(history::push);
return null;
} catch (Exception e) {
// 执行失败,反向撤销已执行的命令(比如先撤销"支付",再撤销"扣库存",最后撤销"创建订单")
Collections.reverse(executedCommands);
executedCommands.forEach(Command::undo);
status.setRollbackOnly();
throw e;
}
});
}
// 撤销最后一个执行的命令
public void undoLastCommand() {
Command command = history.pop();
if (command != null) {
transactionTemplate.execute(status -> {
try {
command.undo();
return null;
} catch (Exception e) {
status.setRollbackOnly();
history.push(command); // 撤销失败,把命令放回历史
throw e;
}
});
}
}
}
// 订单处理服务:组装命令并触发执行
@Service
public class OrderProcessingService {
private final CommandInvoker commandInvoker;
private final OrderService orderService;
private final InventoryService inventoryService;
private final PaymentService paymentService;
@Autowired
public OrderProcessingService(
CommandInvoker commandInvoker,
OrderService orderService,
InventoryService inventoryService,
PaymentService paymentService) {
this.commandInvoker = commandInvoker;
this.orderService = orderService;
this.inventoryService = inventoryService;
this.paymentService = paymentService;
}
public Order placeOrder(OrderRequest orderRequest) {
// 1. 组装订单数据
Order order = new Order();
order.setCustomerId(orderRequest.getCustomerId());
order.setItems(orderRequest.getItems());
order.setTotalAmount(calculateTotal(orderRequest.getItems()));
// 2. 组装支付请求数据
PaymentRequest paymentRequest = new PaymentRequest();
paymentRequest.setAmount(order.getTotalAmount());
paymentRequest.setCardNumber(orderRequest.getPaymentDetails().getCardNumber());
paymentRequest.setExpiryDate(orderRequest.getPaymentDetails().getExpiryDate());
paymentRequest.setCvv(orderRequest.getPaymentDetails().getCvv());
paymentRequest.setOrderId(order.getId()); // 关联订单ID
// 3. 组装命令列表(按执行顺序)
List<Command> commands = new ArrayList<>();
// 命令1:创建订单
commands.add(new CreateOrderCommand(orderService, orderService.getRepository(), order));
// 命令2:给每个商品扣减库存
for (OrderItem item : order.getItems()) {
commands.add(new DeductInventoryCommand(inventoryService, item.getProductId(), item.getQuantity()));
}
// 命令3:处理支付
commands.add(new ProcessPaymentCommand(paymentService, paymentRequest));
// 4. 调用命令执行器,批量执行命令
commandInvoker.executeCommands(commands);
return order;
}
// 计算订单总金额
private BigDecimal calculateTotal(List<OrderItem> items) {
return items.stream()
.map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
实战优势
解耦请求与执行:下单服务只需要组装命令,不用关心每个步骤怎么执行;执行逻辑封装在命令里,修改时互不影响。
支持撤销 / 重做:每个命令都有undo方法,出错时能按顺序撤销,保证数据一致性(比如支付失败,自动回滚库存和订单)。
组合复杂操作:把多个简单命令组合成复杂流程(如下单 = 创建订单 + 扣库存 + 支付),代码清晰且易扩展。
方便日志与监控:通过CommandHistory能记录所有执行过的命令,便于排查问题和做审计日志。
状态模式(State Pattern)
模式概述
对象状态管家:让对象的行为随着内部状态的变化而变化 ------ 比如订单有 "新建""已确认""已支付""已发货" 等状态,每个状态下能执行的操作不同("新建" 状态能确认,不能发货;"已支付" 状态能发货,不能取消),把每个状态的行为封装成独立类,避免一堆if-else判断。
SpringBoot 实战场景
订单状态管理、支付状态流转、工作流审批(比如请假单 "待审批""已批准""已驳回")都常用它!SpringBoot 中结合@Component能把每个状态托管给容器,实现状态的灵活切换。
代码示例(订单状态流转)
bash
// 订单状态接口:定义各状态支持的行为
public interface OrderState {
OrderState confirm(Order order); // 确认订单
OrderState pay(Order order); // 支付订单
OrderState ship(Order order); // 发货
OrderState deliver(Order order); // 确认收货
OrderState cancel(Order order); // 取消订单
OrderState refund(Order order); // 退款
String getStatus(); // 获取状态标识(如"NEW""PAID")
}
// 具体状态1:新建状态(NEW)
@Component
public class NewOrderState implements OrderState {
@Autowired
private ConfirmedOrderState confirmedOrderState; // 下一个状态:已确认
@Autowired
private CancelledOrderState cancelledOrderState; // 下一个状态:已取消
@Override
public OrderState confirm(Order order) {
// 执行"确认订单"逻辑:记录确认时间
order.setConfirmedAt(LocalDateTime.now());
return confirmedOrderState; // 切换到"已确认"状态
}
@Override
public OrderState pay(Order order) {
// 新建状态不能直接支付,抛异常
throw new IllegalStateException("未确认的订单无法支付!");
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("未确认未支付的订单无法发货!");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("未发货的订单无法确认收货!");
}
@Override
public OrderState cancel(Order order) {
// 执行"取消订单"逻辑:记录取消时间和原因
order.setCancelledAt(LocalDateTime.now());
order.setCancellationReason("客户在确认前取消订单");
return cancelledOrderState; // 切换到"已取消"状态
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("未支付的订单无法退款!");
}
@Override
public String getStatus() {
return "NEW";
}
}
// 具体状态2:已确认状态(CONFIRMED)
@Component
public class ConfirmedOrderState implements OrderState {
@Autowired
private PaidOrderState paidOrderState; // 下一个状态:已支付
@Autowired
private CancelledOrderState cancelledOrderState; // 下一个状态:已取消
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("订单已确认,无需重复确认!");
}
@Override
public OrderState pay(Order order) {
// 执行"支付订单"逻辑:记录支付时间
order.setPaidAt(LocalDateTime.now());
return paidOrderState; // 切换到"已支付"状态
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("未支付的订单无法发货!");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("未发货的订单无法确认收货!");
}
@Override
public OrderState cancel(Order order) {
order.setCancelledAt(LocalDateTime.now());
order.setCancellationReason("客户在支付前取消订单");
return cancelledOrderState;
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("未支付的订单无法退款!");
}
@Override
public String getStatus() {
return "CONFIRMED";
}
}
// 具体状态3:已支付状态(PAID)
@Component
public class PaidOrderState implements OrderState {
@Autowired
private ShippedOrderState shippedOrderState; // 下一个状态:已发货
@Autowired
private RefundedOrderState refundedOrderState; // 下一个状态:已退款
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("订单已支付,无需重复确认!");
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("订单已支付,无需重复支付!");
}
@Override
public OrderState ship(Order order) {
// 执行"发货"逻辑:记录发货时间
order.setShippedAt(LocalDateTime.now());
return shippedOrderState; // 切换到"已发货"状态
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("未发货的订单无法确认收货!");
}
@Override
public OrderState cancel(Order order) {
throw new IllegalStateException("已支付的订单无法取消,请申请退款!");
}
@Override
public OrderState refund(Order order) {
// 执行"退款"逻辑:记录退款时间
order.setRefundedAt(LocalDateTime.now());
return refundedOrderState; // 切换到"已退款"状态
}
@Override
public String getStatus() {
return "PAID";
}
}
// 具体状态4:已发货状态(SHIPPED)
@Component
public class ShippedOrderState implements OrderState {
@Autowired
private DeliveredOrderState deliveredOrderState; // 下一个状态:已收货
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("订单已发货,无需重复确认!");
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("订单已支付,无需重复支付!");
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("订单已发货,无需重复发货!");
}
@Override
public OrderState deliver(Order order) {
// 执行"确认收货"逻辑:记录收货时间
order.setDeliveredAt(LocalDateTime.now());
return deliveredOrderState; // 切换到"已收货"状态
}
@Override
public OrderState cancel(Order order) {
throw new IllegalStateException("已发货的订单无法取消,可申请退货退款!");
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("已发货未收货的订单,需先确认收货/退货后再退款!");
}
@Override
public String getStatus() {
return "SHIPPED";
}
}
// 具体状态5:已收货状态(DELIVERED)
@Component
public class DeliveredOrderState implements OrderState {
@Autowired
private RefundedOrderState refundedOrderState; // 下一个状态:已退款
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("订单已完成收货,无需确认!");
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("订单已支付,无需重复支付!");
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("订单已收货,无需发货!");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("订单已完成收货,无需重复确认!");
}
@Override
public OrderState cancel(Order order) {
throw new IllegalStateException("已收货的订单无法取消,可申请售后退款!");
}
@Override
public OrderState refund(Order order) {
// 执行"售后退款"逻辑:记录退款时间
order.setRefundedAt(LocalDateTime.now());
return refundedOrderState; // 切换到"已退款"状态
}
@Override
public String getStatus() {
return "DELIVERED";
}
}
// 具体状态6:已取消状态(CANCELLED)
@Component
public class CancelledOrderState implements OrderState {
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("已取消的订单无法确认!");
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("已取消的订单无法支付!");
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("已取消的订单无法发货!");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("已取消的订单无法确认收货!");
}
@Override
public OrderState cancel(Order order) {
throw new IllegalStateException("订单已取消,无需重复取消!");
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("未支付的取消订单无需退款!");
}
@Override
public String getStatus() {
return "CANCELLED";
}
}
// 具体状态7:已退款状态(REFUNDED)
@Component
public class RefundedOrderState implements OrderState {
@Override
public OrderState confirm(Order order) {
throw new IllegalStateException("已退款的订单无法确认!");
}
@Override
public OrderState pay(Order order) {
throw new IllegalStateException("已退款的订单无需支付!");
}
@Override
public OrderState ship(Order order) {
throw new IllegalStateException("已退款的订单无法发货!");
}
@Override
public OrderState deliver(Order order) {
throw new IllegalStateException("已退款的订单无法确认收货!");
}
@Override
public OrderState cancel(Order order) {
throw new IllegalStateException("已退款的订单无需取消!");
}
@Override
public OrderState refund(Order order) {
throw new IllegalStateException("订单已退款,无需重复退款!");
}
@Override
public String getStatus() {
return "REFUNDED";
}
}
// 订单实体:状态上下文(持有当前状态,触发状态切换)
@Entity
@Table(name = "orders")
@Data
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long customerId;
@OneToMany(cascade = CascadeType.ALL)
private List<OrderItem> items;
private BigDecimal totalAmount;
// 状态相关时间字段
private LocalDateTime createdAt = LocalDateTime.now();
private LocalDateTime confirmedAt;
private LocalDateTime paidAt;
private LocalDateTime shippedAt;
private LocalDateTime deliveredAt;
private LocalDateTime cancelledAt;
private String cancellationReason;
private LocalDateTime refundedAt;
@Transient
private OrderState currentState; // 持有当前状态(不持久化到数据库)
@Column(name = "status")
private String status = "NEW"; // 持久化状态标识
// 加载实体时初始化状态(从数据库status字段恢复currentState)
@PostLoad
private void onLoad() {
initState();
}
private void initState() {
if (status == null) status = "NEW";
// 根据状态标识,从Spring容器获取对应的状态实例
switch (status) {
case "NEW":
currentState = SpringContextHolder.getBean(NewOrderState.class);
break;
case "CONFIRMED":
currentState = SpringContextHolder.getBean(ConfirmedOrderState.class);
break;
case "PAID":
currentState = SpringContextHolder.getBean(PaidOrderState.class);
break;
case "SHIPPED":
currentState = SpringContextHolder.getBean(ShippedOrderState.class);
break;
case "DELIVERED":
currentState = SpringContextHolder.getBean(DeliveredOrderState.class);
break;
case "CANCELLED":
currentState = SpringContextHolder.getBean(CancelledOrderState.class);
break;
case "REFUNDED":
currentState = SpringContextHolder.getBean(RefundedOrderState.class);
break;
default:
throw new IllegalStateException("未知订单状态:" + status);
}
}
// 对外暴露的状态切换方法(调用当前状态的对应方法)
public void confirm() {
currentState = currentState.confirm(this);
status = currentState.getStatus(); // 更新持久化的状态标识
}
public void pay() {
currentState = currentState.pay(this);
status = currentState.getStatus();
}
public void ship() {
currentState = currentState.ship(this);
status = currentState.getStatus();
}
public void deliver() {
currentState = currentState.deliver(this);
status = currentState.getStatus();
}
public void cancel() {
currentState = currentState.cancel(this);
status = currentState.getStatus();
}
public void refund() {
currentState = currentState.refund(this);
status = currentState.getStatus();
}
}
// Spring上下文工具:给实体类注入Spring Bean(关键)
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
// 静态方法获取Bean(实体类无法直接@Autowired,用这个工具类)
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
}
// 订单服务:业务层调用状态切换
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private NewOrderState initialState; // 初始状态:新建
@Transactional
public Order createOrder(Long customerId, List<OrderItem> items, BigDecimal totalAmount) {
Order order = new Order();
order.setCustomerId(customerId);
order.setItems(items);
order.setTotalAmount(totalAmount);
order.setCurrentState(initialState); // 设置初始状态
return orderRepository.save(order);
}
@Transactional
public Order confirmOrder(Long orderId) {
Order order = findOrderById(orderId);
order.confirm(); // 触发状态切换:NEW → CONFIRMED
return orderRepository.save(order);
}
@Transactional
public Order payOrder(Long orderId) {
Order order = findOrderById(orderId);
order.pay(); // 触发状态切换:CONFIRMED → PAID
return orderRepository.save(order);
}
@Transactional
public Order shipOrder(Long orderId) {
Order order = findOrderById(orderId);
order.ship(); // 触发状态切换:PAID → SHIPPED
return orderRepository.save(order);
}
@Transactional
public Order deliverOrder(Long orderId) {
Order order = findOrderById(orderId);
order.deliver(); // 触发状态切换:SHIPPED → DELIVERED
return orderRepository.save(order);
}
@Transactional
public Order cancelOrder(Long orderId) {
Order order = findOrderById(orderId);
order.cancel(); // 触发状态切换(比如NEW → CANCELLED)
return orderRepository.save(order);
}
@Transactional
public Order refundOrder(Long orderId) {
Order order = findOrderById(orderId);
order.refund(); // 触发状态切换(比如PAID → REFUNDED)
return orderRepository.save(order);
}
private Order findOrderById(Long orderId) {
return orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException("订单不存在:" + orderId));
}
// 给外部暴露Repository(命令模式里要用)
public OrderRepository getRepository() {
return orderRepository;
}
}
// 自定义异常:订单不存在
public class OrderNotFoundException extends RuntimeException {
public OrderNotFoundException(String message) {
super(message);
}
}
// 自定义异常:支付失败
public class PaymentFailedException extends RuntimeException {
public PaymentFailedException(String message) {
super(message);
}
}
// 自定义异常:报表导出失败
public class ReportExportException extends RuntimeException {
public ReportExportException(String message, Throwable cause) {
super(message, cause);
}
实战优势
状态行为封装:每个状态的行为都在独立类里,比如 "新建状态能做什么" 全在NewOrderState里,代码清晰,不用翻一堆if-else。
状态切换清晰:状态之间的流转规则(比如 NEW→CONFIRMED,CONFIRMED→PAID)由状态类自己控制,逻辑不混乱。
易扩展新状态:新增 "已拒收" 状态,只需写RejectedOrderState类,实现OrderState接口,修改状态流转规则即可,不用改原有状态代码。
避免状态混乱:每个状态只暴露自己支持的行为,比如 "已支付" 状态不能调用cancel(),从代码层面防止非法操作。
以下是一些在开发过程中使用频率不是这么高的设计模式
桥接模式(Bridge Pattern)
核心思想 :将抽象部分与实现部分分离,使它们可以独立地变化。
实现方式 :通过定义抽象类和实现类,将它们的变化解耦。
应用场景:不同图形API(OpenGL/Vulkan)与形状(圆/方)的组合。
优点 :
解耦 :抽象和实现的解耦,使得它们可以独立变化。
灵活性 :可以独立地扩展抽象和实现。
Java 示例:
bash
// 实现接口
public interface Implementor {
void operation();
}
// 具体实现A
public class ConcreteImplementorA implements Implementor {
@Override
public void operation() {
System.out.println("ConcreteImplementorA operation");
}
}
// 具体实现B
public class ConcreteImplementorB implements Implementor {
@Override
public void operation() {
System.out.println("ConcreteImplementorB operation");
}
}
// 抽象类
public abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
// 扩展抽象类
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
implementor.operation(); // 委托给实现类
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Implementor implementorA = new ConcreteImplementorA();
Abstraction abstraction = new RefinedAbstraction(implementorA);
abstraction.operation();
Implementor implementorB = new ConcreteImplementorB();
abstraction = new RefinedAbstraction(implementorB);
abstraction.operation();
}
}
组合模式(Composite Pattern)
核心思想: 将对象组合成树形结构以表示部分-整体层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
实现方式 :通过定义一个组件接口,将叶子节点和容器节点统一处理。
应用场景:文件系统(文件/文件夹统一处理)、UI 容器组件)。
优点:
一致性 :对单个对象和组合对象的一致性操作。
简化客户端代码 :客户端代码可以统一处理叶子节点和容器节点。
Java 示例:
bash
import java.util.ArrayList;
import java.util.List;
// 组件接口
public interface Component {
void operation();
}
// 叶子节点
public class Leaf implements Component {
@Override
public void operation() {
System.out.println("Leaf operation");
}
}
// 容器节点
public class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Composite root = new Composite();
Component leaf1 = new Leaf();
Component leaf2 = new Leaf();
root.add(leaf1);
root.add(leaf2);
root.operation(); // 统一调用
}
}
外观模式(Facade Pattern)
核心思想 :为子系统中的一组接口提供一个一致的界面,使得子系统更容易使用。
实现方式 :通过定义一个外观类来封装子系统的复杂性,提供简化的接口。
应用场景:Spring 的 JdbcUtils 封装数据库操作细节。
优点:
简化使用 :提供简单的接口来访问复杂的子系统。
解耦 :将客户端与子系统解耦。
Java 示例:
bash
// 子系统类A
public class SubsystemA {
public void operationA() {
System.out.println("SubsystemA operationA");
}
}
// 子系统类B
public class SubsystemB {
public void operationB() {
System.out.println("SubsystemB operationB");
}
}
// 外观类
public class Facade {
private SubsystemA subsystemA;
private SubsystemB subsystemB;
public Facade() {
subsystemA = new SubsystemA();
subsystemB = new SubsystemB();
}
public void operation() {
subsystemA.operationA();
subsystemB.operationB();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.operation(); // 通过外观类调用子系统
}
}
享元模式(Flyweight Pattern)
核心思想 :运用共享技术有效地支持大量细粒度的对象。
实现方式 :通过将对象的共享部分与独享部分分开,将共享部分提取出来。
应用场景:棋类游戏的棋子对象复用、字符串常量池。
优点:
节省内存 :通过共享来减少内存使用。
提高性能 :减少对象创建和管理的开销。
Java 示例:
bash
import java.util.HashMap;
import java.util.Map;
// 享元接口
public interface Flyweight {
void operation(String extrinsicState);
}
// 具体享元类
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
}
}
// 享元工厂
public class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
Flyweight flyweight = flyweights.get(key);
if (flyweight == null) {
flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
}
return flyweight;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
Flyweight flyweight1 = factory.getFlyweight("A");
Flyweight flyweight2 = factory.getFlyweight("B");
flyweight1.operation("1");
flyweight2.operation("2");
}
}
代理模式(Proxy Pattern)
核心思想 :为其他对象提供一种代理以控制对这个对象的访问。
实现方式 :通过定义代理类来控制对真实对象的访问。
应用场景:AOP 实现、RPC 调用。
优点:
控制访问 :可以在代理中实现对真实对象的控制。
增强功能 :可以在代理中增加额外的功能,如延迟加载。
Java 示例:
bash
// 抽象主题接口
public interface Subject {
void request();
}
// 真实主题类
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject request");
}
}
// 代理类
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request(); // 代理控制对真实主题的访问
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request(); // 通过代理访问真实主题
}
}
迭代器模式(Iterator Pattern)
核心思想 :提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部表示。
实现方式 :通过定义迭代器接口和具体迭代器类来遍历集合对象中的元素。
应用场景:集合类、数据库查询结果等。
优点:
简化访问 :提供统一的访问方式。
解耦 :容器和迭代器解耦。
Java 示例:
bash
import java.util.ArrayList;
import java.util.List;
// 迭代器接口
public interface Iterator {
boolean hasNext();
Object next();
}
// 具体迭代器类
public class ConcreteIterator implements Iterator {
private List<Object> items;
private int position;
public ConcreteIterator(List<Object> items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.size();
}
@Override
public Object next() {
return items.get(position++);
}
}
// 聚合类
public class Aggregate {
private List<Object> items = new ArrayList<>();
public void add(Object item) {
items.add(item);
}
public Iterator iterator() {
return new ConcreteIterator(items);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Aggregate aggregate = new Aggregate();
aggregate.add("Item 1");
aggregate.add("Item 2");
Iterator iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
中介者模式(Mediator Pattern)
核心思想: 定义一个对象来封装一组对象之间的交互,使得对象之间的耦合松散,从而使得它们可以独立地改变。
实现方式 :通过定义中介者接口和具体中介者类来协调对象之间的交互。
应用场景:聊天室消息转发、MVC 控制器。
优点:
降低耦合 :将对象间的交互集中在中介者中。
易于维护 :中介者可以集中处理复杂的交互逻辑。
Java 示例:
bash
// 中介者接口
public interface Mediator {
void notify(Component sender, String event);
}
// 组件接口
public abstract class Component {
protected Mediator mediator;
public Component(Mediator mediator) {
this.mediator = mediator;
}
public abstract void handleEvent(String event);
}
// 具体组件A
public class ComponentA extends Component {
public ComponentA(Mediator mediator) {
super(mediator);
}
@Override
public void handleEvent(String event) {
System.out.println("ComponentA handling event: "
+ event);
}
public void triggerEvent(String event) {
mediator.notify(this, event);
}
}
// 具体组件B
public class ComponentB extends Component {
public ComponentB(Mediator mediator) {
super(mediator);
}
@Override
public void handleEvent(String event) {
System.out.println("ComponentB handling event: " + event);
}
}
// 具体中介者类
public class ConcreteMediator implements Mediator {
private ComponentA componentA;
private ComponentB componentB;
public void setComponentA(ComponentA componentA) {
this.componentA = componentA;
}
public void setComponentB(ComponentB componentB) {
this.componentB = componentB;
}
@Override
public void notify(Component sender, String event) {
if (sender == componentA) {
componentB.handleEvent(event);
} else if (sender == componentB) {
componentA.handleEvent(event);
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
ComponentA componentA = new ComponentA(mediator);
ComponentB componentB = new ComponentB(mediator);
mediator.setComponentA(componentA);
mediator.setComponentB(componentB);
componentA.triggerEvent("Event A");
componentB.handleEvent("Event B");
}
}
备忘录模式(Memento Pattern)
核心思想 :在不暴露对象内部状态的情况下,捕获一个对象的内部状态,并在该对象外部保存这个状态。可以在以后将对象恢复到保存的状态。
实现方式 :通过定义备忘录类来保存对象的状态,并通过发起人类和恢复者类来实现状态的恢复。
应用场景:文本编辑器撤销功能、游戏存档。
优点:
状态恢复 :可以在需要的时候恢复对象的状态。
封装性 :不暴露对象的内部状态。
Java 示例:
bash
// 备忘录类
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人类
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
// 管理者类
public class Caretaker {
private Memento memento;
public void saveMemento(Memento memento) {
this.memento = memento;
}
public Memento retrieveMemento() {
return memento;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State1");
caretaker.saveMemento(originator.saveStateToMemento());
originator.setState("State2");
System.out.println("Current State: " + originator.getState());
originator.getStateFromMemento(caretaker.retrieveMemento());
System.out.println("Restored State: " + originator.getState());
}
}
解释器模式(Interpreter Pattern)
核心思想 :给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
实现方式 :通过定义解释器类和表达式类,将文法规则和解释逻辑分开。
应用场景:编译器、SQL 解析器、游戏规则引擎。
优点:
易于扩展 :可以通过增加新的终结符和非终结符来扩展语法。
灵活性 :可以定义复杂的语言规则。
Java 示例:
bash
import java.util.HashMap;
import java.util.Map;
// 表达式接口
public interface Expression {
int interpret(Map<String, Integer> context);
}
// 终结符表达式
public class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret(Map<String, Integer> context) {
return number;
}
}
// 非终结符表达式
public class PlusExpression implements Expression {
private Expression left;
private Expression right;
public PlusExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Map<String, Integer> context) {
return left.interpret(context) + right.interpret(context);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Expression expression = new PlusExpression(new NumberExpression(5), new NumberExpression(3));
Map<String, Integer> context = new HashMap<>();
int result = expression.interpret(context);
System.out.println("Result: " + result); // 输出结果 8
}
}
访问者模式(Visitor Pattern)
核心思想 :表示一个作用于某对象结构中的各元素的操作,它可以在不改变元素类的前提下定义作用于这些元素的新操作。
实现方式 :通过定义访问者接口和具体访问者类,将操作和对象结构分离,使得可以在不改变对象结构的情况下增加新的操作。
应用场景:编译器语法树分析、复杂对象结构遍历。
优点:
扩展性 :可以在不改变对象结构的情况下增加新的操作。
操作集中 :操作被集中在访问者中,使得相关操作更易于维护。
Java 示例:
bash
import java.util.ArrayList;
import java.util.List;
// 访问者接口
public interface Visitor {
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}
// 具体访问者A
public class ConcreteVisitorA implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("Visitor A visiting Element A");
}
@Override
public void visit(ConcreteElementB elementB) {
System.out.println("Visitor A visiting Element B");
}
}
// 具体访问者B
public class ConcreteVisitorB implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("Visitor B visiting Element A");
}
@Override
public void visit(ConcreteElementB elementB) {
System.out.println("Visitor B visiting Element B");
}
}
// 元素接口
public interface Element {
void accept(Visitor visitor);
}
// 具体元素A
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 具体元素B
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 对象结构
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void addElement(Element element) {
elements.add(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ObjectStructure structure = new ObjectStructure();
structure.addElement(new ConcreteElementA());
structure.addElement(new ConcreteElementB());
Visitor visitorA = new ConcreteVisitorA();
structure.accept(visitorA); // Visitor A visiting elements
Visitor visitorB = new ConcreteVisitorB();
structure.accept(visitorB); // Visitor B visiting elements
}
}