Sunday, 8 June 2008

Design Patterns Revisited (3)- The Façade Pattern, Hiding the complexity of the complex..

It is arguable that the Façade pattern is a design pattern or not but it is sure that it is a nice tool method for software developers. The definition of Façade pattern according to mighty GOF is 
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
Seems easy isn't it, well façade is act as a gateway for a series of complex procedures you need to do. All you have to do is delegate everything to your façade and use it as a gateway. You need to call a specific method in the complex system, well they are still available, just call them whenever you need. 

One of the most challenging thing people face when they move to away from their families is to do the washing up. Even you own a washing machine, there are many options, procedures and steps you need to complete. So what if we just design a new washing machine with preset programs like for "very dirty clothes; use double amount detergent, get water twice, wash for longer time then dry..etc" or for "very light dirt; use half amount detergent, get water once, wash for shorter, no need to dry..." or just a normal program like "get the detergent, get the water, wash, dry..". None of the steps above makes sense for me and i really don't care what does the machine is doing as long as the output is clean clothes.  So lets just code a class which will be the façade of our washing machine and will only use the methods which were already provided with the washing machine.

    public class Clothes{
         private int amount;
         private String owner;
         private String status;
         ...
    }
    public class WashingPresets {
        private WashingMachine washingMachine=new WashingMachine;
        public Clothes lightWash(Clothes clothes) {
             washingMachine.getWater(50);
             washingMachine.getDetergent(20);
             washingMachine.wash(clothes);
             return clothes;
        }
        public Clothes heavyWash (Clothes clothes){
             washingMachine.getWater(100);
             washingMachine.getDetergent(35);
             washingMachine.wash(clothes);
             washingMachine.getWater(100);
             washingMachine.getDetergent(40);
             washingMachine.wash(clothes);
             washingMachine.dry(clothes);
             return clothes;             
        }
        public Clothes normalWash(Clothes clothes) {
             washingMachine.getWater(100);
             washingMachine.getDetergent(40);
             washingMachine.wash(clothes);
             washingMachine.dry(clothes);
             return clothes;
        }
    }
 
    public class Client{
         // anyone who wants to use our washing machine can just use such a simple code piece
         public void washMyClothes(){
               Clothes clothes=new Clothes();
               WashingPresets ws=new WashingPresets();
               ws.heavyWash(clothes);
         }
    }

We have just used the special methods provided by our tech-end washing machine and hide the complexity in our façade class. So from now on our house mates just need to select the program which suites their laundry. So nice, so easy and so fast but what if one of our house mate is very ungenerous on spending money and doesn't want to use our heavy washing program because it uses to much detergent. Actually all he wants is to rinse the clothes ones more without detergent and with less water and since he is the only want making the trouble we don't want to add this style as a method in our class. So we let him use our façade along with the methods provided by the producer;

    public class TroublesomeClient{
         public void washMyClothes(){
               Clothes clothes=new Clothes();
               WashingPresets ws=new WashingPresets();
               WashingMachine washingMachine=new WashingMachine;
               ws.lightWash(clothes); //façade call
               washingMachine.getWater(50); //native methods call
               washingMachine.wash(clothes); //native methods call
         }
    }

Well we didn't do too much but with this design we can hide the complexity and all clients including the ungenerous one is quite happy since everyone has much less thing to do and it is hard to miss a step and ruin the laundry. 
As mentioned in Head First Design Patterns just try to obey the principle of least knowledge;
Talk only to your immediate friends!
Always hide the complexity from the code which doesn't need to know the details.