设计模式是软件开发中沉淀的通用、可复用的最佳解决方案,专门解决项目中代码冗余、耦合度过高、扩展性差、维护成本高昂、架构混乱 等核心问题。本文将系统讲解5大创建型模式、7大结构型模式,严格贴合核心设计思想,拆解每种模式的原理、适用场景、核心特点,提供可直接上线的生产级代码案例,同时重点辨析高频相似设计模式的核心区别,完全适配业务开发、源码研读、面试刷题三大场景。
一、创建型设计模式
创建型模式核心定位:专注对象的创建逻辑,屏蔽对象实例化的复杂细节,解耦对象创建与业务逻辑,统一对象创建规范,让代码更优雅、更易拓展。包含:简单工厂、工厂方法、抽象工厂、建造者、原型、单例。
1. 简单工厂模式
简单工厂不属于GOF23种经典设计模式,但却是最基础的对象创建模式。其核心是通过一个统一的工厂类,根据传入的参数,通过if/else、switch判断,创建并返回不同的对象实例。客户端无需关注对象创建细节,直接调用工厂方法即可获取对象。
简单工厂并非GOF23经典设计模式,是最基础的对象创建方案。核心逻辑:通过一个统一的工厂类,基于 if/else、switch 条件判断,根据传入参数创建不同的产品对象,客户端无需关注对象创建细节,直接调用工厂方法获取实例。
优缺点
优点:统一对象创建入口,封装创建逻辑,简化客户端调用。
缺点:严重违背开闭原则,新增产品必须修改工厂类的判断逻辑,产品越多,工厂类越臃肿、维护难度越高。
生产级实战案例
业务场景:支付渠道统一创建,系统支持微信、支付宝支付,通过简单工厂动态生成对应支付对象
import java.math.BigDecimal;
// 支付产品抽象接口
public interface Pay {
void pay(BigDecimal money);
}
// 微信支付实现
public class WechatPay implements Pay {
@Override
public void pay(BigDecimal money) {
System.out.println("微信支付成功,支付金额:" + money);
}
}
// 支付宝支付实现
public class Alipay implements Pay {
@Override
public void pay(BigDecimal money) {
System.out.println("支付宝支付成功,支付金额:" + money);
}
}
// 统一简单工厂类
public class PaySimpleFactory {
public static Pay createPay(String payType) {
if ("WECHAT".equalsIgnoreCase(payType)) {
return new WechatPay();
} else if ("ALIPAY".equalsIgnoreCase(payType)) {
return new Alipay();
} else {
throw new RuntimeException("不支持的支付渠道");
}
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Pay pay = PaySimpleFactory.createPay("ALIPAY");
pay.pay(new BigDecimal("99.9"));
}
}
2. 工厂方法模式
核心原理
工厂方法是简单工厂的迭代升级版,核心设计思想:将对象创建逻辑下放至子类。定义统一的抽象工厂接口,不再通过条件判断创建对象,每一个产品对应一个专属的工厂子类,由子类负责具体产品的实例化。
与简单工厂核心区别
-
简单工厂:单一统一工厂类 + 条件判断创建对象,新增产品需修改原有工厂代码,违背开闭原则
-
工厂方法:抽象工厂 + 子类专属工厂,新增产品只需新增「产品类+工厂子类」,原有代码零修改,完全符合开闭原则
生产级实战案例
业务场景:改造支付渠道场景,支持后续无缝拓展云闪付、抖音支付等新渠道,无需改动核心代码。
import java.math.BigDecimal;
// 产品抽象接口
public interface Pay {
void pay(BigDecimal money);
}
// 具体产品实现
public class WechatPay implements Pay {
@Override
public void pay(BigDecimal money) {
System.out.println("微信支付:" + money);
}
}
public class Alipay implements Pay {
@Override
public void pay(BigDecimal money) {
System.out.println("支付宝支付:" + money);
}
}
// 抽象工厂接口
public interface PayFactory {
Pay createPay();
}
// 专属工厂子类
public class WechatPayFactory implements PayFactory {
@Override
public Pay createPay() {
return new WechatPay();
}
}
public class AlipayFactory implements PayFactory {
@Override
public Pay createPay() {
return new Alipay();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
PayFactory factory = new WechatPayFactory();
Pay pay = factory.createPay();
pay.pay(new BigDecimal("199.9"));
}
}
3. 抽象工厂模式
核心原理
工厂方法针对单一独立产品 创建,而抽象工厂专注产品族 创建。核心定义:提供一个抽象工厂接口,用于创建一系列相关、相互依赖的产品对象,保证同一品牌、同一系列的产品配套使用。
产品族概念:同一系列下的多个关联产品,例如手机产品族包含:手机、耳机、智能手表三件套。
适用场景
系统存在多个产品系列,每个系列包含多个关联产品,需要强制保证产品配套使用,不出现跨系列混用的场景。
生产级实战案例
业务场景:电商数码产品生产,分为小米、华为两大产品族,每个产品族统一生产手机、耳机两类配套产品。
// 产品1:手机抽象接口
public interface Phone {
void showPhoneInfo();
}
// 产品2:耳机抽象接口
public interface HeadSet {
void showHeadSetInfo();
}
// 小米产品族具体产品
public class XiaomiPhone implements Phone {
@Override
public void showPhoneInfo() {
System.out.println("小米14 旗舰手机");
}
}
public class XiaomiHeadSet implements HeadSet {
@Override
public void showHeadSetInfo() {
System.out.println("小米无线蓝牙耳机");
}
}
// 华为产品族具体产品
public class HuaweiPhone implements Phone {
@Override
public void showPhoneInfo() {
System.out.println("华为Mate60 旗舰手机");
}
}
public class HuaweiHeadSet implements HeadSet {
@Override
public void showHeadSetInfo() {
System.out.println("华为FreeBuds降噪耳机");
}
}
// 抽象工厂:定义产品族创建规范
public interface DigitalFactory {
Phone createPhone();
HeadSet createHeadSet();
}
// 小米工厂:生产小米全系产品
public class XiaomiFactory implements DigitalFactory {
@Override
public Phone createPhone() {
return new XiaomiPhone();
}
@Override
public HeadSet createHeadSet() {
return new XiaomiHeadSet();
}
}
// 华为工厂:生产华为全系产品
public class HuaweiFactory implements DigitalFactory {
@Override
public Phone createPhone() {
return new HuaweiPhone();
}
@Override
public HeadSet createHeadSet() {
return new HuaweiHeadSet();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 统一获取华为产品族全套配套产品
DigitalFactory factory = new HuaweiFactory();
Phone phone = factory.createPhone();
HeadSet headSet = factory.createHeadSet();
phone.showPhoneInfo();
headSet.showHeadSetInfo();
}
}
4. 建造者模式
核心原理
建造者模式是分步构建复杂对象 的专属创建型模式,核心思想:将复杂对象的构建过程 与对象的最终表现形态彻底分离,通过固定的构建流程,可生成不同属性、不同形态的对象。
与普通get/set方法核心区别
-
普通get/set:零散无序赋值,无参数校验、无构建顺序,复杂对象赋值代码臃肿混乱,无法区分必填/选填参数
-
建造者模式:链式调用、分步构建、强制必填参数、支持参数校验、构建流程统一规范,完美适配多字段复杂对象
生产级实战案例
业务场景:系统用户实体(多字段、区分必填/选填),企业级开发中DTO、VO、配置类高频使用该模式。
// 复杂用户实体 + 静态内部建造者
public class User {
// 必填核心参数
private String username;
private String phone;
// 选填拓展参数
private String avatar;
private String gender;
private Integer age;
private String sign;
// 私有构造器,仅建造者可访问
private User(UserBuilder builder) {
this.username = builder.username;
this.phone = builder.phone;
this.avatar = builder.avatar;
this.gender = builder.gender;
this.age = builder.age;
this.sign = builder.sign;
}
// 静态内部建造者
public static class UserBuilder {
private String username;
private String phone;
private String avatar;
private String gender;
private Integer age;
private String sign;
// 构造器强制传入必填参数
public UserBuilder(String username, String phone) {
this.username = username;
this.phone = phone;
}
// 链式赋值选填参数
public UserBuilder avatar(String avatar) {
this.avatar = avatar;
return this;
}
public UserBuilder gender(String gender) {
this.gender = gender;
return this;
}
public UserBuilder age(Integer age) {
this.age = age;
return this;
}
public UserBuilder sign(String sign) {
this.sign = sign;
return this;
}
// 最终构建+参数校验
public User build() {
if (username == null || phone == null) {
throw new RuntimeException("用户名和手机号为必填项,不能为空");
}
return new User(this);
}
}
// getter方法省略
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 灵活构建不同参数的用户对象
User user1 = new User.UserBuilder("zhangsan", "13800138000")
.age(25)
.gender("男")
.build();
User user2 = new User.UserBuilder("lisi", "13900139000")
.sign("热爱生活,持续精进")
.build();
}
}
5. 原型模式
核心原理
原型模式核心是对象克隆复制 ,无需通过 new 关键字实例化对象,通过复制已有原型对象快速生成新对象,大幅提升复杂对象创建效率。Java 中通过实现 Cloneable接口、重写 clone() 方法实现。
核心知识点:浅拷贝 & 深拷贝
-
浅拷贝:仅复制基本数据类型的值,引用类型只复制内存地址,新旧对象共享同一个引用对象,修改会互相影响
-
深拷贝:完全复制所有数据,基本类型、引用类型全部新建内存,新旧对象完全独立,互不干扰
生产级实战案例
业务场景:系统全局配置类,配置初始化耗时,通过原型克隆快速复制配置对象,提升系统性能。
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// 系统配置原型类
public class SystemConfig implements Cloneable {
// 基本数据类型
private String appName;
private Integer timeout;
// 引用数据类型
private List<String> whiteList;
// 重写浅拷贝方法
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
// 自定义深拷贝方法
public SystemConfig deepClone() throws CloneNotSupportedException {
SystemConfig clone = (SystemConfig) super.clone();
// 手动新建引用类型对象,彻底隔离数据
clone.whiteList = new ArrayList<>(this.whiteList);
return clone;
}
// getter/setter
public String getAppName() { return appName; }
public void setAppName(String appName) { this.appName = appName; }
public Integer getTimeout() { return timeout; }
public void setTimeout(Integer timeout) { this.timeout = timeout; }
public List<String> getWhiteList() { return whiteList; }
public void setWhiteList(List<String> whiteList) { this.whiteList = whiteList; }
}
// 客户端测试
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
// 初始化原型对象
SystemConfig source = new SystemConfig();
source.setAppName("电商后台系统");
source.setTimeout(3000);
source.setWhiteList(Arrays.asList("127.0.0.1","192.168.1.1"));
// 浅拷贝、深拷贝
SystemConfig shallowClone = (SystemConfig) source.clone();
SystemConfig deepClone = source.deepClone();
// 修改引用类型数据,验证拷贝差异
shallowClone.getWhiteList().add("10.0.0.1");
System.out.println("原对象白名单:" + source.getWhiteList());
System.out.println("深拷贝对象白名单:" + deepClone.getWhiteList());
}
}
6. 单例模式
核心原理
单例模式是最常用的创建型模式,核心规则:一个类在整个应用全局中仅有且只有一个实例,提供全局统一的访问入口。核心特征:私有构造器、静态全局实例、全局静态获取方法。
核心关键字:volatile
双重检查锁单例中,volatile 关键字两大核心作用:禁止指令重排序、保证线程可见性,彻底解决多线程环境下对象半初始化、实例重复创建的线程安全问题。
生产级实战案例(高性能线程安全双重检查锁)
业务场景:全局日志工具、缓存工具、系统配置工具,全局仅需一个实例,节约内存、保证数据统一。
java
public class LogUtil {
// volatile 禁止指令重排、保证线程可见性
private static volatile LogUtil instance;
// 私有构造器:禁止外部new,防止反射破坏单例
private LogUtil() {
if (instance != null) {
throw new RuntimeException("禁止重复创建单例实例");
}
}
// 双重检查锁:兼顾线程安全与高性能
public static LogUtil getInstance() {
if (instance == null) {
synchronized (LogUtil.class) {
if (instance == null) {
instance = new LogUtil();
}
}
}
return instance;
}
// 通用日志业务方法
public void info(String msg) {
System.out.println("【INFO】" + System.currentTimeMillis() + ":" + msg);
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
LogUtil log1 = LogUtil.getInstance();
LogUtil log2 = LogUtil.getInstance();
// 输出true,证明全局唯一实例
System.out.println(log1 == log2);
log1.info("系统启动成功");
}
}
二、结构型设计模式
结构型模式核心定位:专注类与对象的组合结构、依赖关系优化,不修改原有业务代码的前提下,通过组合、适配、封装等方式,优化系统架构、解耦代码、拓展功能,解决系统臃肿、耦合过高、兼容性差的问题。包含7大核心模式:适配器、桥接、组合、装饰者、外观、享元、代理。
1. 适配器模式
1.1 核心原理
适配器是接口兼容适配专用模式,核心:引入中间适配器层,将客户端需要的目标接口,与服务端不兼容的原有接口做转换,让接口不匹配的类可以协同工作。
1.2 解决核心问题
-
接口不匹配:新旧系统、第三方SDK接口参数、方法定义不一致
-
保护现有代码:无法修改第三方、老旧系统的源码,通过适配器间接适配,符合开闭原则
1.3 生产级实战案例
业务场景:新系统统一登录接口规范,适配老旧遗留系统的登录接口,无需改造老系统代码。
java
// 客户端目标接口(新系统统一规范)
public interface NewLoginService {
boolean login(String username, String password);
}
// 服务端原有接口(老旧系统,不可修改)
public class OldLoginService {
public boolean userLogin(String acc, String pwd, Long type) {
System.out.println("老旧系统登录校验逻辑");
return "admin".equals(acc) && "123456".equals(pwd);
}
}
// 适配器:中间转换层,适配新旧接口
public class LoginAdapter implements NewLoginService {
private final OldLoginService oldLoginService = new OldLoginService();
@Override
public boolean login(String username, String password) {
// 统一参数适配、接口转换
return oldLoginService.userLogin(username, password, 1L);
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
NewLoginService loginService = new LoginAdapter();
boolean result = loginService.login("admin", "123456");
System.out.println("登录结果:" + result);
}
}
2. 桥接模式
2.1 核心原理
桥接模式核心:拆分多维变化的类结构,将一个复杂大类拆分为「抽象层」和「实现层」两个独立的层级结构,通过引用建立桥梁关联,让两个层级可以独立拓展,彻底解决继承导致的类爆炸问题。
2.2 适用场景
系统存在两个独立变化的维度,两个维度均需要持续拓展迭代。
2.3 生产级实战案例
业务场景:消息推送系统,包含「消息发送方式(短信/邮件)」「消息级别(普通/紧急)」两个独立变化维度。
java
// 实现层接口:消息发送方式(变化维度1)
public interface MessageSender {
void send(String content);
}
public class SmsSender implements MessageSender {
@Override
public void send(String content) {
System.out.println("短信推送:" + content);
}
}
public class EmailSender implements MessageSender {
@Override
public void send(String content) {
System.out.println("邮件推送:" + content);
}
}
// 抽象层:消息级别(变化维度2),持有实现层引用(桥梁)
public abstract class AbstractMessage {
protected MessageSender sender;
public AbstractMessage(MessageSender sender) {
this.sender = sender;
}
public abstract void sendMessage(String content);
}
// 抽象层具体实现
public class NormalMessage extends AbstractMessage {
public NormalMessage(MessageSender sender) {
super(sender);
}
@Override
public void sendMessage(String content) {
sender.send("【普通消息】" + content);
}
}
public class UrgentMessage extends AbstractMessage {
public UrgentMessage(MessageSender sender) {
super(sender);
}
@Override
public void sendMessage(String content) {
sender.send("【紧急消息】" + content);
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 紧急短信推送
AbstractMessage urgentSms = new UrgentMessage(new SmsSender());
urgentSms.sendMessage("订单超时,请立即处理!");
// 普通邮件推送
AbstractMessage normalEmail = new NormalMessage(new EmailSender());
normalEmail.sendMessage("系统月度维护公告");
}
}
3. 组合模式
3.1 核心原理
组合模式核心:将对象组装成树形层级结构,统一叶子节点(无下级)和容器节点(有下级)的调用规范,让客户端可以像使用单个独立对象一样,统一操作整个树形结构,实现「部分与整体一致」。
3.2 生产级实战案例
业务场景:后台系统树形菜单结构,顶级菜单、子菜单、功能按钮统一渲染管理。
java
import java.util.ArrayList;
import java.util.List;
// 统一组件接口:所有菜单节点通用行为
public interface MenuComponent {
void show();
}
// 叶子节点:功能按钮、无子菜单
public class MenuItem implements MenuComponent {
private String name;
public MenuItem(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println("├─ 功能按钮:" + name);
}
}
// 容器节点:顶级/二级菜单,包含子节点
public class Menu implements MenuComponent {
private String name;
private List<MenuComponent> childList = new ArrayList<>();
public Menu(String name) {
this.name = name;
}
public void add(MenuComponent component) {
childList.add(component);
}
@Override
public void show() {
System.out.println("【顶级菜单】" + name);
for (MenuComponent component : childList) {
component.show();
}
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 构建树形菜单
Menu rootMenu = new Menu("系统管理");
Menu userMenu = new Menu("用户管理");
userMenu.add(new MenuItem("新增用户"));
userMenu.add(new MenuItem("删除用户"));
rootMenu.add(userMenu);
rootMenu.add(new MenuItem("系统参数配置"));
// 统一渲染整个树形结构
rootMenu.show();
}
}
4. 装饰者模式
4.1 核心原理
装饰者模式核心:不修改原对象结构、不使用继承,通过特殊封装对象(装饰器)包裹原对象,动态为原对象绑定、拓展新功能,支持多层嵌套装饰,实现灵活的功能增强。
4.2 核心优势
完全遵循开闭原则,功能拓展灵活、轻量化,可动态叠加、撤销功能,解决继承臃肿、固化的问题。
4.3 生产级实战案例
业务场景:订单支付功能,基于基础支付,动态叠加积分抵扣、红包抵扣增值功能。
java
import java.math.BigDecimal;
// 抽象组件:订单支付统一接口
public interface OrderPay {
BigDecimal pay(BigDecimal amount);
}
// 具体基础组件:原生支付功能
public class BaseOrderPay implements OrderPay {
@Override
public BigDecimal pay(BigDecimal amount) {
return amount;
}
}
// 装饰者抽象类:持有原支付对象
public abstract class PayDecorator implements OrderPay {
protected OrderPay orderPay;
public PayDecorator(OrderPay orderPay) {
this.orderPay = orderPay;
}
}
// 具体装饰器1:积分抵扣
public class IntegralPayDecorator extends PayDecorator {
public IntegralPayDecorator(OrderPay orderPay) {
super(orderPay);
}
@Override
public BigDecimal pay(BigDecimal amount) {
System.out.println("积分抵扣10元");
return orderPay.pay(amount).subtract(new BigDecimal("10"));
}
}
// 具体装饰器2:红包抵扣
public class RedPacketPayDecorator extends PayDecorator {
public RedPacketPayDecorator(OrderPay orderPay) {
super(orderPay);
}
@Override
public BigDecimal pay(BigDecimal amount) {
System.out.println("红包抵扣5元");
return orderPay.pay(amount).subtract(new BigDecimal("5"));
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 基础支付
OrderPay pay = new BaseOrderPay();
// 动态嵌套装饰,叠加双重优惠
pay = new IntegralPayDecorator(pay);
pay = new RedPacketPayDecorator(pay);
BigDecimal finalAmount = pay.pay(new BigDecimal("100"));
System.out.println("订单最终支付金额:" + finalAmount);
}
}
5. 外观模式
5.1 核心原理
外观模式(门面模式)核心:为复杂的子系统、工具类、框架提供一个统一的高层入口接口,屏蔽子系统的复杂内部逻辑、多依赖调用,让客户端只需调用一个简单接口,即可完成复杂操作,大幅降低使用成本。
5.2 适用场景
子系统逻辑复杂、调用链路繁琐、依赖众多,需要简化客户端调用,统一收口接口。
5.3 生产级实战案例
业务场景:电商订单下单流程,包含参数校验、库存扣减、订单创建、消息通知多个复杂子流程,通过外观类统一封装入口。
java
// 子系统1:参数校验
public class OrderValidateService {
public boolean validate() {
System.out.println("订单参数校验通过");
return true;
}
}
// 子系统2:库存扣减
public class StockService {
public void deductStock() {
System.out.println("商品库存扣减成功");
}
}
// 子系统3:订单创建
public class OrderCreateService {
public void createOrder() {
System.out.println("订单创建成功,生成订单号");
}
}
// 子系统4:消息通知
public class MessageNotifyService {
public void sendNotify() {
System.out.println("下单成功,推送短信通知用户");
}
}
// 外观类:统一封装所有子流程,提供唯一入口
public class OrderFacade {
private final OrderValidateService validateService = new OrderValidateService();
private final StockService stockService = new StockService();
private final OrderCreateService createService = new OrderCreateService();
private final MessageNotifyService notifyService = new MessageNotifyService();
// 统一下单入口,客户端无需感知复杂子流程
public void placeOrder() {
if (validateService.validate()) {
stockService.deductStock();
createService.createOrder();
notifyService.sendNotify();
System.out.println("===== 下单流程全部完成 =====");
}
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 仅需调用一个接口,完成完整下单流程
OrderFacade orderFacade = new OrderFacade();
orderFacade.placeOrder();
}
}
6. 享元模式
6.1 核心原理
享元模式是内存优化专用模式 ,核心思想:复用大量重复、细粒度的对象,将对象分为「内部不变状态(共享)」和「外部可变状态(非共享)」,通过工厂缓存共享对象,避免重复创建大量相同对象,节约内存资源。
6.2 适用场景
系统存在大量重复细粒度对象,对象大部分状态固定,仅少量状态变化(如线程池、连接池、字符缓存)。
6.3 生产级实战案例
业务场景:系统日志打印工具,大量重复日志模板对象,通过享元工厂缓存复用模板,减少对象创建。
java
import java.util.HashMap;
import java.util.Map;
// 抽象享元角色:日志模板
public interface LogTemplate {
void printLog(String content);
}
// 具体享元角色:可共享的日志模板(内部状态固定)
public class CommonLogTemplate implements LogTemplate {
// 内部不变状态:日志模板前缀(全局共享)
private final String templatePrefix;
public CommonLogTemplate(String templatePrefix) {
this.templatePrefix = templatePrefix;
}
@Override
public void printLog(String content) {
// 外部可变状态:日志内容(每次不同)
System.out.println(templatePrefix + ":" + content);
}
}
// 享元工厂:缓存共享对象,统一复用
public class LogTemplateFactory {
// 缓存池:存储所有可共享的模板对象
private static final Map<String, LogTemplate> CACHE_POOL = new HashMap<>();
// 获取共享模板,存在则复用,不存在则创建并缓存
public static LogTemplate getTemplate(String prefix) {
if (!CACHE_POOL.containsKey(prefix)) {
CACHE_POOL.put(prefix, new CommonLogTemplate(prefix));
}
return CACHE_POOL.get(prefix);
}
// 获取缓存对象数量
public static int getCacheSize() {
return CACHE_POOL.size();
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 多次获取同一模板,复用同一个对象
LogTemplate info1 = LogTemplateFactory.getTemplate("【INFO】");
LogTemplate info2 = LogTemplateFactory.getTemplate("【INFO】");
LogTemplate error = LogTemplateFactory.getTemplate("【ERROR】");
info1.printLog("系统加载完成");
info2.printLog("接口调用成功");
error.printLog("参数异常");
// 缓存仅2个对象,实现大量场景复用
System.out.println("缓存模板数量:" + LogTemplateFactory.getCacheSize());
System.out.println("INFO模板是否复用:" + (info1 == info2));
}
}
7. 代理模式
7.1 核心原理
代理模式核心:通过代理对象控制对真实目标对象的访问,在不修改真实对象代码的前提下,通过代理层前置、后置拓展通用逻辑(日志、权限、事务、限流),真实对象专注核心业务。
7.2 适用场景
需要对目标对象的方法进行增强、拦截、权限控制、延迟加载、日志记录等通用切面逻辑。
7.3 生产级实战案例(静态代理)
业务场景:用户查询服务,通过代理类统一添加接口调用日志、耗时统计,不改动核心查询逻辑。
java
// 统一业务接口
public interface UserQueryService {
User getUserInfo(Long userId);
}
// 真实目标对象:核心业务实现
public class UserQueryServiceImpl implements UserQueryService {
@Override
public User getUserInfo(Long userId) {
// 核心业务逻辑
return new User(userId, "testUser", "13800138000");
}
}
// 代理对象:增强核心方法
public class UserQueryProxy implements UserQueryService {
// 持有真实目标对象
private final UserQueryService target;
public UserQueryProxy(UserQueryService target) {
this.target = target;
}
@Override
public User getUserInfo(Long userId) {
// 前置增强:记录调用日志、开始时间
System.out.println("开始调用用户查询接口,用户ID:" + userId);
long startTime = System.currentTimeMillis();
// 执行核心业务逻辑
User user = target.getUserInfo(userId);
// 后置增强:统计耗时、结束日志
long cost = System.currentTimeMillis() - startTime;
System.out.println("用户查询接口调用结束,耗时:" + cost + "ms");
return user;
}
}
// 实体类
class User {
private Long userId;
private String username;
private String phone;
// 构造器、getter省略
public User(Long userId, String username, String phone) {
this.userId = userId;
this.username = username;
this.phone = phone;
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
// 通过代理访问目标对象
UserQueryService proxy = new UserQueryProxy(new UserQueryServiceImpl());
User user = proxy.getUserInfo(1001L);
System.out.println("查询用户信息:" + user.getUsername());
}
}
三、高频相似设计模式核心区别
3.1 简单工厂 VS 工厂方法 VS 抽象工厂
-
简单工厂:单一工厂类+条件判断,创建单一产品,不满足开闭,适合简单小项目
-
工厂方法 :一产品一工厂,专注单一产品拓展,满足开闭,适合单一品类迭代场景
-
抽象工厂 :一工厂一族产品,专注产品族配套创建,强制关联产品,适合多系列配套场景
3.2 建造者模式 VS 工厂模式
-
工厂模式 :专注「对象快速创建」,直接返回完整对象,无分步构建过程,适合普通简单对象
-
建造者模式 :专注「复杂对象分步组装」,可控参数、链式构建、支持参数校验,适合多字段、复杂配置对象
3.3 装饰者模式 VS 代理模式
-
装饰者 :核心是增强对象功能,动态叠加业务能力(抵扣、权限、校验),可多层嵌套,关注「业务功能拓展」
-
代理模式 :核心是控制对象访问,做日志、事务、限流、权限拦截,不改变原有业务功能,关注「访问控制与通用增强」
3.4 桥接模式 VS 适配器模式
-
适配器 :解决现有不兼容接口的适配问题,是事后补救、兼容老代码
-
桥接 :提前解耦两个变化维度,规避后续拓展的类爆炸问题,是事前架构优化
3.5 外观模式 VS 适配器模式
-
适配器:1对1适配,解决两个接口不兼容问题
-
外观模式:多对一收口,封装多个复杂子系统,简化客户端调用,不解决接口兼容问题