I write the code in Java and I have a case where I need to get the status of an order depending on the product type. Each product type has the same base logic as written below.
protected String getStatus(ProductType productType, Result result) {
if (result.isSuccess()) {
return "SUCCESS";
} else if (result.getPaymentMethod().equals("TRANSFER")) {
return "WAITING_CONFIRMATION";
} else {
return "WAITING_PAYMENT";
}
}
However, each product type can have custom logic. For example:
- if product type is "A", no need to modify the logic above
- if the status returned from the method above is "SUCCESS" and the product type is "B", I need to call another service to check the status of the product issuance
- if the status returned from the method above is "SUCCESS" and the product type is "C", I need to call partner service.
My question is what is the best design pattern to implement?
The first idea is using something like template method pattern
public class BaseProductStatusService {
public String getStatus(Result result, Product product) {
String status;
if (result.isSuccess()) {
status = "SUCCESS";
} else if (result.getPaymentMethod().equals("TRANSFER")) {
status = "WAITING_CONFIRMATION";
} else {
status = "WAITING_PAYMENT";
}
return doGetStatus(status);
}
protected String doGetStatus(String status, Product product) {
return status;
}
}
// For product A, no need to have its own class since it can use the base class
public class ProductBStatusService extends BaseProductStatusService {
@Override
protected String doGetStatus(String status, Product product) {
if (status.equals("SUCCESS")) {
return this.checkProductIssuance(product);
}
return status;
}
}
public class ProductCStatusService() extends BaseProductStatusService {
@Override
protected String doGetStatus(String status, Product product) {
if (status.equals("SUCCESS")) {
return this.checkStatusToPartner(product);
}
return status;
}
}
Another alternative is using decorator pattern
public interface ProductStatusService() {
String getStatus(Result result, Product product);
}
public class DefaultProductStatusService implements ProductStatusService {
public String getStatus(Result result, Product product) {
String status;
if (result.isSuccess()) {
status = "SUCCESS";
} else if (result.getPaymentMethod().equals("TRANSFER")) {
status = "WAITING_CONFIRMATION";
} else {
status = "WAITING_PAYMENT";
}
return doGetStatus(status);
}
}
public abstract class ProductStatusServiceDecorator implements ProductStatusService {
private ProductStatusService productStatusService;
public ProductStatusServiceDecorator(ProductStatusService productStatusService) {
this.productStatusService = productStatusService;
}
public String getStatus(Result result, Product product) {
return this.productStatusService.getStatus();
}
}
// For product A, no need to have its own class since it can use the DefaultProductStatusService class
public class ProductBStatusServiceDecorator extends ProductStatusServiceDecorator {
public ProductStatusServiceDecorator(ProductStatusService productStatusService) {
super(productStatusService);
}
public String getStatus(Result result, Product product) {
String status = super.getStatus();
if (status.equals("SUCCESS")) {
return this.checkProductIssuance(product);
}
return status;
}
}
public class ProductCStatusServiceDecorator extends ProductStatusServiceDecorator {
public ProductStatusServiceDecorator(ProductStatusService productStatusService) {
super(productStatusService);
}
public String getStatus(Result result, Product product) {
String status = super.getStatus();
if (status.equals("SUCCESS")) {
return this.checkStatusToPartner(product);
}
return status;
}
}
which one is better for the above case and what is the reason? or do you have other suggestion?
Aucun commentaire:
Enregistrer un commentaire