mercredi 25 février 2015

Facade or Decorator

Context :


I have a REST Service let's say CustomerService which for now has one method getCustomer(id, country). Now requirement is that depending upon country I have to perform different business logic like access different database or some custom rules and then report that I received such a request.


Firstly to solve different implementations depending upon country I used Factory pattern as shown below :


Common interface for all country based implementations



public Interface CustomerServiceHandler{
Cusomer getCustomer(String id, String country);
}


Then factory as



public class CustomerServiceHandlerFactory{
public CustomerServiceHandler getHandler(String country){...};
}


Implementation Detail using Facade


Note this facade is called from REST class i.e.CustomerService



public CustomerServiceFacade{
public Customer getCustomer(String id, String country){
//use factory to get handler and then handler.getCustomer
Customer customer = factory.getHandler(country).getCustomer(id,country);
//report the request
reportingService.report('fetch-customer',....);
return customer;
}
}


Going by the SRP(Single Responsibility Principle), this facade is not achieving a single objective. It is fetcing customer as well as reporting that such request was received. So I thought of decorator pattern as follow.


Implementation using Decorator Pattern:



//this is called from Rest layer
public ReportingCustomerHandler implements CustomerServiceHandler{
//this delegate is basically the default implementation and has factory too
private CustomerServiceHandler delegate;
private ReportingService reporting;
public Customer getCustomer(String id, String country){
Customer customer = delegate.getCustomer(id, country);
reporting.report(....);
return customer;
}
}


//this is called from ReportingCustomerHandler
public DefaultCustomerServiceHandler implements CustomerServiceHandler{
private CustomerServiceHandlerFactory factory;

public Customer getCustomer(String id, String country){
//get factory object else use itself, even default implementation is provided by factory
CustomerServiceHandler handler = factory.getHandler(country);
return handler.getCustomer(id,country);

}
}


Note: In second approach I am reusing the interface CustomerServiceHandler(shown in factory code) for Reporting and Default implementations also.


So what is the correct way, or what is the alternative to this if something more suitable is present.


Second part of the question


What if I have to maintain two different interfaces i.e. one CustomerServiceHandler to implement different countries' implementation and one to serve REST Layer. Then what can be the design or alternative. In this case i think facade would fit.


Aucun commentaire:

Enregistrer un commentaire