Thursday 27 October 2011

Creational Pattern - A Close Look

 Ever Wondered in  a new project while creating a new module or a page that would have given a compilation error or a screen pops up without any default data being loaded in the master controls.

 We know consciously or unconsciously that we did not implement an interface or did not implement a  default method or set a value in default property.


   We have been there many times. I would say most of this issue happens either the COMPILATION ERROR or a BLANK SCREEN WITHOUT DATA are due to following reasons.


  • We did not understand what they have implemented in different layers.
  • Current project is not designed using any design pattern, that force the user to implement certain methods by default, eg. say Interface
  • Multiple patterns are used which solves different problem and we cannot figure out what is the actual purpose of the pattern which is used to solve the respective problems.
 Here we will see real time example where different pattern are used to get solution for different type of problems.


 Let us consider my previous project about travel agent for booking airline tickets. This is the biggest project i have worked till  now. We will only talk about scope which will be useful for us in explaining our Creational Pattern.

Problem Statement:


      Travel agent named OBTS(Osaka Business Travel System) manages travel needs of customers. Their main business is to take care of business travels. They reserve/book tickets for airlines/Hotel/Car that is needed for business travel. They also take care of Round trip of WORLD(RTW).


 For example: Business user and his wife flies from Japan to California takes a Rental car drives to Santa Clara, catches a flight and travels to Singapore drops his wife there and travels back to Japan. In Singapore he stays for two days.


OBTS Travel Agent will gather details about the person who travel and reserves Air/Hotel/Car. The details about the traveller and travel should be saved in our local database before booking the travel itinerary. The agent who booked the itinerary should also be saved in the itinerary.


Note: For reserving tickets in various geographical regions we need to access different servers.


Amadeus - North/South America
Abacus - Asia Pacific 
AXES - Japan/Korea
Galileo - Europe


These are commonly used servers. Each servers have different MODES OF COMMUNICATION


Amadeus - XML
Abacus - Webservice
AXES - MQ Series
Galileo - HTTP


We will discuss two CREATIONAL PATTERN which was used to solve the problem.


  1. Abstract Factory Pattern
  2. Singleton Pattern 
Abstract Factory Pattern: 


     Abstract Factory Pattern means providing an interface for creating families of related or dependent objects without specifying their concrete classes.


 In our real time example we will solve the following problem of booking tickets in different servers. Above itinerary has to be booked in different servers with different mode of inputs. Data will be same, but data format and way of communication is different for each server of same itinerary.


Japan to California - AXES
California  to Santa Clara - Amadeus
Santa Clara to Singapore - Abacus


Our first step is build a interface which has the following method that need to Book/Update/Cancel tickets. This will be the object type that will be returned when we try to Create/Modify tickets. We will name it as  IAirlineServerFactory


    public interface IAirlineServerFactory
    {
        bool BookTicket(ItineraryInfo itinerary);
        bool UpdateTicket(ItineraryInfo itinerary);
        bool CancelTicket(ItineraryInfo itinerary);

    }


IAirlineServerFactory will be the interface which gives us the objects by hiding underlying Concrete Class. Next step is to create Concrete class which will have implementation for all different servers. All the implemented class should inherit our IAirlineServerFactory.
 
    public class AbacusServer : IAirlineServerFactory
    {
        public bool BookTicket(ItineraryInfo itinerary)
        {
            //Implementation Here
            return true;
        }
        public bool UpdateTicket(ItineraryInfo itinerary)
        {
            //Implementation Here
            return true;
        }
        public bool CancelTicket(ItineraryInfo itinerary)
        {
            //Implementation Here
            return true;
        }
    }
For simplicity, we will consider only AbacusServer where the data communication is through webservice. Now we need to handle the  creation of Classes for booking tickets for different Server.
    public class AirlineServer
    {

        public static IAirlineServerFactory CreateAirlineServerFactory(String serverType)
        {
            IAirlineServerFactory airlineServer= null;

            if (serverType == "Axes")
            {
                airlineServer = (IAirlineServerFactory)new AxesServer();
            }
            else if (serverType == "Abacus")
            {
                airlineServer = (IAirlineServerFactory)new AbacusServer();
            }
            else if (serverType == "Amadeus")
            {
                airlineServer = (IAirlineServerFactory)new AmadeusServer();
            }
            else if (serverType == "Galileo")
            {
                airlineServer = (IAirlineServerFactory)new GalileoServer();
            }
            return airlineServer;

        }
        
    }


AirlineServer Class acts as factory that actually creates the dependent object based on the servertype. Let us look into FlightItinerary which consumes the class for booking tickets. .

    public class FlightItinerary
    {
        public bool BookTickets(ItineraryInfo itinerary, String serverType)
        {
            IAirlineServerFactory airlineServer = AirlineServer.CreateAirlineServerFactory(serverType);
            return airlineServer.BookTicket(itinerary);
        }
    }
 Thus the concrete class implementation is masked by the IAirlineServerFactory, so we get to book ticket without knowing the implementation of server. To FlightItinerary, it is AirlineServer that has been exposed.


Let us look into second part of the problem


The details about the traveller and travel should be saved in our local database before booking the travel itinerary. The agent who booked the itinerary should also be saved in the itinerary.


We can solve this problem using another Creational pattern named as Singleton Pattern


  Singleton pattern will ensure a class has only one instance and it has only one global entry Point.


We need to save the itinerary in our local database with the details of the agent who booked the ticket.  The details about the agent will always be the same until he logs off. So we dont need to access the database everytime a ticket is booked for agent details.


    public class AgentInfo
    {
        private static AgentInfo _instance;


        public static AgentInfo  GetAgentInfo()
        {
            if (_instance == null)
            {
                _instance = new AgentInfo();
                //Implementation for setting AgentDetails
            }
            return _instance;
        }

    }

  Whenever the agent info needs to saved in the database the application will be get the instance from GetAgentInfo(), which in turn will return new instance if it is for the first time or already created instance if the instance is already created.

Thus booking ticket in different server is handled using Abstract Factory pattern and the user details that needs to be retrieved everytime,  for saving in the local database have been handled by Singleton pattern.

No comments:

Post a Comment

Note: only a member of this blog may post a comment.

Build Bot using LUIS