普通类的工厂派生自通用专业化

时间:2016-06-14 16:59:50

标签: c# generics inheritance refactoring factory

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

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<T>()

更新

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

1 个答案:

答案 0 :(得分:0)

如果您想以这种方式有效地重构代码,那么您必须考虑到&#34;使用D1&#34;和&#34;与D2&#34;合作必须是相同的,只有行为必须不同;也就是说,D1和D2必须有一个共同的界面&#34; (B<T>)并且您应该只使用所说的&#34;界面&#34;否则您将再次开始使用意大利面条代码和丑陋的演员。

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

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<T>如下:

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> { ... }
}

现在你可以绝对控制可以实现多少Di个,你可以暴露一个通用的B<T>,并且你保证总是提供正确的专用类型而不实际让消费者不得不了解它。