Thursday, November 12, 2015

The Facade design pattern

From time to time I like to review code I developed in the past. It's nice to see how you would improve things at the level you are now and remember things that challenged you in a specific project. I was reviewing recently some classes I developed in a project that involved a lot of legacy code written by various developers and was a bit complex and messy. I used a facade to provide access to certain functionalities via a clear (and simple) API and had hidden behind it some classes I developed that were not so "pleasing to read" and worked with and capitalized the legacy code. The methods of the facade would be used by other components of the system written by another developer and I wanted to make his life easier. After the nostalgia, I though to write a tutorial on the Facade design pattern.

The facade design pattern is of the structural family and is used to provide a simple interface to clients, hiding the complexities of the operations it provides behind it. It also can be used to limit the dependencies with outside code on the internal of its application and to provide a well designed API over a poorly designed one.

To provide an example of its use, we will use a hotel reception. When a customer asks for a room it only interacts with the receptionist but a lot of activities are taking place, such as finding the available rooms, sending a cleaning crew (for our example) and retrieving funds from the customer. All these are transparent to the customer who only asks for a room and pays the receptionist in a single interaction. The UML class diagram of the demo we will develop in the tutorial is depicted in the figure below:


Let's start with the classes and functionalities that we want to make transparent and simplify the interaction with the customer. First let's create the FundsChecker class which examines if the client has enough money to book a room:
package com.tasosmartidis.design_patterns_tutorial.facade;

public class FundsChecker {

    public boolean checkIfEnoughMoney(double moneyFromClient) {
        if(moneyFromClient>30)
            return true;
        
        return false; 
    }
}

Our hotel is offering crazy deals, just 30 of some currency and we facilitate them! Next, lets write a class that finds the availability of the hotel rooms:
package com.tasosmartidis.design_patterns_tutorial.facade;

import java.util.Random;

public class RoomAvailabilityFinder {

private Random randomGenerator;
    
    public RoomAvailabilityFinder() {
        randomGenerator = new Random();
    }
    
    public int findAvailableRoom() {
        int emptyRoom = randomGenerator.nextInt(200);
        if(emptyRoom%2==0)
            System.out.println("Room " + emptyRoom + " is available");
        else {
            System.out.println("we are sorry, there are no available rooms!");
            emptyRoom = -1;
        }
        
        return emptyRoom;
    }
}

Apparently only even numbered rooms can be available in our hotel, but even numbered or not, the rooms must absolutely be clean! The CleaningCrew takes care of that:
package com.tasosmartidis.design_patterns_tutorial.facade;

public class CleaningCrew {

    public void cleanRoom(int roomNumber) {
        try {
            Thread.sleep(2000); // Good cleaning takes time!
            System.out.println("Room " + roomNumber +" is clean and ready!");
        } catch (InterruptedException e) { 
            e.printStackTrace();
        }
    }
}

Alright, all the necessary functionalities are in place. Now we want to simplify the interaction of the client with the reception. The client just wants a room and does not care who and how will arrange that for him. The ReceptionFacade class provides that simple interface, with a single method as shown below:
package com.tasosmartidis.design_patterns_tutorial.facade;


public class ReceptionFacade {

    private RoomAvailabilityFinder roomFinder;
    private CleaningCrew cleaningCrew;
    private FundsChecker fundsChecker; 
    
    public ReceptionFacade() {      
        
        roomFinder = new RoomAvailabilityFinder();
        cleaningCrew = new CleaningCrew();
        fundsChecker = new FundsChecker();
    }
    
    public void requestARoomOfMaximum(double clientMoney) {
        if(fundsChecker.checkIfEnoughMoney(clientMoney)) {
            int roomAvailable = roomFinder.findAvailableRoom();
            if(roomAvailable!=-1)
                cleaningCrew.cleanRoom(roomAvailable);
        }else {
            System.out.println("I am sorry there is not an available room for your funds!");
        }
    }
}

Our hotel is ready and will now receive its first potential clients! The demo class below presents how a client interacts with the hotel reception facade:
package com.tasosmartidis.design_patterns_tutorial.facade;


public class HotelDemo {

    public static void main(String[] args) {
        ReceptionFacade receptionist = new ReceptionFacade();
        
        System.out.println("First customer:");
        receptionist.requestARoomOfMaximum(15.00);
        System.out.println();
        System.out.println("Second customer:"); 
        receptionist.requestARoomOfMaximum(50.00);

    }

}


Running this demo application returns the following results:













This concludes the facade design pattern tutorial and the code is as usual available on GitHub. Cheers!

No comments:

Post a Comment