如何使用工厂模式的通用接口? [英] How do I use a generic interface with the factory pattern?
问题描述
这是一个代码真的值得千言万语的案例。后面的代码无法编译。我希望它足够接近显示我想要做的事情。
我没有看到任何在概念上错误的我想要做但似乎是完全混淆语法。当然,如果我想做的事情从根本上讲是一个坏主意,我总是愿意从更多的头脑中学习。
希望,不言而喻是一个人为的例子,没有任何错误检查。我只是想展示我想要实现的模式。
This is one case where code really is worth a thousand words. The code that follows does not compile. I hope it is close enough to show what I am trying to do.
I don't see anything conceptually wrong with what I am trying to do but seem to be in a complete mix-up with syntax. Of course, if what I am trying to do is fundamentally a bad idea, I am always willing to learn from greater minds.
Hopefully, it goes without saying that this is a contrived example, lacking any error checking. I'm just trying to show the pattern I am trying to implement.
public interface IReturnsValue<T>
{
void SetValues( List<T> listOfValues );
T NextValue { get; }
}
public class IntegerReturner : IReturnsValue<int>
{
public void SetValues( List<int> listOfValues ) { _values = listOfValues; }
public int NextValue => _values[ _indexOfNextValue++ ];
private int _indexOfNextValue = 0;
private List<int> _values = null;
}
public class DoubleReturner : IReturnsValue<double>
{
public void SetValues( List<double> listOfValues ) { _values = listOfValues; }
public double NextValue => _values[ _indexOfNextValue++ ];
private int _indexOfNextValue = 0;
private List<double> _values = null;
}
public class ValueReturnerFactory
{
public IReturnsValue<T> CreateValueReturner<T>( string name )
{
if( name == "IntegerReturner" )
return new IntegerReturner();
if( name == "DoubleReturner" )
return new DoubleReturner();
throw new ArgumentException();
}
}
class Program
{
static void Main( string[] args )
{
ValueReturnerFactory factory = new ValueReturnerFactory();
IReturnsValue<T> firstValueReturner = factory.CreateValueReturner<int>( "IntegerReturner" );
IReturnsValue<T> secondValueReturner = factory.CreateValueReturner<double>( "DoubleReturner" );
}
}
我尝试了什么:
我能想到的通用代码类型参数的每种组合。 :(
What I have tried:
Every combination of generic code type parameter I can think of. :(
推荐答案
它不起作用,因为编译器在使用IntegerReturner等时无法检查T是否始终为int。例如,以下调用将是根据方法签名有效:
It doesn't work as the compiler can't check if T is always an int when using IntegerReturner etc. For example, the following call would be valid according to the method signature:
factory.CreateValueReturner<bool>("IntegerReturner")
它必须返回 IReturnsValue< int>
作为 IReturnsValue< bool>
。
您可以接管责任并投入工厂。所以:
where it would have to return an IReturnsValue<int>
as an IReturnsValue<bool>
.
You can "take over responsibility" and cast in the factory. So:
public IReturnsValue<T> CreateValueReturner<T>(string name)
{
if (name == "IntegerReturner")
return (IReturnsValue<T>)new IntegerReturner();
if (name == "DoubleReturner")
return (IReturnsValue<T>)new DoubleReturner();
throw new ArgumentException();
}
如果类型不匹配,您将获得运行时异常。
您还必须在Main方法中指定类型,因为此处未定义T(或者当然使用 var
):
you will then get a runtime exception if the types do not match.
You also have to specify the type in the Main method as T isn't defined here (or use var
of course):
IReturnsValue<int> firstValueReturner = factory.CreateValueReturner<int>("IntegerReturner");
IReturnsValue<double> secondValueReturner = factory.CreateValueReturner<double>("DoubleReturner");
很难说是否有更好的方法来实现这一点,这取决于其余的代码和个人偏好。如果是我,我会考虑是否可以删除名称并选择要从T类型实例化的类 - 那么你就不会遇到T和名称不匹配的情况。工厂方法可以是这样的:
It's hard to say if there are better ways to implement this, it depends on the rest of the code and personal preference. If it was me, I would consider if I could get rid of the name and select the class to instantiate from the type of T - then you can't have a situation where T and name do not match. The factory method can be something like this:
public IReturnsValue<T> CreateValueReturner<T>()
{
if (typeof(T) == typeof(int))
return (IReturnsValue<T>)new IntegerReturner();
if (typeof(T) == typeof(double))
return (IReturnsValue<T>)new DoubleReturner();
throw new ArgumentException();
}
这篇关于如何使用工厂模式的通用接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!