Wednesday, February 9, 2011

Structural Patterns - Facade Pattern

Definition

Make a complex system simpler by providing a unified or general interface, which is a higher layer to these subsystems. 



Where to use & benefits


 

 

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.
  • Wrap a complicated subsystem with a simpler interface.

Problem

A segment of the client community needs a simplified interface to the overall functionality of a complex subsystem.





Facade as the name suggests means the face of the building. The people walking past the road can only see this glass face of the building. They do not know anything about it, the wiring, the pipes and other complexities. The face hides all the complexities of the building and displays a friendly face.
This is how facade pattern is used. It hides the complexities of the system and provides an interface to the client from where the client can access the system. In Java, the interface JDBC can be called a facade. We as users or clients create connection using the “java.sql.Connection” interface, the implementation of which we are not concerned about. The implementation is left to the vendor of driver.
Let’s try and understand the facade pattern better using a simple example. Let’s consider a store. This store has a store keeper. In the storage, there are a lot of things stored e.g. packing material, raw material and finished goods.

You, as client want access to different goods. You do not know where the different materials are stored. You just have access to store keeper who knows his store well. Whatever you want, you tell the store keeper and he takes it out of store and hands it over to you on showing him the credentials. Here, the store keeper acts as the facade, as he hides the complexities of the system Store.

Let us see how the Store example works.

Store.java

package structural.facade; public interface Store {
  public Goods getGoods();
}// End of interface
The store can very well be an interface. This only returns Goods. The goods are of three types as discussed earlier in this document. RawMaterialGoods, FinishedGoods and PackagingMaterialsGoods. All these classes can implement the Goods interface.
Similarly, the stores are of three types and can implement the Store interface. Let’s have a look at the code for one of the stores.

FinishedGoodsStore.java

package structural.facade; public class FinishedGoodsStore implements Store {

  public Goods getGoods() {
FinishedGoods finishedGoods = new FinishedGoods();
return finishedGoods;
}
}// End of class
Now let’s consider the facade StoreKeeper.
StoreKeeper.java
package structural.facade; public class StoreKeeper {
  /**
* The raw materials are asked for and
* are returned
*
* @return raw materials
*/
public RawMaterialGoods getRawMaterialGoods() {
RawMaterialStore store = new RawMaterialStore();
RawMaterialGoods rawMaterialGoods = (RawMaterialGoods)store.getGoods();
return rawMaterialGoods;
}

/**
* The packaging materials are asked for and
* are returned
*
* @return packaging materials
*/
public PackingMaterialGoods getPackingMaterialGoods() {
PackingMaterialStore store = new PackingMaterialStore();
PackingMaterialGoods packingMaterialGoods = (PackingMaterialGoods)store.getGoods();
return packingMaterialGoods;
}


/**
* The finished goods are asked for and
* are returned
*
* @return finished goods
*/
public FinishedGoods getFinishedGoods() {
FinishedGoodsStore store = new FinishedGoodsStore();
FinishedGoods finishedGoods = (FinishedGoods)store.getGoods();
return finishedGoods;
}
}// End of class
This is clear that the complex implementation will be done by StoreKeeper himself. The client will just access the StoreKeeper and ask for either finished goods, packaging material or raw material.
How will the client program access this façade? Here is a simple code.

Client.java

package structural.facade; public class Client {
  /**
* to get raw materials
*/
public static void main(String[] args) {
StoreKeeper keeper = new StoreKeeper();
RawMaterialGoods rawMaterialGoods = keeper.getRawMaterialGoods();
}
}// End of class
In this way the implementation is left to the façade. The client is given just one interface and can access only that. This hides all the complexities.
There is another way of implementing this. We can have just one method in our StoreKeeper class getGoods(String goodsType).
Another version of StoreKeeper method is here.

StoreKeeper.java

package structural.facade; public class StoreKeeper {
  /**
* The common method
*
* @return Goods
*/
public Goods getGoods(String goodsType) {
if (goodsType.equals("Packaging")) {
PackingMaterialStore store = new PackingMaterialStore();
PackingMaterialGoods packingMaterialGoods = (PackingMaterialGoods)store.getGoods();
return packingMaterialGoods;
}
else if (goodsType.equals("Finished")) {
FinishedGoodsStore store = new FinishedGoodsStore();
FinishedGoods finishedGoods = (FinishedGoods)store.getGoods();
return finishedGoods;
}
else {
RawMaterialStore store = new RawMaterialStore();
RawMaterialGoods rawMaterialGoods = (RawMaterialGoods)store.getGoods();
return rawMaterialGoods;
}
}// End of class
The client program can now create an object of StoreKeeper class and call method getGoods() passing as parameter the type of goods required. This can be done as follows.
new StoreKeeper().getGoods(“RawMaterials”);
In this case, the type-casting ill be needed on client side to narrow down Goods to RawMaterialsGoods.
All in all, the Façade pattern hides the complexities of system from the client and provides a simpler interface. Looking from other side, the facade also provides the implementation to be changed without affecting the client code.


Example 2: 

Example

JDBC design is a good example of Façade pattern. A database design is complicated. JDBC is used to connect the database and manipulate data without exposing details to the clients.
Security of a system may be designed with Façade pattern. Clients' authorization to access information may be classified. General users may be allowed to access general information; special guests may be allowed to access more information; administrators and executives may be allowed to access the most important information. These subsystems may be generalized by one interface. The identified users may be directed to the related subsystems.
interface General {
    public void accessGeneral();
}
interface Special extends General {
    public void accessSpecial();
}
interface Private extends General {
    public void accessPrivate();
}

class GeneralInfo implements General {
    public void accessGeneral() {
 //...
    }
    //...
}
class SpecialInfo implements Special{
    public void accessSpecial() {
        //...
    }
    public void accessGeneral() {}
    //...
}
class PrivateInfo implements Private, Special {
    public void accessPrivate() {
 // ...
    }
    public void accessSpecial() {
 //...
    }
    public void accessGeneral() {
 // ...
    }
    //...
}

class Connection {
   //...
    
   if (user is unauthorized) throw new Exception();
   if (user is general) return new GeneralInfo();
   if (user is special) return new SpecialInfo();
   if (user is executive) return new PrivateInfo();
   //...
}
The above code example illustrates that the whole system is not exposed to the clients. It depends on the user classification.
Mr. SudHakar Chavali proposes a better design, similar to the above, but avoids repeated code. Look at code below.
interface General {
    public void accessGeneral();
}

interface Special extends General {

    public void accessSpecial();

}

interface Private extends General {

    public void accessPrivate();

}

class GeneralInfo implements General {

    public void accessGeneral() {

 //...
    }

    //...
}

class SpecialInfo extends GeneralInfo implements Special{

    public void accessSpecial() {

        //...
    }

}

class PrivateInfo extends SpecialInfo implements Private {

    public void accessPrivate() {

 // ...

    }
   
    //...
}
To avoid repeated code, SpecialInfo become subclass of GeneralInfo and PrivateInfo becomes subclass of SpecialInfo. When a person is exposed to special information, that person is allowed to access general information also. When a person is exposed to private information, that person is allowed to access general information and special information also.



Example 3:


Facade in Java

Why read if you can watch?

Watch design patterns video tutorial
Read full article

Facade design pattern

  1. Identify the desired unified interface for a set of subsystems
  2. Design a “wrapper” class that can encapsulate the use of the subsystems
  3. The client uses (is coupled to) the Facade
  4. The facade/wrapper “maps” to the APIs of the subsystems
// 1. Subsystem
class PointCarte {
  private double x, y;
  public PointCarte( double xx, double yy ) {
    x = xx;
    y = yy;
  }
  public void  move( int dx, int dy ) {
    x += dx;
    y += dy;
  }
  public String toString() {
    return "(" + x + "," + y + ")";
  }
  public double getX() {
    return x;
  }
  public double getY() {
    return y;
  } 
}

// 1. Subsystem
class PointPolar {
  private double radius, angle;
  public PointPolar( double r, double a ) {
    radius = r;
    angle = a;
  }
  public void  rotate( int ang ) {
    angle += ang % 360;
  }
  public String toString() {
    return "[" + radius + "@" + angle + "]";
  }
}

// 1. Desired interface: move(), rotate()
class Point {
  private PointCarte pc; // 2. Design a "wrapper" class
  
  public Point( double xx, double yy ) {
    pc = new PointCarte( xx,yy );
  }
  public String toString() {
    return pc.toString();
  }
  // 4. Wrapper maps
  public void move( int dx, int dy ) {
    pc.move( dx,dy );
  }
  public void rotate( int angle, Point o ) {
    double x = pc.getX() - o.pc.getX();
    double y = pc.getY() - o.pc.getY();
    PointPolar pp = new PointPolar( Math.sqrt(x*x+y*y),
                          Math.atan2(y,x)*180/Math.PI );
    // 4. Wrapper maps
    pp.rotate( angle );
    System.out.println( "  PointPolar is " + pp );
    String str = pp.toString();  int i = str.indexOf( '@' );
    double r = Double.parseDouble( str.substring(1,i) );
    double a = Double.parseDouble( str.substring(i+1,str.length()-1) );
    pc = new PointCarte(r*Math.cos(a*Math.PI/180) + o.pc.getX(),
                  r*Math.sin(a*Math.PI/180) + o.pc.getY() );
  }
}

class Line {
  private Point o, e;
  public Line( Point ori, Point end ) {
    o = ori;
    e = end;
  }
  public void  move( int dx, int dy ) {
    o.move( dx, dy );
    e.move( dx, dy );
  }
  public void  rotate( int angle ) {
    e.rotate( angle, o );
  }
  public String toString() {
    return "origin is " + o + ", end is " + e;
  }
}

class FacadeDemo {
  public static void main( String[] args ) {
    // 3. Client uses the Facade
    Line line1 = new Line( new Point(2,4), new Point(5,7) );
    line1.move(-2,-4);
    System.out.println( "after move:  " + line1 );
    line1.rotate(45);
    System.out.println( "after rotate: " + line1 );
    Line line2 = new Line( new Point(2,1), new Point(2.866,1.5) );
    line2.rotate(30);
    System.out.println( "30 degrees to 60 degrees: " + line2 );
  }
}
after move: origin is (0.0,0.0), end is (3.0,3.0) PointPolar is [4.242@90.0] after rotate: origin is (0.0,0.0), end is (0.000,4.242) PointPolar is [0.999@60.0] 30 degrees to 60 degrees: origin is (2.0,1.0), end is (2.499,1.866)

No comments:

Post a Comment