将Java类分组以实现实例化的最佳实践

时间:2015-01-03 15:45:55

标签: java inner-classes organization

我正在构建一个软件,用于发送和接收特定二进制定义和特定版本的消息。因此,我有类似这样的类,这些类主要仅在包名称(版本,在本例中)中有所不同:

对于1.5版:

com.mydomain.clothesmessage.v0105.fielddefinitions.Field100
com.mydomain.clothesmessage.v0105.fielddefinitions.Field200
com.mydomain.clothesmessage.v0105.messagedefinitions.Pants
com.mydomain.clothesmessage.v0105.messagedefinitions.Socks

和版本2.7:

com.mydomain.clothesmessage.v0207.fielddefinitions.Field100
com.mydomain.clothesmessage.v0207.fielddefinitions.Field200
com.mydomain.clothesmessage.v0207.messagedefinitions.Pants
com.mydomain.clothesmessage.v0207.messagedefinitions.Socks

管理这些消息的传输和接收的类使用所有版本,具体取决于消息的来源等。

我的问题是定义类的实例需要我使用整个包路径,否则它是不明确的。即使存在我在给定文件中仅使用一个版本的情况,代码的随意读者也无法看到正在使用的版本。在查看导入的包之前,Pants pants = new Pants()是不明确的。

我对此的理想用法是这样的:

V0207.Pants pantsMessage = new V0702.Pants();

这清楚地说明了正在使用的版本。我可以通过将Pants消息类创建为V0207类的内部类来实现这一点,但随后V0207类变得巨大(每个给定版本可能有一百条消息,每条消息有100个字段)。有没有办法#include一个内部类,所以它们可以存储在单独的文件中?这将是理想的。

我想我可以用一个包装类来模拟它,它做了一些事情(愚蠢?),这样在V0207对象中存在Pants类的实例:

Object pantsMessage = V0207.pants.getClass().newInstance();
((com.mydomain.clothesmessage.v0207.messagedefinitions.Pants)pantsMessage).getZipperType();

但我不喜欢这样。它看起来很人为,在使用时需要试用/捕捉和铸造。可怕。

我也可以使用工厂。这会更好一些,但需要父类(或接口),并且在使用时需要转换,因为每条消息都有唯一的方法。

Message pantsMessage = V0207Factory.newMessage(V0207.PantsMessage);
((com.mydomain.clothesmessage.v0207.messagedefinitions.Pants)pantsMessage).getZipperType();

Message sockMessage = V0207Factory.newSock();
((com.mydomain.clothesmessage.v0207.messagedefinitions.Socks)sockMessage).getSmellLevel();

你有什么想法?我使用的是JDK 1.7,但1.8可以使用。

2 个答案:

答案 0 :(得分:1)

考虑将工厂设计模式与接口一起使用。您使用的Java版本没有什么区别(尽管如果我没记错的话,4月份对Java 7的支持会消失)。

为每个类定义一个接口,其中包含将由该类的所有版本实现的方法签名。

更新您的类定义以包含适当的接口定义。

为每个需要的类创建一个类工厂,并为其传递创建适当版本的类所需的信息。此类工厂应返回已创建类的接口类型。

以下是一个例子:

<强> TestPants

public class TestPants {
    IPants pants = PantsFactory.PantsFactory(207);
    Message zipperType = pants.getZipperType();
    Message color = pants.getColor();
    )
}

<强> IPants

public interface IPants {
    Message getZipperType();
    Message getColor();
}

<强>裤子

public class Pants implements IPants {
    // Class fields and Object fields
    @Override
    public Message getColor () {
        return null;
    }
    @Override
    public Message getZipperType () {
        return null;
    }
    // implement any common methods among all versions
}

<强> PantsV0105

public class PantsV0105 extends Pants {
    // add changes for this version
}

<强> PantsV0207

public class PantsV0207 extends Pants {
    // add changes for this version
}

<强> PantsFactory

public class PantsFactory {
    public static IPants PantsFactory(int version) {
        switch (version) {
        case 105: return new PantsV0105(); break;
        case 207: return new PantsV0207(); break;
            default: return null;
    }
}

答案 1 :(得分:0)

我最初通过在一个巨大的“版本”类中使用内部静态类来解决这个问题。因此,使用看起来像这样:

V0207.Pants pantsMessage = new V0702.Pants();

但是版本类('V0207')增长得太快了,特别是当团队中的其他开发人员要求采用更“Java”的方式设置字段时(需要大量的getter和setter)。

因此,最终的解决方案是将消息放在他们自己的v0207.messages包名中,并在每个消息前加上版本:

V0207_Pants pantsMessage = new V0702_Pants();

它不如使用C ++命名空间那么好,但它可以工作。该版本对于读者来说是清楚的,并且该对象可以包含大量代码而不会使任何文件变得太大。