【问题标题】:The Decorator Pattern & Extension Methods in c#c# 中的装饰器模式和扩展方法
【发布时间】:2011-06-20 18:16:39
【问题描述】:

在开始描述我的问题之前,我想定义装饰器和扩展方法的定义 装饰器

动态地为对象附加额外的职责。装饰器为扩展功能提供了一种灵活的替代子类的方法

扩展方法

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型

我在c#中有以下代码sn-p

public interface IMyInterface
{
    void Print();
}

public static class Extension
{
    public static void PrintInt(this IMyInterface myInterface, int i)
    {
        Console.WriteLine
            ("Extension.PrintInt(this IMyInterface myInterface, int i)");
    }

    public static void PrintString(this IMyInterface myInterface, string s)
    {
        Console.WriteLine
            ("Extension.PrintString(this IMyInterface myInterface, string s)");
    }
}

public class Imp : IMyInterface
{
    #region IMyInterface Members

    public void Print()
    {
        Console.WriteLine("Imp");
    }

    #endregion
}

class Program
{
    static void Main(string[] args)
    {
        Imp obj = new Imp();
        obj.Print();
        obj.PrintInt(10);
    }
}

在上面的代码中,我在不修改现有代码的情况下扩展接口,这两种方法可用于派生类。所以我的问题是:扩展方法是装饰器模式的替代品吗?

【问题讨论】:

  • 可能会发现装饰器模式取代了静态扩展方法,主要是因为静态方法难以测试并且它们增加了耦合。

标签: c# design-patterns


【解决方案1】:

你错过了装饰器模式的动态部分。扩展方法是在编译时定义的静态野兽,可以使用也可以不使用……但在运行时不能修改/交换。

【讨论】:

  • 感谢 jdehaan 的评论。您的意思是,在装饰器模式中,我们添加了新功能以在不知情的情况下动态输入。
  • 是的,这通常涉及对接口达成一致,但此功能也应在运行时可替换,而扩展方法并非如此:它们是编译时的选择。
【解决方案2】:

扩展方法实际上只是调用静态方法的语法糖。

虽然使用装饰器实际上可以改变被装饰类的行为,但扩展方法只能改变类的属性或调用方法,就像“普通”静态方法一样。

装饰器模式实际上被定义为使用包装器来改变行为,而扩展方法显然没有这样做。

【讨论】:

    【解决方案3】:

    扩展方法不能替代装饰器模式。扩展方法可以为现有类型提供功能,而无需创建派生类型。

    这与装饰器模式的传统实现不同。装饰器模式允许您在运行时为对象动态提供多种行为,而无需为这些行为的每个组合创建新的子类。

    【讨论】:

      【解决方案4】:

      扩展方法是装饰器模式还是访客模式?看完后我会说它更类似于访客。

      引用维基百科的伟大之处,永远不会出错的百科:P

      在面向对象的编程和软件工程中,访问者 设计模式是一种将算法与对象分离的方法 它运行的结构。这种分离的实际结果是 无需向现有对象结构添加新操作的能力 修改这些结构。这是轻松遵循的一种方法 开/关原则。本质上,访问者允许添加新的 类族的虚函数而不修改类 他们自己;相反,创建一个访问者类来实现所有 虚函数的适当特化。这 访问者将实例引用作为输入,并实现目标 通过双重调度。

      【讨论】:

        【解决方案5】:

        Erich Gamma (GoF) 的这个解释似乎是最好的……http://www.mif.vu.lt/~plukas/resources/Extension%20Objects/ExtensionObjectsPattern%20Gamma96.pdf

        主要是说明

        a) 将不同客户端(现在和未来)所需的所有操作和状态组合到一个接口中会导致接口臃肿

        b) 所需的操作(已知和未知)可以分为组件。可以从中定义一个(或多个)组件接口)(扩展接口)。这些可能由对象(当前和未来)实现,也可能不实现。

        c) 希望使用此扩展接口的客户端可以查询组件是否支持它

        d) 最后,这个扩展接口有一个通用的基类(ComponentExtension)和最小的接口来管理扩展本身(检查扩展是否存在,通知扩展它即将被删除)

        在以下情况下使用:

        1 当您现有的类可能需要附加不可预见的接口(即新的、当前未知的行为模式)时。

        2 当一个代表关键抽象的类为不同的客户扮演不同的(不可预见的和开放式的)角色时。

        3 你希望在没有子类的情况下进行扩展

        类似于下面的模式

        访问者需要稳定的类层次结构并引入依赖循环

        装饰器,使用更透明,界面狭窄,应扩充现有操作

        适配器,支持现有接口

        【讨论】:

          猜你喜欢
          • 2013-02-19
          • 1970-01-01
          • 2014-10-29
          • 2017-04-02
          • 1970-01-01
          • 2018-12-23
          • 1970-01-01
          • 2011-11-22
          • 2012-01-28
          相关资源
          最近更新 更多