Facade design pattern in Java

Melissa 153 Published: 08/24/2024

Facade design pattern in Java

Facade Design Pattern in Java:

The facade design pattern is a structural design pattern that provides a simplified interface to a complex system of classes or subsystems. Its purpose is to hide the complexity of the underlying system and provide a single, unified interface for clients (users) to interact with it.

In Java, we can implement the facade design pattern using an interface or abstract class as the facade. This interface will encapsulate the functionality of multiple classes or systems, providing a simplified way for users to access these functionalities without having to know about the underlying complexity.

Here is an example implementation:

// System components (complex subsystems)

public class Light {

public void on() {

System.out.println("Light turned on");

}

public void off() {

System.out.println("Light turned off");

}

}

public class Television {

public void on() {

System.out.println("Television turned on");

}

public void off() {

System.out.println("Television turned off");

}

}

// Facade interface

public interface ElectronicDeviceFacade {

void turnOn();

void turnOff();

}

// Concrete facade implementation

public class LivingRoomFacade implements ElectronicDeviceFacade {

private Light light;

private Television television;

public LivingRoomFacade(Light light, Television television) {

this.light = light;

this.television = television;

}

@Override

public void turnOn() {

light.on();

television.on();

System.out.println("Living room lights and TV turned on");

}

@Override

public void turnOff() {

light.off();

television.off();

System.out.println("Living room lights and TV turned off");

}

}

// Client code

public class Main {

public static void main(String[] args) {

Light light = new Light();

Television television = new Television();

ElectronicDeviceFacade facade = new LivingRoomFacade(light, television);

facade.turnOn(); // Output: Light turned on, Television turned on, Living room lights and TV turned on

facade.turnOff(); // Output: Light turned off, Television turned off, Living room lights and TV turned off

}

}

In this example, the LivingRoomFacade class implements the ElectronicDeviceFacade interface, which provides a simplified way for clients to control the lights and television in a living room. The client code (in the Main class) can easily turn on or off the entire system without having to know about the individual components (lights and TV) that make it up.

Benefits:

Simplified interface: Clients only need to interact with a single interface, which simplifies their experience. Hide complexity: The facade hides the underlying complexity of the system, making it easier for clients to use without having to understand how each component works individually. Decoupling: The facade provides a layer of abstraction between the client and the complex system, allowing changes or updates to be made independently.

In summary, the facade design pattern in Java helps simplify the interaction with complex systems by providing a unified interface that encapsulates the underlying complexity.

What is an example of adapter design pattern in Java?

The Adapter Design Pattern!

In Java, the Adapter Design Pattern is a behavioral design pattern that allows two incompatible objects to work together seamlessly. It's like a bridge that connects the two objects, enabling them to communicate effectively.

Let's consider an example to illustrate this concept:

Suppose we have a legacy system with a "Printable" interface:

public interface Printable {

void print(String text);

}

Now, imagine we want to integrate this system with a modern "Digital Display" that supports only PDF files. The problem is that the "Printable" interface and the "Digital Display" have different methods for displaying text.

To overcome this incompatibility, we can create an adapter class that adapts the "Printable" object to fit the needs of the "Digital Display":

public class PrintableAdapter {

private final Printable printable;

public PrintableAdapter(Printable printable) {

this.printable = printable;

}

public void display(String text) { // Adapted method name

printable.print(text);

}

}

The adapter class takes an instance of the "Printable" interface as a constructor argument and provides a new method display() that calls the original print() method. This allows us to use the "Printable" object with the "Digital Display" without modifying the original system.

Here's how we can use this adapter in our Java code:

public class Main {

public static void main(String[] args) {

Printable printable = new MyPrintableObject(); // Legacy system

DigitalDisplay digitalDisplay = new DigitalDisplay();

// Create an instance of the adapter class, passing the legacy object as a parameter

PrintableAdapter adapter = new PrintableAdapter(printable);

// Now we can use the adapted "Printable" object with the "Digital Display"

digitalDisplay.display("Hello World!"); // This call is routed to the print() method in the adapter

System.out.println(digitalDisplay.read()); // The output will be "Hello World!"

}

}

In this example, we create an instance of the PrintableAdapter class and pass the legacy object (MyPrintableObject) as a parameter. Then, we can use the adapted object with the "Digital Display" to display text.

The Adapter Design Pattern allows us to:

Decouple the original system from the new system by creating an adapter that translates between their interfaces. Preserve the legacy system's functionality and avoid modifying it. Integrate the old and new systems seamlessly, making them work together harmoniously.

In summary, the Adapter Design Pattern is a powerful tool in Java (and other languages) for adapting incompatible objects to work together effectively, preserving the integrity of each system while enabling seamless integration.