装饰模式和代理模式对比

一、装饰模式

用户使用代码:

//基类
class Subject
{
public:
    virtual void operation();
};

//具体类
class ConcreteSubject : public Subject
{
public:
    virtual void operation();
};

//装饰类
class Decorate : public Subject
{
public:
    Decorate(Subject* pSubject);
    virtual void operate();
private:
    Subject* m_pSubject;
};

//具体装饰类
class ConcreteDecorate : public Decorate
{
public:
    ConcreteDecorate(Subject* pSubject);
    virtual void operate();
};
ConcreteDecorate(Subject* pSubject)
    :Decorate(pSubject)
{
}
void ConcreDecorate::operate()
{
    //other operation
    //otheroperate();
    super.operate();
}

int main()
{
    Subject* pSubject = new ConcreteSubject();
    Decorate* pDecorate = new ConcreteDecorate(pSubject);
    pDecorate->operation();
    return 0;
}

二、代理模式

代码示例:

//基类
class Subject
{
public:
    virtual void operation();
};

//具体类
class ConcreteSubject : public Subject
{
public:
    virtual void operation();
};

//代理类
class Proxy : public Subject
{
public:
    virtual void operation();

private:
    ConcreteSubject m_objConcreteSubject;
};
void Proxy::operation()
{
    m_objConcreteSubject.operation();
}

int main()
{
    Subject* pSubject = new Proxy();
    pSubject->operation();
}

三、对比

从类图关系来看,装饰模式中由Decorate类聚合Subject类,用户使用时,需要自己构造Subject实例,然后将Subject实例作为Decorate构造函数参数传入Decorate,Decorate实例在实现具体操作时,除了调用Subject的操作函数还添加补充操作函数,起到“装饰”的作用。代理模式中Proxy类负责Subject实例的构造和销毁,用户在使用过程中不用直接操作Subject具体实例,由Proxy来负责实现具体的操作。

装饰模式主要强调对Subject类功能的扩展,而代理模式侧重于对Subject类的访问控制。

 

<think>好的,我现在需要回答用户关于Java中装饰模式代理模式区别及用法对比的问题。用户已经提供了一些相关的引用资料,我需要结合这些资料以及之前的知识来组织回答。 首先,我需要回顾装饰模式代理模式的基本概念。装饰模式用于动态地给对象添加职责,而代理模式则是控制对对象的访问。根据引用[1],这两个模式都基于组合,结构上相似,容易混淆。引用[3][4]提到,装饰模式强调功能扩展,代理模式强调访问控制。此外,代理模式可能在内部创建目标对象,而装饰模式通过构造函数传入目标对象。 接下来,我需要整理它们的区别。根据引用,主要区别可能在于目的、对象创建方式、使用阶段、透明性、接口方法以及应用场景等方面。例如,装饰模式是透明的,可以叠加使用,而代理模式可能隐藏目标对象,并且可能仅代理部分方法。 然后,我需要考虑Java中的应用实例。用户提供的示例中,装饰模式用于I/O流,如FilterInputStream,而代理模式如Spring AOP的动态代理。需要将这些例子融入回答中,以具体说明区别。 另外,用户的问题还提到了用法对比,所以需要分别说明何时使用装饰模式,何时使用代理模式,并给出实际场景。例如,装饰模式适用于需要动态添加功能的场合,代理模式适用于访问控制、延迟加载等。 最后,需要确保回答结构清晰,分点明确,并引用提供的参考资料来支持观点。同时,要避免重复,并确保语言准确,符合用户要求的格式,如使用中文,正确引用标识等。</think>在Java中,装饰模式代理模式都通过组合方式操作目标对象,但二者的设计目的实现细节存在本质差异。以下是两者的详细对比分析: --- ### 一、核心差异对比表 | 维度 | 装饰模式(Decorator) | 代理模式(Proxy) | |------------------|---------------------------------------------|-------------------------------------------| | **核心目的** | 动态添加功能(增强型扩展)[^3] | 控制对象访问(保护/延迟/远程访问等)[^4] | | **目标对象创建** | 由客户端传入(构造方法注入)[^3] | 通常由代理类内部创建(隐藏目标对象)[^3] | | **使用阶段** | 运行时动态叠加装饰 | 编译期或运行时(动态代理)确定代理关系 | | **透明性** | 对客户端透明(接口一致)[^1] | 可能不透明(隐藏目标对象状态)[^4] | | **接口方法** | 通常实现目标对象完整接口 | 可能仅代理部分方法 | | **典型应用** | Java I/O流装饰器、GUI组件增强[^1] | Spring AOP、远程方法调用、虚拟代理[^2] | --- ### 二、代码实现差异示例 #### 1. 装饰模式(以I/O流为例) ```java // 组件接口 public interface DataSource { void writeData(String data); } // 基础组件 class FileDataSource implements DataSource { public void writeData(String data) { System.out.println("写入文件: " + data); } } // 装饰器基类 abstract class DataSourceDecorator implements DataSource { protected DataSource wrappee; public DataSourceDecorator(DataSource source) { this.wrappee = source; } } // 具体装饰器:加密功能 class EncryptionDecorator extends DataSourceDecorator { public EncryptionDecorator(DataSource source) { super(source); } @Override public void writeData(String data) { wrappee.writeData(encrypt(data)); } private String encrypt(String data) { return "加密后的" + data; } } // 使用方式:动态叠加功能 DataSource source = new EncryptionDecorator(new FileDataSource()); source.writeData("敏感数据"); // 输出:写入文件: 加密后的敏感数据 ``` #### 2. 代理模式(以虚拟代理为例) ```java interface Image { void display(); } // 真实对象(延迟加载) class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename = filename; loadFromDisk(); } private void loadFromDisk() { System.out.println("加载大文件: " + filename); } public void display() { System.out.println("显示图片: " + filename); } } // 代理类(控制访问) class ProxyImage implements Image { private RealImage realImage; private String filename; public ProxyImage(String filename) { this.filename = filename; } @Override public void display() { if (realImage == null) { realImage = new RealImage(filename); // 按需创建真实对象 } realImage.display(); } } // 使用方式:客户端无感知 Image image = new ProxyImage("1GB_Photo.jpg"); image.display(); // 首次调用时才加载大文件 ``` --- ### 三、关键差异点详解 1. **目标对象控制权** - 装饰器:客户端显式传递被装饰对象,可多层嵌套(如`new A(new B(new C()))`) - 代理器:代理类内部管理目标对象生命周期,客户端无法直接访问真实对象[^3] 2. **设计意图差异** - 装饰模式关注**功能增强**(如I/O流的缓冲/加密装饰)[^1] - 代理模式关注**访问控制**(如Spring AOP的权限校验、日志记录)[^2] 3. **方法覆盖范围** - 装饰器通常实现目标对象完整接口(保证透明性) - 代理器可能仅实现部分方法(如远程代理只代理远程调用相关方法)[^4] 4. **运行时行为** ```mermaid graph LR A[客户端] --> B[装饰器] B --> C[被装饰对象] D[客户端] --> E[代理] E --> F[真实对象] ``` --- ### 四、应用场景选择指南 | **场景特征** | 推荐模式 | |-------------------------------|---------------| | 需要动态叠加多个功能 | 装饰模式 | | 需要控制对象创建/访问时机 | 代理模式 | | 需要拦截特定方法(如AOP) | 动态代理[^2] | | 需要保持接口完全一致 | 装饰模式[^1] | | 需要隐藏目标对象细节 | 代理模式[^4] | --- ### 五、常见混淆场景解析 1. **日志记录功能** - 代理模式:记录方法调用信息(如Spring AOP) - 装饰模式:在原有功能基础上增加日志格式处理 2. **缓存实现** - 代理模式:实现缓存代理(如MyBatis的Mapper代理) - 装饰模式:给数据源添加缓存层(如装饰数据库连接) --- 通过理解二者的核心差异,可以更准确地选择模式。在Java生态中,装饰模式常见于I/O流处理(如`BufferedInputStream`),而代理模式广泛应用于框架级控制(如Spring的声明式事务管理)[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值