Labels

Thursday, November 18, 2010

Facade Design Pattern - Structural

1.1          Definition

The facade pattern is an object-oriented design pattern.  A facade is an object that provides a simplified interface to a larger body of code, such as a class library. Facade Design pattern provides an easy to use interface and makes things easier by hiding the details of the implementation.

When designing good programs, programmers usually attempt to avoid excess coupling between module/classes.  Using this pattern helps to simplify much of the interfacing that makes large amounts of coupling complex to use and difficult to understand.

In a nutshell, this is accomplished by creating a small collection of classes that have a single class (Facade) that is used to access them.


A facade can accomplish all of the following.

  • It can make a software library easier to use and understand since the facade has convenient methods for common tasks.
  • It makes code that uses the library more readable for the same reason.
  • It can reduce dependencies of outside code on the inner workings of a library since most code uses the facade.  This allows for more flexibility in developing the system.
  • It can wrap a poorly designed collection of APIs with a single well-designed API.               

1.2          Intent

·         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. [GoF, p185]
·         Wrap a complicated subsystem with a simpler interface.
·         To decouple the classes of the subsystem from its clients and other subsystems, thereby promoting subsystem independence and portability

1.3          Motivation


To to reduce this complexity best is to introduce a facade object that provides a single, simplified interface to the more general facilities of a subsystem


1.1           Advantages/Disadvantages

Advantage –

  • It hides the implementation of the subsystem from clients, making the  subsystem easier to use
  • It promotes weak coupling between the subsystem and its clients. This allows you to change the classes the comprise the subsystem without affecting the clients.
  • It reduces compilation dependencies in large software systems
  • It simplifies porting systems to other platforms, because it's less likely that building one subsystem requires building all others

Disadvantage –

  • It does not prevent sophisticated clients from accessing the underlying classes
  • Note that Facade does not add any functionality, it just simplifies interfaces

1.2          Structure








1.3          Participants

The classes and/or objects participating in this pattern are:

Facade   
·         Knows which subsystem classes are responsible for a request.
·         Delegates client requests to appropriate subsystem objects.

Subsystem classes
·         Implement subsystem functionality.
·         Handle work assigned by the Facade object.
·         Have no knowledge of the facade and keep no reference to it.


1.4          Non-Software Example



In most of the Pizza centers, orders will be given through phone calls with the customer interacting with the Customer service representative.  In this case, consumers do not have access to the Billing system, Kitchen and delivery department.  The customer service representative acts as an interface and interacts with each of the departments involved in the transaction and ensures that Pizzas are delivered to the consumer.

1.5          Sample Code

This code demonstrates the Facade pattern which provides a simplified and uniform interface to a large subsystem of classes.


class Facade
  {
    SubSystemOne one;
    SubSystemTwo two;
    SubSystemThree three;
    SubSystemFour four;

    public Facade()
    {
      one = new SubSystemOne();
      two = new SubSystemTwo();
      three = new SubSystemThree();
      four = new SubSystemFour();
    }

    public void MethodA()
    {
      Console.WriteLine("\nMethodA() ---- ");
      one.MethodOne();
      two.MethodTwo();
      four.MethodFour();
    }

    public void MethodB()
    {
      Console.WriteLine("\nMethodB() ---- ");
      two.MethodTwo();
      three.MethodThree();
    }
  }

class SubSystemOne
  {
    public void MethodOne()
    {
      Console.WriteLine(" SubSystemOne ");
    }
  }
class SubSystemTwo
  {
    public void MethodTwo()
    {
      Console.WriteLine(" SubSystemTwo ");
    }
  }
class SubSystemThree
  {
    public void MethodThree()
    {
      Console.WriteLine(" SubSystemThree ");
    }
  }
class SubSystemFour
  {
    public void MethodFour()
    {
      Console.WriteLine(" SubSystemFour ");
    }
  }


class MainApp
  {
    public static void Main()
    {
      Facade facade = new Facade();

      facade.MethodA();
      facade.MethodB();

      // Wait for user
      Console.Read();
    }
  }


Output

MethodA() ----
SubSystemOne Method
SubSystemTwo Method
SubSystemFour Method

MethodB() ----
SubSystemTwo Method
SubSystemThree Method



1.6          Sample Code2

This real-world code demonstrates the Facade pattern as a MortgageApplication object which provides a simplified interface to a large subsystem of classes measuring the creditworthyness of an applicant.


// Façade class

class Mortgage
    private Bank bank = new Bank();
    private Loan loan = new Loan();
    private Credit credit = new Credit();

    public bool
IsEligible(Customer cust, int amount)
    {

      Console.WriteLine("{0} applies for {1:C} loan\n", cust.Name, amount);

      bool eligible = true;

       if (!bank.
HasSufficientSavings(cust, amount))
      {
        eligible = false;
      }
      else if (!loan.
HasNoBadLoans(cust))
      {
        eligible = false;
      }
      else if (!credit.
HasGoodCredit(cust))
      {
        eligible = false;
      }

      return eligible;

    }
  }
}

class Bank
  {
    public bool HasSufficientSavings(Customer c, int amount)
    {
      Console.WriteLine("Check bank for " + c.Name);
      return true;
    }
  }
 class Credit
  {
    public bool HasGoodCredit(Customer c)
    {
      Console.WriteLine("Check credit for " + c.Name);
      return true;
    }
  }
class Loan
  {
    public bool HasNoBadLoans(Customer c)
    {
      Console.WriteLine("Check loans for " + c.Name);
      return true;
    }
  }


class Customer
  {
    private string name;

    // Constructor
    public Customer(string name)
    {
      this.name = name;
    }

    // Property
    public string Name
    {
      get{ return name; }
    }
  }

class MainApp
  {
    static void Main()
    {
       Customer customer = new Customer("Ann McKinsey");
       Mortgage mortgage = new Mortgage();


      bool eligable = mortgage.IsEligible(customer,125000);
     
      Console.WriteLine("\n" + customer.Name +  " has been " + (eligable ? "Approved" : "Rejected"));
      Console.Read();
    }
  }

Output -

Ann McKinsey applies for $125,000.00 loan

Check bank for Ann McKinsey
Check loans for Ann McKinsey
Check credit for Ann McKinsey
Ann McKinsey has been Approved

Hope this helps.

Thanks & Regards,
Arun Manglick

No comments:

Post a Comment