我正在构建一个软件,用于发送和接收特定二进制定义和特定版本的消息。因此,我有类似这样的类,这些类主要仅在包名称(版本,在本例中)中有所不同:
对于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可以使用。
答案 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 ++命名空间那么好,但它可以工作。该版本对于读者来说是清楚的,并且该对象可以包含大量代码而不会使任何文件变得太大。