Reputation: 5142
I have different kind of Customer POJO. And I have a function which takes customer details in a string format and take the type of the customer as well. Now, with this function I wanted to add the some information to it and then return the JSON string. I can do it by checking for type and deserializing to appropriate objects and handle it. But I wanted to figure out some way of refactoring which can do this without knowing the type of customers.
Following are my classes:
@Value.Immutable
public interface Customer1 {
String firstName();
String phoneNumber();
@Value.Immutable
interface Address1 {
String addressLine();
}
}
========
@Value.Immutable
public interface Customer2 {
String firstName();
String lastName();
@Value.Immutable
interface Address2 {
String addressLine();
String addressLine2();
}
}
========
public enum CustomerType {
CUSTOMER1(Customer1.class, Customer1.Address1.class),
CUSTOMER2(Customer2.class, Customer2.Address2.class);
private final Class<?> type;
private final Optional<Class<?>> addressType;
CustomerType(final Class<?> type) {
this.type = type;
this.addressType = Optional.empty();
}
CustomerType(final Class<?> type, final Class<?> addressType) {
this.type = type;
this.addressType = Optional.of(addressType);
}
public Class<?> getType() {
return type;
}
public Optional<Class<?>> getAddressType() {
return addressType;
}
}
========
private static final Gson GSON;
public String check(String customerType, String customerDetails, String addressDetails) {
// Write this function such that it doesn't have to do check on what is customer Type.
if (CustomerType.CUSTOMER1.name().equals(type)) {
Customer1.Address1 address1 = GSON.fromJson(addressDetails, Customer1.Address1.class);
Customer1 updatedCustomerDetails = ImmutableCustomer1.copyOf(GSON.fromJson(customerDetails, Customer1.class))
.withAddress1(address1);
return GSON.toJson(updatedCustomerDetails);
} else if (CustomerType.CUSTOMER2.name().equals(type)) {
/// Similar like above
} else {
return null;
}
Is there any way I can generalize my check function using the CustomerType library? I am ready to refactor my code to any level. Probably my current model of Customer is wrong which makes me not do that easily.
Upvotes: 0
Views: 91
Reputation: 5034
Firstly, determine what type of customer (ie, which value of CustomerType) you are dealing with. With that in hand, you can use a switch
statement to determine processing (and ideally you can move each type's processing out to a separate method). Importantly, using such a switch statement can then trigger a build-time-error if any CustomerTypes are missing - better to catch that problem at build time than finding out some time later from an obscure runtime bug report !
public String check(String customerType, String customerDetails, String addressDetails)
{
try {
CustomerType customerType = CustomerType.valueOf(type);
} catch (IllegalArgumentException e) {
return null;
}
// Java12 - Use Switch Expressions
String result =
switch (customerType) {
case CUSTOMER1 -> formatCustomer1(customerDetails, addressDetails);
case CUSTOMER2 -> formatCustomer2(customerDetails, addressDetails);
// etc
}
// Up to Java 11 - Use normal Switch statement
String result = null;
switch (customerType) {
case CUSTOMER1: result = formatCustomer1(customerDetails, addressDetails);
break;
case CUSTOMER2: result = formatCustomer2(customerDetails, addressDetails);
break;
// etc
}
Java12's Switch Expressions have a few advantages :
1) Much cleaner syntax (not least, no "break" statements !)
2) Compile time error if not all enums are handled.
However, even the pre-Java12 switch has :
1) Your IDE will probably warn you if any enum values are missing
2) You can use automated tools that will fire a build-time-failure if enum values are missing
You could also take this a step further, and add methods to the CustomerType enum itself to call those "format" methods (although personally I think that could be taking things a step too far).
Upvotes: 1