Friday, May 28, 2010

Lazy Initialization Pattern

As name suggests Lazy initialization pattern delays the creation of an object till it is requested for the first time in program.

Definition: The Lazy initialization pattern defers resource acquisitions to the latest possible point in time during system execution in order to optimize resource usage. 

Lazy initialization is typically accompanied by a flag for indicating whether the initialization process is executed or not. As and when an object is requested, associated flag is first tested. If the object is created priory by another request then same is returned else it is initialized on the spot.

Lazy initialization approach should only be used
  • When initialization of the instance variable would consume a significant amount of time.
  • When initialization of the instance variable would consume a significant amount of resources.
  • When chance of the variable not been used is very high
The benefits of this approach include:
  • Increase in performance of application due to avoiding unnecessary creation of an object.
  • Optimal utilization of memory, as creation of object is postponed till it actually required in application.
  • The stability of the applications is increased because resource exhaustion becomes less likely.
The Consequences of this approach include:
  • The execution of the Lazy Initialization can introduce a significant time delay to the regular program execution. Especially for real-time systems such behavior is not advisable.
  • Lazy Initialization might introduce additional complexity to the program, especially concerning the program logic and distribution of initialization code throughout class.
  • The behavior of a lazy Initialization pattern can become distinctly non-linear when certain thresholds are reached, e.g. virtual memory systems can end up thrashing. This disqualifies the pattern for usage in real-time systems.

For example, consder a Tax calculation application where calculation of actual tax that need to be payed is posponded till user filled all information and clicked 'Calculate' button.

package
{
   public class TaxCalculator()
   {
      private var grossIncome:Number;

      private var taxAmount:Number;

      public var monthlyBasic:Number;
      public var monthlyDA:Number;
      public var monthlyOther:Number;
      public var yearlyInsurance:Number;
      public var yearlyPPF:Number;
      public var yearlyBonds:Number;

      public function TaxCalculator():void
      {
      }
    
      pulic function get gross():Number
      {

         // Evaluating user gross income as an when asked, not prior to that.
         grossIncome = (monthlyBasic + monthlyDA + monthlyOther) * 12 - (yearlyInsurance + yearlyPPF + yearlyBonds);
         return grossIncome;
      }
      public function actualTaxAmount():Number
      {

         // Evaluating actual tax amount as an when asked,
         // not prior to that.
         var taxableAmount:Number = (gross-150000);

         if(taxableAmount < = 0)
         {
             taxAmount = 0
         }
         else
         {
            if(taxableAmount < = 350000)
            {
               taxAmount = taxableAmount * 0.1;
            }

            else
            {
               taxableAmount = taxableAmount - 350000;
               taxAmount += 35000;

               if(taxableAmount < = 300000)
               {
                  taxAmount += taxableAmount * 0.2;
               }
               else
               {
                  taxableAmount = taxableAmount - 300000;
                  taxAmount += 30000 + taxableAmount * 0.3;
               }
            }
         }

         return taxAmount;
      }
   }
}
class 1: TaxCalculator

package
{
   public class TaxCalculatorManager
   {
      private static var INSTANCE:TaxCalculator;

      public function TaxCalculatorManager(value:SingletomeEnforcer):void
      {
      }

      public static function getInstance():TaxCalculator
      {
         if(INSTANCE == null)
         {
            INSTANCE = new TaxCalculator();
         }
         
         return INSTANCE
      }
   }
}
/* Inline class to enforce singleton pattern */
class SingletonEnforcer
{
   
}
class 2: TaxCalculatorManager

package
{

   import flash.display.MovieClip;
   import flash.events.MouseEvent;

   public class Client extends MovieClip
   {

      private var taxCalculator:TaxCalculator;
    
      public function Client():void
      {

          init();
          calculateBtn.addEventListener(MouseEvent.CLICK, calculateTax);
      }

      private function init():void
      {
         // Initializing all on screen input text fields
         this.monthlyBasicTxt.text = 0;
         this.monthlyDATxt.text = 0;
         this.monthlyOtherTxt.text = 0;

         this.yearlyInsuranceTxt.text = 0;
         this.yearlyPPFTxt.text = 0;
         this.yearlyBondsTxt.text = 0;

         this.grossAmountTxt.text = 0;
         this.taxAmountTxt.text = 0;

      }
      public function calculateTax(e:MouseEvent):void
      {
         if(taxCalculator == null)
         {
            //Posponding initialization of TaxCalculator object
            //till it is first required;
            taxCalculator = TaxCalculatorManager.getInstance();
         }
         // setting user inputted income in TaxCalculator object
         taxCalculator.monthlyBasic = Number(this.monthlyBasicTxt.text);
         taxCalculator.monthlyDA = Number(this.monthlyDATxt.text);
         taxCalculator.monthlyOther = Number(this.monthlyOtherTxt.text);

         taxCalculator.yearlyInsurance = Number(this.yearlyInsuranceTxt.text);
         taxCalculator.yearlyPPF = Number(this.yearlyPPFTxt.text);
         taxCalculator.yearlyBonds = Number(this.yearlyBondsTxt.text);

         //displaying user gross value along with actual tax value.
         this.grossAmountTxt.text  = taxCalculator.gross
         this.taxAmountTxt.text  = taxCalculator.actualTaxAmount();
      }
   }
}
class 3: Client

Lazy initialization is often used together with a Factory Method Pattern. This combines three ideas:
  • Using a factory method to get instances of a class (Factory Method Pattern)
  • Storing the instances in a variable mapped with a flag, so that same instance is referred when getter is fired with same parameter  (compare with a Singleton Pattern)
  • Using lazy initialization to instantiate the object the first time it is requested (Lazy Initialization Pattern).

No comments:

Post a Comment