1043 words
5 minutes
设计模式系列(四):易混淆辨析

AI 智能总结

设计模式 4 易混淆辨析#

开发与面试经常分不清几组外观相似的模式,核心区分方式:看设计目标、接口是否变化、意图,附带代码特征对比。

1. 装饰器 vs 适配器 vs 代理#

三者都采用「包装对象」的形式,最容易混淆。

核心结论#

  • 装饰器:接口不变,增强功能
  • 适配器:转换接口,兼容异构
  • 代理:控制访问,管控原始对象

装饰器(Decorator)#

目标:动态叠加功能,原始接口保持不变
包装类与被包装类实现同一个接口,可以多层嵌套拓展。

interface Coffee{
double cost();
}
class SimpleCoffee implements Coffee{
@Override public double cost(){return 10;}
}
// 装饰器,实现相同接口
class MilkDecorator implements Coffee{
private Coffee coffee;
public MilkDecorator(Coffee coffee){this.coffee = coffee;}
@Override
public double cost(){
return coffee.cost() + 3;
}
}

适配器(Adapter)#

目标:接口转换,解决两个类接口不兼容
新旧接口不一样,做翻译层,不侧重增强功能。

// 新系统标准接口
interface Target {void handle();}
// 老系统类,方法名不一致
class OldService {void oldHandle(){}}
// 适配器做转换
class ServiceAdapter implements Target{
private OldService oldService;
@Override
public void handle() {
oldService.oldHandle();
}
}

代理(Proxy)#

目标:控制对真实对象的访问,增加预处理/后置处理
接口和真实对象保持一致,重点是访问管控(权限、延迟加载、AOP)。

interface UserService{
void query();
}
class UserServiceImpl implements UserService{}
// 代理类
class UserProxy implements UserService{
private UserService target;
@Override
public void query() {
System.out.println("前置校验");
target.query();
}
}

快速区分口诀:

  • 同接口、叠加功能 → 装饰器
  • 接口不一样、做兼容转换 → 适配器
  • 同接口、管控对象访问 → 代理

2. 工厂 vs 建造者#

共同点:都负责对象创建;区别在于对象复杂度与创建方式

工厂模式(工厂方法/抽象工厂)#

关注点:整体产出完整对象,不需要关心构建步骤。
适用:产品结构简单,一次性创建完成。

建造者(Builder)#

关注点:分步构造复杂对象,对象属性繁多、构造流程复杂。
适用:对象存在大量可选参数,构造步骤固定,但细节可变。

// Builder示例
class Person {
private String name;
private Integer age;
// 私有构造
private Person(Builder builder){
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private String name;
private Integer age;
public Builder name(String name){
this.name = name;
return this;
}
public Builder age(Integer age){
this.age = age;
return this;
}
public Person build(){
return new Person(this);
}
}
}
// 使用:分步赋值
Person p = new Person.Builder().name("test").age(20).build();

区分要点:

  • 一次性生成产品 → 工厂
  • 分步骤组装、参数众多 → 建造者

3. 策略 vs 状态#

结构高度相似,都有上下文Context、多个实现类,是面试重难点。

策略模式#

  • 算法之间互相独立,主动切换
  • 上下文主动传入/设置策略;策略之间互不感知
  • 示例:支付方式、折扣算法
interface PayStrategy{
void pay();
}
class AliPay implements PayStrategy{}
class PayContext{
private PayStrategy strategy;
public void setStrategy(PayStrategy s){this.strategy = s;}
}

状态模式#

  • 状态自动流转,状态之间具备关联性
  • 对象内部状态发生变化,自动切换行为;状态类可以驱动状态变更
  • 示例:订单状态(待支付→已支付→已取消)
// 状态接口
interface OrderState {
void pay(OrderContext order);
void cancel(OrderContext order);
}
// 待支付状态
class WaitingPayState implements OrderState {
public void pay(OrderContext order) {
// 支付成功,切换到已支付状态
order.setState(new PaidState());
}
public void cancel(OrderContext order) {
order.setState(new CanceledState());
}
}
// 订单上下文
class OrderContext {
private OrderState state;
public void setState(OrderState state) {
this.state = state; // 状态自动流转切换
}
}

区分要点:

  • 人为主动选择不同算法,算法无关联 → 策略
  • 对象自身状态自动流转,状态之间存在切换逻辑 → 状态

总结一览#

分组核心区分点
装饰器/适配器/代理功能增强 / 接口转换 / 访问控制
工厂/建造者一次性创建对象 / 分步组装复杂对象
策略/状态主动选择独立算法 / 对象内部自动流转状态

实践提醒:不要只看代码结构,优先思考业务意图,才能准确选用模式。

设计模式系列(四):易混淆辨析
https://fuwari.vercel.app/posts/design-series/design-04-confusion/
Author
Zero02
Published at
2025-07-22
License
CC BY-NC-SA 4.0