Search code examples
javaoopservicerefactoringfacade

JAVA Facade pattern, correct implementation?


I have a client like with a constructor which is quite lengthy in terms of the argument list , e.g,

Class Client {
   private ServiceA _serviceA;
   private ServiceB _serviceB;
   ....
   private ServiceE _serviceE;

   public Client(ServiceA serviceA, ServiceB serviceB,...ServiceE service E) { ... }

   public doTask1(TypeA typeA) { //only serviceA, serviceB service being used... }

   public doTask2(TypeB typeB) { //only serviceD, serviceE being used ... }
}

I want to use a service facade here to prune the constructor argument list. However, I am pretty confused as the core responsibility of the facade implementation. So I have written down a facade with the services as the class variables and their getters , as below:

Class Facade {
   private ServiceA _serviceA;
   private ServiceB _serviceB;
   ....
   private ServiceE _serviceE;

   getters () ...
}

Is this correct way to abstract facade in this case. If not , what would have been the proper way to refactor the Client class?


Solution

  • Facedes has a completely different intent: they are created to encapsulate and hide the underlying structure and behaviour of classes. Take an example of a car. It's made of many components: on-board computer, fuel pump, engine etc. If you want to start it, just press the start button:

    class FuelPump {
      private boolean pumpTurnedOn;
      public FuelPump() {
        pumpTunrnedOn=false;
      }
      public boolean isPumpTunredOn() {
        return pumpTurnedOn;
      }
      public void setPumpTurnedOn (boolean newState) {
        pumpTurndeOn=newState;
        if (newState) {
          System.out.println ("fuel pump now is on");
        } else {
          System.out.println ("fuel pump now is turned off");
        }
      }
    }
    

    class Engine {
      private boolean engineStarted;
      public Engine() {
        engineStarted=false;
      }
      public boolean isEngineStarted() {
        return engineStarted;
      }
      public void setEngineStarted (boolean newState) {
        engineStarted=newState;
        if (newState) {
          System.out.println("engine now is on");
        } else {
          System.out.println("engine now is turned off");
        }
      }
    }
    

    // this is the Car facade:
    class Car {
      private FuelPump fuelPump;
      private Engine engine;
      // + other components of Car
      public Car () {
        fuelPump = new FuelPump();
        engine = new Engine();
      }
      public void startCar() {
        fuelPump.setPumpTurnedOn(true);
        engine.setEngineStarted(true);
        // + other methods of start procedures with other components
        System.out.println("Your car has been startded");
      }
      public void stopCar() {
        engine.setEngineStarted(false);
        fuelPump.setPumpTurnedOn(false);
        // + other methods on other components for shutting down car
      }
    }
    

    The client code snippet:

    Car car=new Car();
    car.startCar();
    // later on
    car.stopCar();
    

    As you may see the client doesn't know anything about the underlying components to start the car. It has only to use the startCar() method, and the Car facade will do the rest. Facade is a structural pattern. If you have many constructor arguments and want to reduece them use one of the creational patterns. In case you have compulsory and non compulsory fields I suggest using the builder pattern. For example your compulsory constructor arguments are Service_A and Service_B and Service_C to Service_E are not required. Then your ClientBuilder class should like be this:

    class ClientBuilder{
      private static Service_A serviceA;  // required
      private static Service_B serviceB;  // required
      private static Service_C serviceC;
      private static Service_D serviceD;
      private static Service_E serviceE;
    
      // since this builder is singleton
      private static ClientBuilder builderInstance = new ClientBuilder();
      private ClientBuilder () {};
    
      public static ClientBuilder getBuilderInstance (Service_A service_A, Service_B service_B){
        serviceA = service_A;
        serviceB = service_B;
        serviceC = null; 
        serviceD = null;
        serviceE = null;
        return builderInstance;
      }
    
      public static ClientBuilder addServiceC (Service_C service_C) {
        serviceC = service_C;
        return builderInstance; 
      }
    
      public static ClientBuilder addServiceD (Service_D service_D) {
        serviceC = service_D;
        return builderInstance; 
      }
    
      public static ClientBuilder addServiceE (Service_E service_E) {
        serviceE = service_E;
        return builderInstance; 
      }
    
      public static Client build(){
        return new Client (serviceA, ServiceB, ServiceC, ServiceD, ServiceE);
      }
    

    In this case you can instantinate your Client class only with the mandatory arguments. The best thing is the not required arguments' order are interchangeable:

      Client aClient = ClientBuilder.getBuilderInstance(aServiceA, aServiceB)
            .addServiceE(aServiceE)
            .addServiceC(aServiceC)
            .build();
    

    Now aClient has been created with services A,B,C,E and serviceD remains null. Later you can set it by appropriate setter. The getters and setters must be in your Client class. To put it in a nutshell, with builder class you can reduce the number of constructor arguments only for the mandatory and set up optional fields later with setters. You can read more details in the Gang of Four book or if you are a serious Java fun I suggest Head First's Design Patterns book. Hope I could help you, bye!