当前位置: 首页 > article >正文

C# 设计模式:装饰器模式与代理模式的区别

C# 设计模式:装饰器模式与代理模式的区别

在软件设计中,装饰器模式(Decorator Pattern)和代理模式(Proxy Pattern)都是结构型设计模式,它们的目的都是通过对对象进行包装,来增加或改变对象的行为。虽然它们有一些相似之处,但实际上,它们的设计初衷和使用场景有所不同。本文将通过对比这两种模式,帮助大家更好地理解它们的区别和应用场景。

1. 装饰器模式与代理模式的相似性

装饰器模式和代理模式在表面上有一定的相似性,主要体现在以下几个方面:

  • 都涉及到对对象的包装:无论是装饰器模式还是代理模式,都通过一个包装类来代理或装饰原有对象。
  • 都可以增强对象的功能:通过包装,装饰器模式和代理模式都可以在不改变原有对象代码的情况下,添加新的功能或行为。

然而,它们的核心差异在于目的和实现方式。

2. 装饰器模式 (Decorator Pattern)

目的:装饰器模式的目的是动态地为一个对象添加额外的功能或行为。装饰器通常是为了增强对象的功能,不会改变对象本身的行为。

特点

  • 装饰器模式的关键是递归地装饰对象。它通常是一个实现了相同接口或继承了相同类的对象,可以在运行时增加或修改被装饰对象的行为。
  • 装饰器模式可以在不修改原始对象的情况下,给对象动态地添加功能。

应用场景

  • 需要为一个对象添加额外的职责和行为,而又不想改变对象的结构。
  • 适合用在“责任链”或“动态行为扩展”场景中。
示例:C# 装饰器模式
using System;

// 定义接口
public interface ICar
{
    void Assemble();
}

// 具体组件:普通汽车
public class BasicCar : ICar
{
    public void Assemble()
    {
        Console.WriteLine("Assembling a basic car.");
    }
}

// 装饰器:高级汽车
public class SportsCar : ICar
{
    private ICar car;

    public SportsCar(ICar car)
    {
        this.car = car;
    }

    public void Assemble()
    {
        car.Assemble();
        Console.WriteLine("Adding features of sports car.");
    }
}

// 装饰器:豪华汽车
public class LuxuryCar : ICar
{
    private ICar car;

    public LuxuryCar(ICar car)
    {
        this.car = car;
    }

    public void Assemble()
    {
        car.Assemble();
        Console.WriteLine("Adding features of luxury car.");
    }
}

// 客户端代码
class Program
{
    static void Main()
    {
        ICar sportsCar = new SportsCar(new BasicCar());
        sportsCar.Assemble();  // 组装运动型车

        Console.WriteLine();

        ICar sportsLuxuryCar = new LuxuryCar(new SportsCar(new BasicCar()));
        sportsLuxuryCar.Assemble();  // 组装豪华运动型车
    }
}

运行结果

Assembling a basic car.
Adding features of sports car.

Assembling a basic car.
Adding features of sports car.
Adding features of luxury car.
3. 代理模式 (Proxy Pattern)

目的:代理模式的目的是通过控制访问来间接地管理对某个对象的操作。代理通常是为了控制对真实对象的访问,可以是为了延迟实例化、权限控制或做一些前置处理等。

特点

  • 代理模式的关键是控制对目标对象的访问。代理可以控制目标对象的创建、访问、权限检查等行为。
  • 代理模式的代理类通常实现与被代理类相同的接口,可以通过代理类来调用目标对象的方法。
  • 代理有时用于控制资源的访问,例如通过虚拟代理延迟加载,或者通过安全代理控制对敏感资源的访问。

应用场景

  • 需要在客户端和真实对象之间插入一个代理,以控制对真实对象的访问。
  • 用于懒加载(虚拟代理)、权限控制(保护代理)或日志监控等场景。
示例:C# 代理模式
using System;

// 定义接口
public interface IRealSubject
{
    void Request();
}

// 真实对象:实际操作的对象
public class RealSubject : IRealSubject
{
    public void Request()
    {
        Console.WriteLine("Request is being processed by the RealSubject.");
    }
}

// 代理类:控制访问的代理
public class Proxy : IRealSubject
{
    private RealSubject realSubject;

    public void Request()
    {
        if (realSubject == null)
        {
            realSubject = new RealSubject();  // 延迟实例化
        }
        Console.WriteLine("Proxy: Checking access before forwarding request.");
        realSubject.Request();  // 转发请求
    }
}

// 客户端代码
class Program
{
    static void Main()
    {
        IRealSubject proxy = new Proxy();
        proxy.Request();  // 通过代理访问
    }
}

运行结果

Proxy: Checking access before forwarding request.
Request is being processed by the RealSubject.
4. 装饰器模式与代理模式的区别
方面装饰器模式 (Decorator)代理模式 (Proxy)
目的动态地添加功能或责任,使得对象的行为得到增强。控制对对象的访问,可能会在请求前进行权限检查或懒加载等操作。
行为装饰器改变或扩展对象的行为,不影响原有对象的接口。代理不改变对象的行为,主要用于控制访问权限。
实现方式装饰器是一个封装对象并实现相同接口的类。代理实现与被代理对象相同的接口,控制对对象的访问。
应用场景用于动态地为对象添加功能,通常不涉及对对象访问的控制。用于控制对对象的访问,例如延迟加载、权限控制等。
功能重点扩展功能和责任控制访问(懒加载、权限控制等)
5. 总结

尽管装饰器模式和代理模式看起来很相似,都是通过包装对象来增强或控制对象的行为,但它们有不同的设计目的和使用场景。装饰器模式主要用于增强对象的功能,而代理模式则主要用于控制访问,尤其是延迟加载、权限控制等。理解这两者的区别,可以帮助我们在开发中做出更加合适的设计决策。
在实际开发中,当你需要扩展对象的功能时,可以考虑使用装饰器模式;而当你需要控制对象的访问或者做一些额外的管理时,可以考虑使用代理模式。


http://www.kler.cn/a/464188.html

相关文章:

  • docker中使用Volume完成数据共享
  • 昆仑万维大数据面试题及参考答案
  • Node 如何生成 RSA 公钥私钥对
  • 运算符重载 - 自定义运算符行为
  • 【数据结构Ⅰ复习题】
  • driftingblues2
  • 力扣hot100——二叉树
  • 高效使用AI完成编程项目任务的指南:从需求分析到功能实现
  • 华为OD E卷(100分)45-喊7的次数重排
  • 【网站推荐】IP反查域名实战
  • leetcode 729. 我的日程安排表 I 中等
  • 小程序配置文件 —— 15 页面配置
  • 【2024美国数学建模AB题原文翻译】
  • 基于QT(C++)实现的坦克大战
  • 力扣刷题:栈和队列OJ篇(下)
  • 力扣-数据结构-10【算法学习day.81】
  • 浅谈Beam Search
  • “混合双打”二维数组展平的有效方案(Python)
  • 【SqlSugar雪花ID常见问题】.NET开源ORM框架 SqlSugar 系列
  • requests请求带cookie
  • 深入理解Java Map集合
  • 逻辑回归(Logistic Regression)深度解析
  • 在Swagger(现称为OpenAPI)中各类@api之间的区别
  • k8s系列--docker拉取镜像导入k8s的containerd中
  • HTML——56.表单发送
  • 从零开始学桶排序:Java 示例与优化建议