分组 Java 类 以实现实例化清晰度的最佳实践
Best practice for grouping Java classes for instantiation clarity
我正在构建一个软件,可以发送和接收特定二进制定义和特定版本的消息。因此,我有 class 看起来像这样的,它们主要仅在包名称(在本例中为版本)上有所不同:
对于 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
管理这些消息的传输和接收的class使用所有版本,具体取决于消息的来源等
我的问题是定义 class 的实例需要我使用整个包路径,否则它会不明确。即使存在我在给定文件中只使用一个版本的情况,随意 reader 代码也无法看到正在使用的版本。 Pants pants = new Pants()
在您查看导入包之前是不明确的。
我的理想用法是这样的:
V0207.Pants pantsMessage = new V0702.Pants();
这使得使用的版本一目了然。我可以通过将裤子消息 classes 创建为 V0207 class 的内部 classes 来实现这一点,但随后 V0207 class 变得巨大(可能有一百个消息,每个版本有 100 个字段)。有没有办法 #include 一个内部 class,这样它们就可以存储在单独的文件中?这将是理想的。
我想我可以用一个包装器 class 来模拟它,它做一些事情(愚蠢的?)像这样,在 V0207 对象中存在一个裤子 class 的实例:
Object pantsMessage = V0207.pants.getClass().newInstance();
((com.mydomain.clothesmessage.v0207.messagedefinitions.Pants)pantsMessage).getZipperType();
但我不喜欢那样。它看起来做作并且在使用时需要 try/catch 和转换。太可怕了。
我也可以使用工厂。那会好一点,但需要父 class(或接口)并且在使用时需要强制转换,因为每条消息都有独特的方法。
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 可能可用。
考虑使用带接口的工厂设计模式。您使用的 Java 版本没有区别(尽管如果我没记错的话,对 Java 7 的支持在 spring 的四月份消失了)。
为每个 class 定义一个接口,其中包含将由 class 的所有版本实现的方法签名。
更新您的 class 定义以包含适当的接口定义。
为每个需要的 class 创建一个 class 工厂,将创建 class 的适当版本所需的信息传递给它。此 class 工厂应 return 所创建 class 的接口类型。
这是一个例子:
试裤
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
}
裤子V0105
public class PantsV0105 extends Pants {
// add changes for this version
}
裤子V0207
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;
}
}
我最初通过在一个巨大的 "version" class 中使用内部静态 classes 解决了这个问题。因此,使用看起来像这样:
V0207.Pants pantsMessage = new V0702.Pants();
但是版本 class ('V0207') 增长太快,尤其是当团队中的其他开发人员需要更多 "Java" 设置字段的方式时(这需要大量吸气剂和吸气剂)。
因此,最终的解决方案是将消息放在它们自己的 v0207.messages 包名称中,并在每条消息前加上版本:
V0207_Pants pantsMessage = new V0702_Pants();
它不如使用 C++ 名称空间好,但它可以工作。版本清晰到reader,对象可以包含很多代码而不会导致任何文件变得太大。
我正在构建一个软件,可以发送和接收特定二进制定义和特定版本的消息。因此,我有 class 看起来像这样的,它们主要仅在包名称(在本例中为版本)上有所不同:
对于 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
管理这些消息的传输和接收的class使用所有版本,具体取决于消息的来源等
我的问题是定义 class 的实例需要我使用整个包路径,否则它会不明确。即使存在我在给定文件中只使用一个版本的情况,随意 reader 代码也无法看到正在使用的版本。 Pants pants = new Pants()
在您查看导入包之前是不明确的。
我的理想用法是这样的:
V0207.Pants pantsMessage = new V0702.Pants();
这使得使用的版本一目了然。我可以通过将裤子消息 classes 创建为 V0207 class 的内部 classes 来实现这一点,但随后 V0207 class 变得巨大(可能有一百个消息,每个版本有 100 个字段)。有没有办法 #include 一个内部 class,这样它们就可以存储在单独的文件中?这将是理想的。
我想我可以用一个包装器 class 来模拟它,它做一些事情(愚蠢的?)像这样,在 V0207 对象中存在一个裤子 class 的实例:
Object pantsMessage = V0207.pants.getClass().newInstance();
((com.mydomain.clothesmessage.v0207.messagedefinitions.Pants)pantsMessage).getZipperType();
但我不喜欢那样。它看起来做作并且在使用时需要 try/catch 和转换。太可怕了。
我也可以使用工厂。那会好一点,但需要父 class(或接口)并且在使用时需要强制转换,因为每条消息都有独特的方法。
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 可能可用。
考虑使用带接口的工厂设计模式。您使用的 Java 版本没有区别(尽管如果我没记错的话,对 Java 7 的支持在 spring 的四月份消失了)。
为每个 class 定义一个接口,其中包含将由 class 的所有版本实现的方法签名。
更新您的 class 定义以包含适当的接口定义。
为每个需要的 class 创建一个 class 工厂,将创建 class 的适当版本所需的信息传递给它。此 class 工厂应 return 所创建 class 的接口类型。
这是一个例子:
试裤
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
}
裤子V0105
public class PantsV0105 extends Pants {
// add changes for this version
}
裤子V0207
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;
}
}
我最初通过在一个巨大的 "version" class 中使用内部静态 classes 解决了这个问题。因此,使用看起来像这样:
V0207.Pants pantsMessage = new V0702.Pants();
但是版本 class ('V0207') 增长太快,尤其是当团队中的其他开发人员需要更多 "Java" 设置字段的方式时(这需要大量吸气剂和吸气剂)。
因此,最终的解决方案是将消息放在它们自己的 v0207.messages 包名称中,并在每条消息前加上版本:
V0207_Pants pantsMessage = new V0702_Pants();
它不如使用 C++ 名称空间好,但它可以工作。版本清晰到reader,对象可以包含很多代码而不会导致任何文件变得太大。