如何使用工厂模式的通用接口? [英] How do I use a generic interface with the factory pattern?

查看:90
本文介绍了如何使用工厂模式的通用接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个代码真的值得千言万语的案例。后面的代码无法编译。我希望它足够接近显示我想要做的事情。



我没有看到任何在概念上错误的我想要做但似乎是完全混淆语法。当然,如果我想做的事情从根本上讲是一个坏主意,我总是愿意从更多的头脑中学习。



希望,不言而喻是一个人为的例子,没有任何错误检查。我只是想展示我想要实现的模式。



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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆