Facade design pattern in Java and Python

Structural Design Patterns provide different ways to create a class structure, for example using inheritance and composition to create a large object from small objects. Following design patterns come under this category.

Facade pattern provides a simplified interface to a complex subsystem.

The Facade pattern hides the complexities of the system and provides an interface to the client using which the client can access the system. It simplifies a client's interaction with a complex system by localizing the interactions into a single interface. A facade classes is used to provide a single interface to set of classes. As a result, the client can interact with a single object rather than being required to interact directly in complicated ways with the objects that make up the subsystem.

According to GoF Facade design pattern is:

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

Facade design pattern is one among the other design patterns that promote loose coupling. It emphasizes one more important aspect of design which is abstraction. By hiding the complexity behind it and exposing a simple interface it achieves abstraction.

Mediator design pattern may look very similar to facade design pattern in terms of abstraction. Mediator abstracts the functionality of the subsystems in this way it is similar to the facade pattern. In the implementation of mediator pattern, subsystem or peers components are aware of the mediator and that interact with it. In the case of facade pattern, subsystems are not aware of the existence of facade. Only facade talks to the subsystems.

Important Points:

  • Facade pattern is more like a helper for client applications; it doesn’t hide subsystem interfaces from the client. Whether to use Facade or not is completely dependent on client code.
  • Facade pattern can be applied at any point of development, usually when the number of interfaces grows and system gets complex.
  • Subsystem interfaces are not aware of Facade and they shouldn’t have any reference of the Facade interface.
  • Facade pattern should be applied for similar kind of interfaces; its purpose is to provide a single interface rather than multiple interfaces that does the similar kind of jobs.
  • Subsystem may be dependent with one another. In such case, facade can act as a coordinator and decouple the dependencies between the subsystems.
  • We can use factory design pattern with Facade to provide better interface to client systems.

The following sequence diagram illustrates how the pattern is used by a client.

dp_facade_seq.png

Java

We are going to create a Shape interface and concrete classes implementing the Shape interface. A facade class ShapeMaker is defined as a next step.

ShapeMaker class uses the concrete classes to delegate user calls to these classes. FacadePatternDemo, our demo class, will use ShapeMaker class to show the results.

dp_facade.png

Create an interface.

public interface Shape {
   void draw();
}

Create concrete classes implementing the same interface.

public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Rectangle::draw()");
   }
}
public class Square implements Shape {
   @Override
   public void draw() {
      System.out.println("Square::draw()");
   }
}
public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("Circle::draw()");
   }
}

Create a facade class.

public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;

   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }

   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

Use the facade to draw various types of shapes.

public class FacadePatternDemo {
   public static void main(String[] args) {
      ShapeMaker shapeMaker = new ShapeMaker();

      shapeMaker.drawCircle();
      shapeMaker.drawRectangle();
      shapeMaker.drawSquare();      
   }
}

Python

import abc

class Shape(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def draw(self):
        pass

class Rectangle(Shape):
    def draw(self):
        print("Rectangle::draw()")


class Square(Shape):
    def draw(self):
        print("Square::draw()")


class Circle(Shape):
    def draw(self):
        print("Circle::draw()")


class ShapeMaker:
   def __init__(self):
      self.circle = Circle()
      self.rectangle = Rectangle()
      self.square = Square()

   def draw_circle(self):
      self.circle.draw()

   def draw_rectangle(self):
      self.rectangle.draw()

   def draw_square(self):
      self.square.draw()


if __name__ == '__main__':
    shape_maker = ShapeMaker()

    shape_maker.draw_circle()
    shape_maker.draw_rectangle()
    shape_maker.draw_square()
comments powered by Disqus