facade pattern java with real world example

The Facade Pattern provides a unified interface to a set of interfaces in a subsytem. Facade defines a higher-level interface that makes the subsystem easier to use.

The Facade Pattern allows us to avoid tight coupling between clients and subsystems and also it helps us adhere to a object oriented principle called Principle of Least Knowledge – talk only to your immediate friends.This principle prevents us from creating designs that have a large number of classes coupled together so that changes in one part of the system cascade to other parts. When you build a lot of dependencies between many classes, you are building a fragile system that will be costly to maintain and complex for others to understand.

Using facade pattern the clients will just interact and depend on just one class which will be our facade class instead of depending on many classes.

Lets take an example in one of our project we had written an api for handling breach journey. Once the system finds out that there is a breach in elements the system will use our breach journey api to validate and pass the breach to the required downstream interfaces.

As part of the breach processing many steps where performed like enriching the breach data,validating the breach data for duplication and then passing on the breach data to the interested components.Lets see the client code without using facade first


public class Test {

private EnrichElementData elementData;

private BreachValidator breachValidator;

private BreachObserver breachObserver;

public EnrichElementData getElementData() {
return elementData;
}

public void setElementData(EnrichElementData elementData) {
this.elementData = elementData;
}

public BreachValidator getBreachValidator() {
return breachValidator;
}

public void setBreachValidator(BreachValidator breachValidator) {
this.breachValidator = breachValidator;
}

public BreachObserver getBreachObserver() {
return breachObserver;
}

public void setBreachObserver(BreachObserver breachObserver) {
this.breachObserver = breachObserver;
}

public void breachProcessor(Breach breach) {
EnrichElementData enrichElementData = getElementData().getEnrichData(breach.getElementId());
boolean test = getBreachValidator().isDuplicate(breach.getElementId());
if (!test) {
getBreachObserver().publish(breach,enrichElementData);
}

}

}

As we can see in the above code the client code is dependent and coupled with many classes and also its lot of work for clients to do.

Lets write a facade to provide a unified interface which will make the usage of api by subsystem easier to use.


public class BreachJourneyFacade {

private EnrichElementData elementData;

private BreachValidator breachValidator;

private BreachObserver breachObserver;

public EnrichElementData getElementData() {
return elementData;
}

public void setElementData(EnrichElementData elementData) {
this.elementData = elementData;
}

public BreachValidator getBreachValidator() {
return breachValidator;
}

public void setBreachValidator(BreachValidator breachValidator) {
this.breachValidator = breachValidator;
}

public BreachObserver getBreachObserver() {
return breachObserver;
}

public void setBreachObserver(BreachObserver breachObserver) {
this.breachObserver = breachObserver;
}

public void breachJourney(Breach breach) {
EnrichElementData enrichElementData = getElementData().getEnrichData(breach.getElementId());
boolean test = getBreachValidator().isDuplicate(breach.getElementId());
if (!test) {
getBreachObserver().publish(breach,enrichElementData);
}

}

}

With the facade in place the client code is decoupled completely and it depends only on the BreachJourneyFacade and also its much easier to use


public class TestWithFacade {

private BreachJourneyFacade breachJourneyFacade;

public BreachJourneyFacade getBreachJourneyFacade() {
return breachJourneyFacade;
}

public void setBreachJourneyFacade(BreachJourneyFacade breachJourneyFacade) {
this.breachJourneyFacade = breachJourneyFacade;
}

public void breachProcessor(Breach breach) {

new TestWithFacade().getBreachJourneyFacade().breachJourney(breach);

}

}