C# 一分钟浅谈:装饰者模式与代理模式

简介: 【10月更文挑战第12天】本文介绍了面向对象编程中的两种常见设计模式:装饰者模式和代理模式。装饰者模式允许在运行时动态地给对象添加功能,而代理模式则通过代理对象控制对另一个对象的访问。文章详细讲解了这两种模式的概念、常见问题、如何避免问题以及代码示例,帮助读者更好地理解和应用这些设计模式。

在面向对象编程中,设计模式是一种在特定情况下解决软件设计问题的通用可重用解决方案。本文将重点介绍两种常见的设计模式:装饰者模式和代理模式。我们将从概念入手,逐步深入到实现细节,并通过代码示例来帮助理解这些模式的应用场景和实现方式。

image.png

装饰者模式

概念

装饰者模式允许在运行时动态地给一个对象添加功能,而无需修改其结构。这种模式通过创建一个包装对象,即装饰者,来包裹真实对象,从而实现行为的增强或修改。

常见问题与易错点

  1. 过度使用装饰者:装饰者模式虽然强大,但过度使用会导致类层次结构过于复杂,难以维护。
  2. 性能问题:每次添加装饰者都会增加一层额外的调用,可能会影响性能。
  3. 透明性和透明装饰者:透明装饰者可以完全替代被装饰的对象,但不透明装饰者则不能。选择合适的装饰者类型很重要。

如何避免

  • 适度使用:只在确实需要动态添加功能时使用装饰者模式。
  • 性能优化:如果性能成为瓶颈,可以考虑使用其他优化手段,如缓存。
  • 明确需求:根据具体需求选择透明或不透明装饰者。

代码示例

假设我们有一个简单的 Logger 类,用于记录日志。我们希望在不修改原有代码的情况下,增加日志的格式化功能。

// 抽象组件
public abstract class Logger
{
   
    public abstract void Log(string message);
}

// 具体组件
public class ConsoleLogger : Logger
{
   
    public override void Log(string message)
    {
   
        Console.WriteLine(message);
    }
}

// 装饰者基类
public abstract class LoggerDecorator : Logger
{
   
    protected readonly Logger _logger;

    public LoggerDecorator(Logger logger)
    {
   
        _logger = logger;
    }

    public override void Log(string message)
    {
   
        _logger.Log(message);
    }
}

// 具体装饰者
public class TimestampLogger : LoggerDecorator
{
   
    public TimestampLogger(Logger logger) : base(logger) {
    }

    public override void Log(string message)
    {
   
        var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        base.Log($"{timestamp} - {message}");
    }
}

public class Program
{
   
    public static void Main()
    {
   
        Logger logger = new TimestampLogger(new ConsoleLogger());
        logger.Log("Hello, World!");
    }
}

在这个例子中,TimestampLogger 是一个装饰者,它在记录日志时添加了时间戳。

代理模式

概念

代理模式提供一个代理对象来控制对另一个对象的访问。代理对象可以在客户端和目标对象之间起到中介作用,从而实现各种功能,如延迟初始化、权限控制等。

常见问题与易错点

  1. 性能开销:代理模式会增加额外的调用开销,可能影响性能。
  2. 复杂性:代理模式可能会使代码结构变得复杂,特别是当代理逻辑较为复杂时。
  3. 透明性和不透明代理:透明代理可以完全替代被代理的对象,而不透明代理则不能。

如何避免

  • 适度使用:只在确实需要控制访问或延迟初始化时使用代理模式。
  • 性能优化:如果性能成为瓶颈,可以考虑使用其他优化手段,如异步调用。
  • 明确需求:根据具体需求选择透明或不透明代理。

代码示例

假设我们有一个 FileReader 类,用于读取文件内容。我们希望在读取文件之前进行权限检查。

// 抽象主题
public interface IFileReader
{
   
    string ReadFile(string filePath);
}

// 真实主题
public class FileReader : IFileReader
{
   
    public string ReadFile(string filePath)
    {
   
        return System.IO.File.ReadAllText(filePath);
    }
}

// 代理
public class FileReaderProxy : IFileReader
{
   
    private readonly FileReader _fileReader;

    public FileReaderProxy(FileReader fileReader)
    {
   
        _fileReader = fileReader;
    }

    public string ReadFile(string filePath)
    {
   
        if (CheckPermission())
        {
   
            return _fileReader.ReadFile(filePath);
        }
        else
        {
   
            throw new UnauthorizedAccessException("You do not have permission to read this file.");
        }
    }

    private bool CheckPermission()
    {
   
        // 模拟权限检查
        return true; // 假设用户有权限
    }
}

public class Program
{
   
    public static void Main()
    {
   
        IFileReader fileReader = new FileReaderProxy(new FileReader());
        try
        {
   
            string content = fileReader.ReadFile("example.txt");
            Console.WriteLine(content);
        }
        catch (UnauthorizedAccessException ex)
        {
   
            Console.WriteLine(ex.Message);
        }
    }
}

在这个例子中,FileReaderProxy 是一个代理,它在读取文件之前进行了权限检查。

总结

装饰者模式和代理模式都是设计模式中的重要成员,它们各自解决了不同的问题。装饰者模式适用于在运行时动态地给对象添加功能,而代理模式则适用于控制对对象的访问。通过合理使用这两种模式,可以提高代码的灵活性和可维护性。希望本文的介绍和代码示例能帮助你更好地理解和应用这些设计模式。

目录
相关文章
|
网络安全 C#
C#设计模式之十二代理模式(Proxy Pattern)【结构型】
原文:C#设计模式之十二代理模式(Proxy Pattern)【结构型】 一、引言   今天我们要讲【结构型】设计模式的第七个模式,也是“结构型”设计模式中的最后一个模式,该模式是【代理模式】,英文名称是:Proxy Pattern。
1795 0
|
SQL C# 设计模式
乐在其中设计模式(C#) - 代理模式(Proxy Pattern)
原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为其他对象提供一个代理以控制对这个对象的访问。
971 0
|
C# 设计模式 数据安全/隐私保护
C#设计模式(9)——装饰者模式(Decorator Pattern)
原文:C#设计模式(9)——装饰者模式(Decorator Pattern) 一、引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类)、AccessoriesPhone(挂件手机类)等,这样就会导致 ”子类爆炸“问题,为了解决这个问题,我们可以使用装饰者模式来动态地给一个对象添加额外的职责。
1092 0
|
C# 设计模式 iOS开发
C#设计模式(13)——代理模式(Proxy Pattern)
原文:C#设计模式(13)——代理模式(Proxy Pattern) 一、引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代理对象代替目标对象,然后客户端只需要访问代理对象,由代理对象去帮我们去请求目标对象并返回结果给客户端,这样的一个解决思路就是今天要介绍的代理模式。
1129 0
【读书笔记】代理模式代码(C#)
  代理模式代码,与大家分享,代码如下:/Files/cappuccino/ProxyModel.rar
689 0
|
10天前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。