测试 object 工厂
Testing object factory
我实现了如下工厂:
class MessageFactory {
private static final Map<Integer, MessageBuilder> IdToMessage = new HashMap<Integer, MessageBuilder>() {{
put(StatusMessage.ID, StatusMessage::new);
put(ConfigurationMessage.ID, ConfigurationMessage::new);
}};
public createMessage(byte[] payload){
int id = getId(payload);
return typeToMessage.get(id).create(payload);
}
}
此工厂接收消息的有效负载(字节),从其 header 中获取消息的 ID,然后使用其引用存储在 HashMap 中的相应消息的构造函数。
我想执行一个测试以确保所有消息都在 HashMap 中定义。
所有消息都在同一个 java 包中,编写一个测试以确保此 java 包中的所有 java 类都在 Hashmap 中是否有意义?
你有没有看到任何其他方法来确保一旦添加了新消息,它也会被添加到这个 hashmap 中?这是我正在开发的代码中的一个问题,因为这种模式在多个地方使用。
我建议重构您的代码,以便编译器为您完成这项工作。
选项 1:切换表达式
首先,熟悉Java12.
中介绍的switch expressions
Exhaustiveness
When using switch statements, it doesn't really matter if all cases are covered.
For switch expressions though, the compiler insists that all possible cases are covered.
将其应用到您的案例中:
- 创建新的 MessageType 枚举
- 允许从 int id 创建 MessageType
- 重构 crateMessage 以利用 switch 表达式
enum MessageType {
STATUS_MESSAGE_TYPE(1),
CONFIGURATION_MESSAGE_TYPE(5);
private final int id;
MessageType(int id) {
this.id = id;
}
public static MessageType fromId(int id) {
// iteration used for lookup,
// alternatively a static lookup Map can be used
for (var mt : MessageType.values()) {
if (mt.id == id) {
return mt;
}
}
throw new IllegalArgumentException("Unknown message type:" + id);
}
}
class MessageFactory {
static Message create(byte[] payload) {
var id = getId(payload);
var messageType = MessageType.fromId(id);
return switch (messageType) {
case STATUS_MESSAGE_TYPE -> new StatusMessage();
case CONFIGURATION_MESSAGE_TYPE -> new ConfigurationMessage();
};
}
}
如果您添加新的消息类型,代码将停止编译。
选项 2:枚举方法
enum MessageType {
STATUS_MESSAGE_TYPE(1, StatusMessage::new),
CONFIGURATION_MESSAGE_TYPE(5, ConfigurationMessage::new);
private final int id;
private final Supplier<Message> messageBuilder;
MessageType(int id, Supplier<Message> messageBuilder) {
this.id = id;
this.messageBuilder = messageBuilder;
}
Message create() {
return messageBuilder.get();
}
public static MessageType fromId(int id) {
// iteration used for lookup,
// alternatively a static lookup Map can be used
for (var mt : MessageType.values()) {
if (mt.id == id) {
return mt;
}
}
throw new IllegalArgumentException("Unknown message type:" + id);
}
}
class MessageFactory {
static Message create(byte[] payload) {
var id = getId(payload);
var messageType = MessageType.fromId(id);
return messageType.create();
}
}
我实现了如下工厂:
class MessageFactory {
private static final Map<Integer, MessageBuilder> IdToMessage = new HashMap<Integer, MessageBuilder>() {{
put(StatusMessage.ID, StatusMessage::new);
put(ConfigurationMessage.ID, ConfigurationMessage::new);
}};
public createMessage(byte[] payload){
int id = getId(payload);
return typeToMessage.get(id).create(payload);
}
}
此工厂接收消息的有效负载(字节),从其 header 中获取消息的 ID,然后使用其引用存储在 HashMap 中的相应消息的构造函数。
我想执行一个测试以确保所有消息都在 HashMap 中定义。 所有消息都在同一个 java 包中,编写一个测试以确保此 java 包中的所有 java 类都在 Hashmap 中是否有意义? 你有没有看到任何其他方法来确保一旦添加了新消息,它也会被添加到这个 hashmap 中?这是我正在开发的代码中的一个问题,因为这种模式在多个地方使用。
我建议重构您的代码,以便编译器为您完成这项工作。
选项 1:切换表达式
首先,熟悉Java12.
中介绍的switch expressionsExhaustiveness
When using switch statements, it doesn't really matter if all cases are covered.
For switch expressions though, the compiler insists that all possible cases are covered.
将其应用到您的案例中:
- 创建新的 MessageType 枚举
- 允许从 int id 创建 MessageType
- 重构 crateMessage 以利用 switch 表达式
enum MessageType {
STATUS_MESSAGE_TYPE(1),
CONFIGURATION_MESSAGE_TYPE(5);
private final int id;
MessageType(int id) {
this.id = id;
}
public static MessageType fromId(int id) {
// iteration used for lookup,
// alternatively a static lookup Map can be used
for (var mt : MessageType.values()) {
if (mt.id == id) {
return mt;
}
}
throw new IllegalArgumentException("Unknown message type:" + id);
}
}
class MessageFactory {
static Message create(byte[] payload) {
var id = getId(payload);
var messageType = MessageType.fromId(id);
return switch (messageType) {
case STATUS_MESSAGE_TYPE -> new StatusMessage();
case CONFIGURATION_MESSAGE_TYPE -> new ConfigurationMessage();
};
}
}
如果您添加新的消息类型,代码将停止编译。
选项 2:枚举方法
enum MessageType {
STATUS_MESSAGE_TYPE(1, StatusMessage::new),
CONFIGURATION_MESSAGE_TYPE(5, ConfigurationMessage::new);
private final int id;
private final Supplier<Message> messageBuilder;
MessageType(int id, Supplier<Message> messageBuilder) {
this.id = id;
this.messageBuilder = messageBuilder;
}
Message create() {
return messageBuilder.get();
}
public static MessageType fromId(int id) {
// iteration used for lookup,
// alternatively a static lookup Map can be used
for (var mt : MessageType.values()) {
if (mt.id == id) {
return mt;
}
}
throw new IllegalArgumentException("Unknown message type:" + id);
}
}
class MessageFactory {
static Message create(byte[] payload) {
var id = getId(payload);
var messageType = MessageType.fromId(id);
return messageType.create();
}
}