【问题标题】:Factory of plain classes derived from generic specializations从泛型特化派生的普通类的工厂
【发布时间】:2016-06-14 16:59:50
【问题描述】:

我有一个 C# 泛型类 B<T>。我还有一组派生类Di : B<Ti>。所有这些类始终使用相同的参数集创建。 所以它导致了意大利面条代码:

if (typeof(T) == typeof(A1)) {work with D1}
else if (typeof(T) == typeof(A2)) {work with D2}
...

显然我想重构代码,使其看起来像这样:

var dInst = GiveMeD<T>();
work with Di

如何实现函数GiveMeD&lt;T&gt;()

更新:

work with Di -> 转换为基类B&lt;T&gt; 并使用它的接口。 这里的主要问题 - 每个代码块在派生类构造函数调用中都不同。

【问题讨论】:

  • “与 D1 合作”是否与“与 D2 合作”等不同?
  • public static T GiveMeD(){ //code here } 这里的代码code会有一个对象列表,你可以写一个类似这样的LINQ查询: var objs=List.Where (p=>p.GetType()== T)。
  • 我会说不是 Where(),而是 FirstOrDefault()...

标签: c# generics inheritance refactoring factory


【解决方案1】:

如果你想以这种方式有效地重构代码,那么你必须考虑到“使用D1”和“使用D2”必须相同,只有行为必须不同;也就是说,D1 和 D2 必须有一个共同的“接口”(B&lt;T&gt;),并且您应该只利用所说的“接口”,否则您将再次开始到处出现意大利面条代码和丑陋的演员表。

如果这符合您的需求(如果不符合,那么您应该重新考虑解决问题的整个方法),常见的模式是简单地创建一个工厂方法,您的意大利面条代码只会被编写一次:

public static B<T> CreateD<T>()
{
    if (T is A1) return ... //here you can create a new instance of D1 or return a cached one, etc.
    else if (T is A2) return ...
}

当消费者不需要知道D1D2等而只需要知道B&lt;T&gt;时,我喜欢使用的一个漂亮的模式如下:

public class B<T>
{
    public B<T> CreateD<T>()
    {
        if (T is A1) return ... //here you can create a new instance of D1 or return a cached one, etc.
        else if (T is A2) return ...
        ...
    }

    private B() { } //note constructor is private, consumer can't create a B<T>

    private class D1: B<A1> { ... } //private nested types, not visible outside B<T>.
    private class D2: B<A2> { ... }
}

现在您可以完全控制可以实现多少Dis,您公开了一个通用的B&lt;T&gt;,并且您保证始终返回正确的专用类型,而无需让消费者真正了解它.

【讨论】:

  • 我对这种方法有一个疑问:基类应该知道派生自它的类吗?我不相信。
  • @user2123007 并没有。派生类是基类中的私有嵌套类这一事实只是一种方便的模式,可以向消费者隐藏实现细节,但仅此而已。尝试找到一条信息 B&lt;T&gt; 有关于 D1D2 的信息,如果派生类没有嵌套,则不会有这些信息。
  • @user2123007 嵌套在基类中的私有模式是针对特定场景的解决方案。就像我说的,它涵盖了肯定不是继承的一般用例的特殊需求。在您的特定场景中,这种模式很可能不是最好的方法,常规的工厂方法就足够了。
  • @user2123007 如何使用这种模式的一个很好的例子就是这个简单的immutable stack class
猜你喜欢
  • 1970-01-01
  • 2020-09-17
  • 2018-01-08
  • 1970-01-01
  • 2014-09-23
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多