【问题标题】:Generic base class wraps nested generic class to reduce type argument specification: Is there a name for this pattern?泛型基类包装嵌套泛型类以减少类型参数规范:这种模式有名称吗?
【发布时间】:2013-04-18 11:57:57
【问题描述】:

好的问题标题远非不言自明。我经常看到自己这样做:

来自this answer

public static class Equality<T>
{
    public static IEqualityComparer<T> CreateComparer<K>(Func<T, K> keySelector)
    {
        return new KeyEqualityComparer<K>(keySelector);
    }



    class KeyEqualityComparer<K> : IEqualityComparer<T>
    {
        readonly Func<T, K> keySelector;

        public KeyEqualityComparer(Func<T, K> keySelector)
        {    
            this.keySelector = keySelector;
        }

        public bool Equals(T x, T y)
        {
            ----
        }

        public int GetHashCode(T obj)
        {
            ....
        }
    }
}

我做了什么:有一个实现细节 KeyEqualityComparer&lt;T, K&gt; 我必须调用:

new KeyEqualityComparer<Person, int>(p => p.ID);

通过将其嵌套为私有类,我不仅隐藏了实现(内部类的公共构造函数现在已经模糊了),而且获得了更好的语法:

Equality<Person>.CreateComparer(p => p.ID);

请注意,我没有从父类(静态)继承嵌套类。

或者有时我看到自己doing this

public abstract class Equater<T> : IEqualityComparer<T>
{
    public static Equater<T> Create<TKey>(Func<T, TKey> keySelector)
    {
        return new Impl<TKey>(keySelector);
    }

    public abstract bool Equals(T x, T y);

    public abstract int GetHashCode(T obj);



    class Impl<TKey> : Equater<T>
    {
        readonly Func<T, TKey> keySelector;

        public Impl(Func<T, TKey> keySelector)
        {
            this.keySelector = keySelector;
        }

        public override bool Equals(T x, T y)
        {
            ----
        }

        public override int GetHashCode(T obj)
        {
            ....
        }
    }
}

另一个类似的here

public class Accessor<S>
{
    public static Accessor<S, T> Create<T>(Expression<Func<S, T>> memberSelector)
    {
        return new GetterSetter<T>(memberSelector);
    }

    class GetterSetter<T> : Accessor<S, T>
    {
        public GetterSetter(Expression<Func<S, T>> memberSelector) : base(memberSelector)
        {

        }
    }
}

public class Accessor<S, T> : Accessor<S>
{
    Func<S, T> Getter;
    Action<S, T> Setter;

    public bool IsReadable { get; private set; }
    public bool IsWritable { get; private set; }
    public T this[S instance]
    {
        get
        {
            if (!IsReadable)
                throw new ArgumentException("Property get method not found.");

            return Getter(instance);
        }
        set
        {
            if (!IsWritable)
                throw new ArgumentException("Property set method not found.");

            Setter(instance, value);
        }
    }

    protected Accessor(Expression<Func<S, T>> memberSelector) //access not given to outside world
    {
        ----
    }

}

请注意,在这两种情况下,我从包装类继承。所以现在我不仅得到了前者的好处,而且还可以维护这样的列表:

List<Equater<Person>> { persons with different implementations };

它不时帮助我。 所以我很想知道这种模式是否有名称?

【问题讨论】:

    标签: c# generics design-patterns naming nested-class


    【解决方案1】:

    我认为这很像基于抽象工厂模式的Class Clusters pattern

    【讨论】:

      【解决方案2】:

      我认为你在这里没有遵循任何一种模式。

      我想说,通过用一个“Create”方法替换多个“CreateComparer”方法,您只是简化了一个 Creation Method 模式。你可以在某种意义上说这是一种工厂模式?!或者也许是一种建造者模式——我猜那个是可以解释的?!

      通过在“Equater”中嵌入“Impl”,您有点遵循命令模式 - 封装方法调用,以便您的调用代码不知道它是如何完成的

      无论如何,对不起,我不能比这更有帮助或给你一个明确的答案!无论如何,希望它有所帮助!

      【讨论】:

      • 对不起,我编辑了答案,因为我认为我根本没有使用命令或构建器模式。如果我的答案有差异,请随时编辑
      • @nawfal:虽然我们鼓励编辑答案以改进它们,但请记住,您应该尊重原作者的写作。在伯蒂的原始答案中,您的编辑似乎变化太大 - 特别是您对最后一段的编辑可能会让人觉得是在别人嘴里说的话。也就是说,我会让 Bertie 决定他是要保留编辑还是回滚,因为答案属于他。如果他确实回滚了它们,您可能希望发布您的研究作为自己的答案。
      • 感谢 BoltClock - 我已经回滚了更改,因为我相信它对我原来的答案的改变太多了。但是,如果@nawfal 愿意将他的 cmets 添加为新答案,那么我显然对此没有任何问题。
      • @BoltClock 抱歉,我希望选择他的答案,因为他给了我正确的方向。但我发现了一些我认为的事实错误。尽管我试图纠正他的回答,但我尽可能地留下了他的话(这就是为什么你会看到很多相似之处)。但最后我同意这是太多的编辑。感谢您的提示,我会记住的。
      • @Bertie 你真的认为这里有命令模式或构建器模式吗?没门。命令模式是关于封装(如将所有相关信息组合在一起),但不是以我接近的方式(保护免受外界影响)。事实上,我认为我所做的与命令模式完全相反,我根本不公开实现,而只公开 ICommand。看到这个en.wikipedia.org/wiki/Command_pattern
      【解决方案3】:

      正如 Bertie 正确指出的那样,我在这里可能没有遵循 任何一个 模式。

      我想说,通过将具体实现的实例化委托给CreateComparer 方法,我刚刚简化了对象创建——它属于Creation Method patterns。通过为对象实例化提供一个静态函数,它有点像工厂模式 - 特别是this variant of Factory Method

      通过从Equater 继承Impl,我有点遵循Abstract Factory 模式-其中Equater 是工厂的工厂,Impl 是它的实现,以将Impl 本身返回,除了@987654332 @ 实际上并没有创建任何其他对象(换句话说,Impl 并不意味着是一个工厂),而是通过构造函数实例化自身。所以严格来说,它不是抽象工厂模式,但它更接近于Impl可以有一个方法来调用自己的构造函数并返回一个实例。

      此外,通过嵌入和隐藏实现细节(嵌套类本身),暴露的类(父类)向外界假装,好像它正在做它的工作。这就是所谓的Delegation Pattern

      至于在嵌套的泛型类中隐藏泛型类的实现以便为方法调用提供更简单的签名的名称,我认为不存在这样的名称。即使存在任何名称,它也必须非常特定于语言(或类似语言),因为涉及到诸如泛型/类型推断等语言结构。 Eric Lippert 在嵌套类 here 中发现了相同的用途,尽管它与泛型无关,他称之为工厂模式。

      【讨论】:

        猜你喜欢
        • 2019-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多