2026/6/20 12:11:34
网站建设
项目流程
大型企业网站制作,网站首页图片做多大,百度平台营销,制作网站怎么做的目录
一、 创建型模式#xff1a;解决对象创建的复杂问题
1. 单例模式#xff1a;全局配置管理#xff08;无人售货柜项目#xff09;
场景痛点
解决方案#xff1a;懒汉式单例#xff08;双重检查锁#xff0c;线程安全#xff09;
应用效果
框架关联
2. 工厂方…目录一、 创建型模式解决对象创建的复杂问题1. 单例模式全局配置管理无人售货柜项目场景痛点解决方案懒汉式单例双重检查锁线程安全应用效果框架关联2. 工厂方法模式支付方式适配电商项目场景痛点解决方案工厂方法模式定义支付工厂子类实现具体支付方式步骤 1定义抽象产品支付接口步骤 2实现具体产品各支付方式步骤 3定义抽象工厂 具体工厂步骤 4业务层调用无需关注具体实现应用效果二、 结构型模式优化代码结构降低耦合1. 代理模式接口权限控制无人售货柜后台场景痛点解决方案动态代理模式JDK 动态代理AOP 思想步骤 1定义业务接口步骤 2实现目标对象真实业务逻辑步骤 3实现代理类权限校验逻辑步骤 4业务层使用代理应用效果框架关联2. 装饰器模式IO 流增强无人售货柜日志模块场景痛点解决方案装饰器模式动态给日志对象添加功能步骤 1定义抽象组件日志接口步骤 2实现基础组件本地文件日志步骤 3实现装饰器增强功能步骤 4业务层组合装饰器应用效果框架关联三、 行为型模式规范对象交互提升逻辑灵活性1. 策略模式订单价格计算电商项目场景痛点解决方案策略模式封装不同优惠策略动态切换步骤 1定义策略接口步骤 2实现具体策略步骤 3策略上下文统一调用入口步骤 4业务层调用应用效果2. 命令模式设备指令下发无人售货柜项目场景痛点解决方案命令模式封装指令为对象解耦指令发送者与执行者步骤 1定义抽象命令步骤 2实现具体命令步骤 3实现命令调用者指令管理器步骤 4控制器调用应用效果四、 设计模式选型核心思路五、 总结设计模式的价值在于解决真实业务场景中的耦合、扩展、复用问题。本文结合电商订单、无人售货柜、支付系统等真实项目场景拆解常用设计模式的落地思路与代码实现聚焦 “为什么用”“怎么用”“解决什么问题” 三大核心。一、 创建型模式解决对象创建的复杂问题创建型模式的核心目标是封装对象创建细节让调用方无需关注初始化逻辑提升创建灵活性。1. 单例模式全局配置管理无人售货柜项目场景痛点无人售货柜项目中DeviceConfig包含设备的串口配置、网络参数、货道信息等全局配置全系统需共享同一实例且初始化时需从本地文件加载配置避免重复 IO 操作。解决方案懒汉式单例双重检查锁线程安全java运行/** * 售货柜设备配置单例模式 * 核心全局唯一实例 延迟初始化 线程安全 */ public class DeviceConfig { // 1. 私有静态变量volatile 禁止指令重排 private static volatile DeviceConfig instance; // 配置参数 private String serialPort; // 串口地址 private int baudRate; // 波特率 private MapInteger, String channelMap; // 货道映射 // 2. 私有构造器禁止外部new private DeviceConfig() { // 从本地配置文件加载参数实际项目用Properties/YAML loadConfigFromFile(); } // 3. 公共静态方法双重检查锁懒加载 public static DeviceConfig getInstance() { if (instance null) { // 第一次检查避免不必要的锁 synchronized (DeviceConfig.class) { // 加锁 if (instance null) { // 第二次检查防止多线程重复创建 instance new DeviceConfig(); } } } return instance; } // 加载配置文件 private void loadConfigFromFile() { // 实际逻辑读取config/device.properties this.serialPort /dev/ttyUSB0; this.baudRate 9600; this.channelMap new HashMap(); channelMap.put(1, 可乐); channelMap.put(2, 薯片); } // getter方法 public String getSerialPort() { return serialPort; } public MapInteger, String getChannelMap() { return channelMap; } }应用效果全系统共享同一配置实例避免重复加载文件导致的性能损耗延迟初始化首次调用getInstance()才加载配置减少项目启动时间线程安全双重检查锁保证多线程环境下不会创建多个实例。框架关联Spring 容器中的默认 Bean 是单例模式底层通过DefaultSingletonBeanRegistry实现原理与上述案例一致。2. 工厂方法模式支付方式适配电商项目场景痛点电商订单支付模块需支持微信支付、支付宝、银联三种方式后续可能新增 “云闪付”。若直接在业务代码中用if-else判断支付类型会导致代码臃肿、扩展困难新增支付方式需修改原有代码违反开闭原则。解决方案工厂方法模式定义支付工厂子类实现具体支付方式步骤 1定义抽象产品支付接口java运行/** * 抽象支付产品 */ public interface Payment { // 发起支付 String pay(String orderId, BigDecimal amount); // 查询支付状态 boolean queryPayStatus(String orderId); }步骤 2实现具体产品各支付方式java运行// 微信支付实现 public class WechatPayment implements Payment { Override public String pay(String orderId, BigDecimal amount) { // 调用微信支付SDK return 微信支付下单成功订单号 orderId 金额 amount; } Override public boolean queryPayStatus(String orderId) { return true; // 模拟查询结果 } } // 支付宝支付实现 public class AlipayPayment implements Payment { Override public String pay(String orderId, BigDecimal amount) { return 支付宝支付下单成功订单号 orderId 金额 amount; } Override public boolean queryPayStatus(String orderId) { return true; } }步骤 3定义抽象工厂 具体工厂java运行/** * 抽象支付工厂 */ public interface PaymentFactory { Payment createPayment(); } // 微信支付工厂 public class WechatPaymentFactory implements PaymentFactory { Override public Payment createPayment() { return new WechatPayment(); } } // 支付宝支付工厂 public class AlipayPaymentFactory implements PaymentFactory { Override public Payment createPayment() { return new AlipayPayment(); } }步骤 4业务层调用无需关注具体实现java运行Service public class OrderPayService { // 根据支付类型获取工厂创建支付实例 public String doPay(String orderId, BigDecimal amount, String payType) { PaymentFactory factory; switch (payType) { case WECHAT: factory new WechatPaymentFactory(); break; case ALIPAY: factory new AlipayPaymentFactory(); break; default: throw new IllegalArgumentException(不支持的支付类型); } Payment payment factory.createPayment(); return payment.pay(orderId, amount); } }应用效果开闭原则新增 “云闪付” 只需添加CloudPayment和CloudPaymentFactory无需修改原有业务代码职责单一每种支付方式的逻辑封装在独立类中便于维护和测试解耦业务层只依赖Payment接口不依赖具体实现类。二、 结构型模式优化代码结构降低耦合结构型模式的核心目标是通过类 / 对象的组合解决结构臃肿、扩展困难的问题。1. 代理模式接口权限控制无人售货柜后台场景痛点无人售货柜后台的DeviceManageService包含设备重启、货道修改、参数配置等敏感接口需对调用方进行权限校验如只有管理员角色才能调用。若直接在接口中添加权限逻辑会导致业务逻辑与权限逻辑耦合且重复代码多。解决方案动态代理模式JDK 动态代理AOP 思想步骤 1定义业务接口java运行/** * 设备管理接口被代理接口 */ public interface DeviceManageService { void restartDevice(String deviceId); // 重启设备 void updateChannel(String deviceId, MapInteger, String channelMap); // 修改货道 }步骤 2实现目标对象真实业务逻辑java运行/** * 真实设备管理服务 */ Service public class DeviceManageServiceImpl implements DeviceManageService { Override public void restartDevice(String deviceId) { System.out.println(重启设备 deviceId); // 实际逻辑发送重启指令到硬件 } Override public void updateChannel(String deviceId, MapInteger, String channelMap) { System.out.println(修改设备货道 deviceId 货道映射 channelMap); } }步骤 3实现代理类权限校验逻辑java运行/** * 权限代理类JDK 动态代理 * 核心在不修改目标对象的前提下增强方法功能 */ public class PermissionProxy implements InvocationHandler { // 目标对象被代理的真实对象 private final Object target; public PermissionProxy(Object target) { this.target target; } /** * 代理方法增强目标方法的执行逻辑 */ Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1. 前置增强权限校验 checkPermission(); // 2. 执行目标方法 Object result method.invoke(target, args); // 3. 后置增强记录操作日志 logOperation(method.getName(), args); return result; } // 权限校验逻辑 private void checkPermission() { // 实际逻辑从 ThreadLocal 获取当前用户角色 String role UserContextHolder.getCurrentUser().getRole(); if (!ADMIN.equals(role)) { throw new SecurityException(无权限操作设备); } } // 日志记录逻辑 private void logOperation(String methodName, Object[] args) { System.out.println(执行设备操作 methodName 参数 Arrays.toString(args)); } // 获取代理对象的工具方法 public static Object getProxy(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new PermissionProxy(target) ); } }步骤 4业务层使用代理java运行Configuration public class DeviceConfig { Bean public DeviceManageService deviceManageService() { // 创建真实对象 DeviceManageServiceImpl target new DeviceManageServiceImpl(); // 生成代理对象并返回 return (DeviceManageService) PermissionProxy.getProxy(target); } } // 控制器调用 RestController RequestMapping(/device) public class DeviceController { Autowired private DeviceManageService deviceManageService; PostMapping(/restart/{deviceId}) public String restart(PathVariable String deviceId) { deviceManageService.restartDevice(deviceId); return 操作成功; } }应用效果解耦权限校验、日志记录与业务逻辑完全分离符合单一职责原则可复用代理逻辑可复用在其他需要权限控制的接口上无侵入无需修改目标对象的代码只需通过代理增强功能。框架关联Spring AOP 的底层就是动态代理模式Transactional、Cacheable等注解的实现原理与上述案例一致。2. 装饰器模式IO 流增强无人售货柜日志模块场景痛点无人售货柜的日志模块需要记录设备操作日志要求日志内容需格式化包含时间、设备 ID、操作类型日志需同时写入本地文件 上传到云端后续可能新增 “加密日志” 功能。若直接写一个LogService包含所有逻辑会导致功能耦合、扩展困难。解决方案装饰器模式动态给日志对象添加功能步骤 1定义抽象组件日志接口java运行/** * 抽象日志组件 */ public interface Logger { void log(String deviceId, String content); }步骤 2实现基础组件本地文件日志java运行/** * 基础日志组件写入本地文件 */ public class FileLogger implements Logger { Override public void log(String deviceId, String content) { // 实际逻辑写入本地文件 /logs/device-{deviceId}.log System.out.println(【本地日志】设备 deviceId 内容 content); } }步骤 3实现装饰器增强功能java运行/** * 装饰器抽象类遵循抽象组件接口持有组件引用 */ public abstract class LoggerDecorator implements Logger { protected Logger logger; public LoggerDecorator(Logger logger) { this.logger logger; } } // 装饰器1格式化日志添加时间戳 public class FormatLoggerDecorator extends LoggerDecorator { public FormatLoggerDecorator(Logger logger) { super(logger); } Override public void log(String deviceId, String content) { // 格式化内容[时间] 设备ID - 内容 String formatContent String.format([%s] %s - %s, LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), deviceId, content); // 调用被装饰者的方法 logger.log(deviceId, formatContent); } } // 装饰器2上传云端日志 public class CloudLoggerDecorator extends LoggerDecorator { public CloudLoggerDecorator(Logger logger) { super(logger); } Override public void log(String deviceId, String content) { // 1. 先执行被装饰者的逻辑写入本地 logger.log(deviceId, content); // 2. 新增功能上传到云端 uploadToCloud(deviceId, content); } private void uploadToCloud(String deviceId, String content) { System.out.println(【云端日志】设备 deviceId 内容 content); } }步骤 4业务层组合装饰器java运行Service public class DeviceLogService { private final Logger logger; // 构造器注入组合装饰器 public DeviceLogService() { // 基础组件本地日志 Logger baseLogger new FileLogger(); // 装饰器1格式化 Logger formatLogger new FormatLoggerDecorator(baseLogger); // 装饰器2上传云端 this.logger new CloudLoggerDecorator(formatLogger); } public void recordLog(String deviceId, String content) { logger.log(deviceId, content); } } // 调用示例 deviceLogService.recordLog(DEVICE001, 货道1补货完成); // 输出结果 // 【本地日志】设备DEVICE001内容[2025-12-26T15:30:00] DEVICE001 - 货道1补货完成 // 【云端日志】设备DEVICE001内容[2025-12-26T15:30:00] DEVICE001 - 货道1补货完成应用效果功能动态组合按需组合装饰器如只需要本地日志则不加CloudLoggerDecorator开闭原则新增 “加密日志” 只需添加EncryptLoggerDecorator无需修改原有代码职责单一每个装饰器只负责一个增强功能便于维护。框架关联JDK 的IO 流是装饰器模式的经典实现如BufferedInputStream装饰FileInputStream实现缓冲功能。三、 行为型模式规范对象交互提升逻辑灵活性行为型模式的核心目标是定义对象间的通信方式解决行为协调、职责分配的问题。1. 策略模式订单价格计算电商项目场景痛点电商订单结算时需根据用户等级、优惠券、促销活动计算最终价格普通用户原价VIP 用户9 折新用户满 100 减 20叠加优惠券再减固定金额。若用if-else实现会导致逻辑混乱、扩展困难新增优惠类型需修改结算方法。解决方案策略模式封装不同优惠策略动态切换步骤 1定义策略接口java运行/** * 订单优惠策略接口 */ public interface DiscountStrategy { /** * 计算优惠后价格 * param order 订单信息 * return 优惠后金额 */ BigDecimal calculate(Order order); /** * 获取策略类型 */ String getType(); }步骤 2实现具体策略java运行// 策略1普通用户无优惠 public class NormalUserStrategy implements DiscountStrategy { Override public BigDecimal calculate(Order order) { return order.getTotalAmount(); } Override public String getType() { return NORMAL; } } // 策略2VIP用户9折 public class VipUserStrategy implements DiscountStrategy { Override public BigDecimal calculate(Order order) { return order.getTotalAmount().multiply(new BigDecimal(0.9)); } Override public String getType() { return VIP; } } // 策略3新用户满100减20 public class NewUserStrategy implements DiscountStrategy { Override public BigDecimal calculate(Order order) { BigDecimal amount order.getTotalAmount(); return amount.compareTo(new BigDecimal(100)) 0 ? amount.subtract(new BigDecimal(20)) : amount; } Override public String getType() { return NEW; } }步骤 3策略上下文统一调用入口java运行/** * 策略上下文封装策略选择逻辑提供统一调用入口 */ Service public class DiscountContext { // 策略容器Spring 启动时自动注入所有策略实现类 private final MapString, DiscountStrategy strategyMap; // 构造器注入Spring 会自动将所有 DiscountStrategy 实现类放入 Map public DiscountContext(ListDiscountStrategy strategies) { this.strategyMap new HashMap(); for (DiscountStrategy strategy : strategies) { strategyMap.put(strategy.getType(), strategy); } } /** * 计算订单最终价格 */ public BigDecimal calculateFinalPrice(Order order) { // 1. 获取用户类型对应的策略 String userType order.getUser().getType(); DiscountStrategy strategy strategyMap.getOrDefault(userType, new NormalUserStrategy()); // 2. 计算基础优惠价格 BigDecimal discountAmount strategy.calculate(order); // 3. 叠加优惠券优惠 if (order.getCoupon() ! null) { discountAmount discountAmount.subtract(order.getCoupon().getAmount()); } // 4. 价格不能小于0 return discountAmount.compareTo(BigDecimal.ZERO) 0 ? BigDecimal.ZERO : discountAmount; } }步骤 4业务层调用java运行Service public class OrderService { Autowired private DiscountContext discountContext; public BigDecimal checkout(Order order) { return discountContext.calculateFinalPrice(order); } }应用效果消除 if-else策略选择逻辑由strategyMap自动完成代码更简洁灵活扩展新增 “黑钻用户 8 折” 策略只需添加BlackDiamondStrategy类无需修改原有代码便于测试每个策略可单独测试降低测试复杂度。2. 命令模式设备指令下发无人售货柜项目场景痛点无人售货柜后台需向设备下发多种指令货道库存查询指令设备重启指令商品价格更新指令要求指令可异步执行无需等待设备响应指令可记录日志便于排查问题后续可新增指令类型如 “清库存指令”。解决方案命令模式封装指令为对象解耦指令发送者与执行者步骤 1定义抽象命令java运行/** * 设备指令抽象命令 */ public interface DeviceCommand { // 执行指令 void execute(); // 获取指令ID String getCommandId(); }步骤 2实现具体命令java运行/** * 具体命令1库存查询指令 */ public class StockQueryCommand implements DeviceCommand { private final String deviceId; private final DeviceClient deviceClient; // 设备通信客户端执行者 private final String commandId; public StockQueryCommand(String deviceId, DeviceClient deviceClient) { this.deviceId deviceId; this.deviceClient deviceClient; this.commandId CMD_ System.currentTimeMillis(); } Override public void execute() { // 调用执行者的方法下发查询指令 String result deviceClient.sendQueryStockCommand(deviceId); // 记录指令执行日志 System.out.println(执行库存查询指令 commandId 设备 deviceId 结果 result); } Override public String getCommandId() { return commandId; } } /** * 具体命令2价格更新指令 */ public class PriceUpdateCommand implements DeviceCommand { private final String deviceId; private final DeviceClient deviceClient; private final MapInteger, BigDecimal priceMap; // 货道-价格映射 private final String commandId; public PriceUpdateCommand(String deviceId, DeviceClient deviceClient, MapInteger, BigDecimal priceMap) { this.deviceId deviceId; this.deviceClient deviceClient; this.priceMap priceMap; this.commandId CMD_ System.currentTimeMillis(); } Override public void execute() { String result deviceClient.sendUpdatePriceCommand(deviceId, priceMap); System.out.println(执行价格更新指令 commandId 设备 deviceId 结果 result); } Override public String getCommandId() { return commandId; } }步骤 3实现命令调用者指令管理器java运行/** * 命令调用者设备指令管理器 * 核心触发命令执行无需关注命令具体逻辑 */ Service public class DeviceCommandInvoker { Autowired private DeviceClient deviceClient; // 线程池异步执行指令 private final ExecutorService executor Executors.newFixedThreadPool(5); /** * 下发库存查询指令 */ public String sendStockQueryCommand(String deviceId) { DeviceCommand command new StockQueryCommand(deviceId, deviceClient); executor.submit(command::execute); // 异步执行 return command.getCommandId(); } /** * 下发价格更新指令 */ public String sendPriceUpdateCommand(String deviceId, MapInteger, BigDecimal priceMap) { DeviceCommand command new PriceUpdateCommand(deviceId, deviceClient, priceMap); executor.submit(command::execute); return command.getCommandId(); } }步骤 4控制器调用java运行RestController RequestMapping(/device/command) public class DeviceCommandController { Autowired private DeviceCommandInvoker commandInvoker; PostMapping(/stock/{deviceId}) public String queryStock(PathVariable String deviceId) { String commandId commandInvoker.sendStockQueryCommand(deviceId); return 指令已下发ID commandId; } PostMapping(/price/{deviceId}) public String updatePrice(PathVariable String deviceId, RequestBody MapInteger, BigDecimal priceMap) { String commandId commandInvoker.sendPriceUpdateCommand(deviceId, priceMap); return 指令已下发ID commandId; } }应用效果解耦指令发送者控制器与执行者DeviceClient完全分离发送者无需知道指令如何执行异步化通过线程池实现指令异步执行提升系统响应速度可扩展新增 “清库存指令” 只需添加StockClearCommand类无需修改调用者代码可追踪每个指令有唯一 ID便于日志记录和问题排查。四、 设计模式选型核心思路先解决问题再谈模式不要为了用模式而用模式简单场景如查询用户直接写代码即可遵循设计原则所有模式的本质是落地七大设计原则违背原则的模式使用都是 “过度设计”组合使用模式实际项目中模式往往是组合使用的如工厂模式 策略模式、代理模式 装饰器模式参考框架源码Spring、MyBatis 等框架是设计模式的最佳实践教材阅读源码能加深对模式的理解。五、 总结设计模式不是 “银弹”而是解决特定问题的工具。在实际项目中判断是否使用模式的核心标准是是否降低了耦合是否提升了扩展性是否便于维护和测试掌握设计模式的关键不是死记硬背代码结构而是理解模式背后的设计思想——高内聚、低耦合、开闭原则这样才能在面对复杂业务场景时灵活选择合适的模式。