Java中的通用工厂方法

3

我知道有一些关于这个主题的帖子,但我无法确定我的问题所在。阅读搜索结果时,我比以往更困惑了。我希望我能清楚地表达我的问题。

我有一个消息类型层次结构和一个用于这些消息的通用处理器层次结构。到目前为止,我已经成功运行了这个程序。现在我想为处理器实现一个工厂方法,并被我选择的通用方法卡住了。请看我的示例:

abstract class Message
{
    abstract int getTest();
}

class MyMessage1 extends Message
{
    @Override
    int getTest()
    {
        return 1;
    }
}

class MyMessage2 extends Message
{
    @Override
    int getTest()
    {
        return 2;
    }
}

interface Processor<T extends Message>
{
    void initialize(final T p_message);

    void doWork();
}

abstract class BaseMessageProcessor<T extends Message> implements Processor<T>
{
    private T message;

    @Override
    public void initialize(T p_message)
    {
        message = p_message;
    }

    protected T getMessage()
    {
        return message;
    }
}

class MyMessage1Processor extends BaseMessageProcessor<MyMessage1>
{
    @Override
    public void doWork()
    {
        // perfectly valid assignment
        MyMessage1 msg = getMessage();
        // do something
    }
}

class MyMessage2Processor extends BaseMessageProcessor<MyMessage2>
{
    @Override
    public void doWork()
    {
        // perfectly valid assignment
        MyMessage2 msg = getMessage();
        // do something
    }
}

目前这个部分是有效的,并且按预期工作。但是现在需要使用工厂:

class ProcessorFactory
{
    <T extends Message> Processor<T> createProcessor(final Class<T> p_msgType)
    {
        if (p_msgType.equals(MyMessage1.class))
        {
            // Type mismatch: cannot convert from MyMessage1Processor to Processor<T>
            return new MyMessage1Processor();
        }
        else if (p_msgType.equals(MyMessage2.class))
        {
            // Type mismatch: cannot convert from MyMessage2Processor to Processor<T>
            return new MyMessage2Processor();
        }
        else
        {
            throw new Exception("Unsupported message type: " + p_msgType);
        }
    }
}

也许我在这里犯了一个愚蠢的错误,但我看不到。如果有人能给我提示,我会很感激。

敬礼

塞巴斯蒂安

编辑: 好吧,我的错。问题在于我得到了编译器错误,如注释中所述,“默认区域设置”(例如,对于第二个返回语句,我得到了编译错误):

类型不匹配:无法从MyMessage2Processor转换为Processor


1
第二段代码区域中有注释。我相信它们表达了问题的本质。 - default locale
5
我遇到了一个问题,于是想使用Java来解决。现在我有了一个ProblemFactory。 - Gregory Pakosz
当然,我可以将MyMessage1Processor强制转换为Processor<T>,但为什么要使用泛型呢?难道没有一种直接的类型安全的方法来做到这一点吗? - Sebastian Götz
这是在没有泛型的情况下对基于泛型的类进行子类化(例如IntegerArrayList extends ArrayList<Integer>)时的常见陷阱。据我所知,您不能再将它们泛化处理。 - David Harkness
这似乎是正确的,因为这样做是有效的:if (p_msgType.equals(MyMessage1.class)) { return new BaseMessageProcessor<T>() { @Override public void doWork() { } }; } 这等同于我的子类化。 - Sebastian Götz
请不要在Java中制造核弹,当你写超过100行代码时就准备好爆炸。你不想花费整夜来调试,对吧?那么请看看我的建议。 - Edmondo
1个回答

2
要了解为什么您失败了,您必须了解类型擦除的工作原理:
当您明确知道自己做得对时,编译器不知道,更重要的是,因为信息已被取消,所以无法知道设计上是否正确。
让我尝试进一步解释这个概念:由于类型擦除,在编译时,类型T被转换为java.lang.Object,并且Java编译器没有编译时信息说:
如果 a.getClass().equals(MyClass.class) 那么 a.getClass() 的类型 将是MyClass<MyClass>
重要提示:请尽量避免编写此代码,因为它会导致可怕的设计。如果你不想在错误和难以维护的代码地狱中死去,请勿强制类型安全语言使用逻辑证明类型安全而不是编译类型证据。如果您通过编译器进行类型安全强制转换,则有可能某天更改类结构并忘记更改工厂,所有内容都正常编译,但运行时会出现问题。
工厂方法通常是隐藏生产对象逻辑的模式,如果您最终处于这种情况,则可能意味着您没有正确使用泛型。编写一个更干净的设计,写一门课程会更好。
也许您可以添加一个附加问题:如何以类型安全的方式实现这种模式?

1
嗯,类型擦除。之前就是这个问题的核心 :-) 你说得对,我的直觉告诉我在这里进行强制转换并不是正确的解决方案。所以我从Processor接口中移除了泛型类型。谢谢。 - Sebastian Götz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接