简体   繁体   English

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

[英]Best practice for grouping Java classes for instantiation clarity

I am building a piece of software that sends and receives messages in particular binary definitions and with a particular version. 我正在构建一个软件,该软件以特定的二进制定义和特定的版本发送和接收消息。 As such, I have classes that look like this, which vary mostly only in the package name (the version, in this case): 因此,我有一些看起来像这样的类,它们的区别仅在于包名称(在本例中为版本)上:

For version 1.5: 对于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

and for version 2.7: 对于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

The class that manages the transmission and reception of these messages uses all versions, depending on where the message comes from, etc. 管理这些消息的发送和接收的类使用所有版本,具体取决于消息的来源等。

My problem is that defining an instance of the class requires I use the entire package path, because otherwise it's ambiguous. 我的问题是,定义类的实例需要我使用整个包路径,因为否则它是模棱两可的。 Even if there exists a situation where I use only one version in a given file, a casual reader of the code won't be able to see what version is being used. 即使存在在给定文件中仅使用一个版本的情况,临时的代码阅读器也无法看到正在使用的版本。 Pants pants = new Pants() is ambiguous until you look at the imported package. Pants pants = new Pants()在您查看导入的包之前是模棱两可的。

My ideal usage of this would be something like this: 我的理想用法是这样的:

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

That makes it very clear what version is being used. 这样就很清楚使用了哪个版本。 I could make this happen by creating the Pants message classes as inner classes of the V0207 class, but then the V0207 class becomes gigantic (there could be a hundred messages, each with 100 fields, for every given version). 我可以通过将Pants消息类创建为V0207类的内部类来实现这一点,但随后V0207类变得巨大(对于每个给定的版本,可能有一百条消息,每条消息包含100个字段)。 Is there possibly a way to #include an inner class, so they can be stored in separate files? 有没有办法#include一个内部类,以便可以将它们存储在单独的文件中? This would be ideal. 这将是理想的。

I suppose I can emulate this with a wrapper class, that does something (silly?) like this, where there exists an instance of the Pants class in the V0207 object: 我想我可以用一个包装器类来模拟它,这样做(傻吗?),在V0207对象中存在一个Pants类的实例:

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

But I dislike that. 但是我不喜欢这样。 It looks contrived and requires try/catch and casting when in use. 它看起来很虚构,在使用时需要尝试/捕捉和转换。 Terrible. 可怕。

I could also use a factory. 我也可以使用工厂。 That would be a bit nicer, but requires a parent class (or interface) and would require casting when used, since each message has unique methods. 这样会更好一些,但是需要一个父类(或接口),并且在使用时需要进行强制转换,因为每条消息都有唯一的方法。

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

or 要么

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

What are your thoughts? 你怎么看? I'm using JDK 1.7, but 1.8 might be usable. 我正在使用JDK 1.7,但1.8可能可用。

Consider using the factory design pattern with interfaces. 考虑使用带有接口的工厂设计模式。 The version of Java that you use does not make a difference (though support for Java 7 goes away in the spring, April if I remember correctly). 您所使用的Java版本没有什么不同(尽管我记得正确,但对Java 7的支持将在四月的春天消失)。

Define an interface for each class containing the method signatures that will be implemented by all the versions of the class. 为每个类定义一个接口,该接口包含将由该类的所有版本实现的方法签名。

Update your class definitions to include the appropriate interface definition. 更新您的类定义以包括适当的接口定义。

Create a class factory for each needed class, passing it the information needed to create the appropriate version of the class. 为每个所需的类创建一个类工厂,并向其传递创建适当版本的类所需的信息。 This class factory should return the interface type for the created class. 该类工厂应返回所创建类的接口类型。

Here is an example: 这是一个例子:

TestPants TestPants

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

IPants IPants

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

Pants 裤子

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 PantsV0105

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

PantsV0207 PantsV0207

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

PantsFactory 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;
    }
}

I initially solved this by using inner static classes in one gigantic "version" class. 我最初通过在一个巨大的“版本”类中使用内部静态类解决了此问题。 Thus, the use looked like this: 因此,用法如下所示:

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

But the version class ('V0207') grew too quickly, especially as other developers on the team demanded a more "Java" way of setting the fields (which required a lot of getters and setters). 但是版本类('V0207')的增长速度过快,尤其是当团队中的其他开发人员要求使用一种更“ Java”的方式设置字段时(这需要大量的getter和setter)。

Thus, the final solution is to put the messages inside their own v0207.messages package name, and prepend each message with the version: 因此,最终的解决方案是将消息放入其自己的v0207.messages包名称中,并在每个消息之前添加以下版本:

V0207_Pants pantsMessage = new V0702_Pants();

It's not as nice as using a C++ namespace, but it works. 它不像使用C ++名称空间那样好,但是可以工作。 The version is clear to the reader, and the object can contain a lot of code without any files becoming too large. 该版本对读者很清楚,并且该对象可以包含很多代码,而不会使任何文件变得太大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM