Hooks Method in C#

In my last blog, I explained about Template Method Design Pattern.

In this blog, I would take Template Method to the next level. In this blog, I would explains about “Hooks” and why are they needed.

What are Hooks?

A hook is a method that is declared in the abstract class but it is either empty or contains default implementation.

Why are they needed?

Hooks give subclass the ability to hook into the algorithm (template method) at various points. Subclasses, if they wish, can hook into the algorithm or are free to ignore the hook.

That means there is no obligation that each subclass should follow the each and every step defined in algorithm. They have freedom to skip a step but the order of steps are preserved by template method.

Example:

I also explained about ON and Off buttons. These button follows an orderly invocation of methods defined in Template Method.

What if we introduce a one more method in our algorithm that sets the Duration of the timer. That means when a Switch-On button is pressed, it asks user to set the timer duration for which an equipment must be operational / kept on. But it is upto the equipment if they wish to use this functionality and there is no obligation.

Code: 
  1. public  sealed override void Exceute()  
  2.         {  
  3.             IsPowerOn();  
  4.             CheckTheStatusOfDevice();  
  5.             SwitchOnOffDevice();  
  6.   
  7.              if(IsTimerset())  
  8.               {  
  9.                SetTheTimerDuration();  
  10.               }  
  11.         } 


 In the code above, IsTimerSet is a hook. It contains the default implementation in the abstract class where template method is defined.
  1. protected  virtual bool IsTimerset()  
  2.      {  
  3.          return false;  
  4.      } 
Subclasses can override this method but doesn't have to.
  1. public class SwitchOnWaschmachine:ICommand  
  2.    {  
  3.        private readonly Waschmachine _waschmachine;  
  4.        private bool isDeviceOn { getset; }          
  5.        public SwitchOnWaschmachine(Waschmachine waschmachine)  
  6.        {  
  7.            _waschmachine = waschmachine;  
  8.        }  
  9.   
  10.   
  11.        protected override void SwitchOnOffDevice()  
  12.        {  
  13.            if (isDeviceOn)  
  14.            {  
  15.                Console.WriteLine("Device is Already On");  
  16.            }  
  17.            else  
  18.            {  
  19.                _waschmachine.SwitchOn();  
  20.   
  21.            }  
  22.        }  
  23.   
  24.        protected override void CheckTheStatusOfDevice()  
  25.        {  
  26.            if (_waschmachine._deviceStatus)  
  27.                isDeviceOn = true;  
  28.            else  
  29.                isDeviceOn = false;  
  30.        }  
  31.   
  32.        protected override bool IsTimerset()  
  33.        {  
  34.            bool shouldTimerBeSet = getUserInput();  
  35.   
  36.            return shouldTimerBeSet;  
  37.        }  
  38.   
  39.        public override string ToString()  
  40.        {  
  41.            return "Washing Machine";  
  42.        }  
  43.   
  44.        private bool getUserInput()  
  45.        {  
  46.            do  
  47.            {  
  48.                DialogResult dialogResult=MessageBox.Show("Do you want to set the time?""Remote Control", MessageBoxButtons.YesNo);  
  49.                string userInput = Console.ReadLine();  
  50.                var timer = dialogResult== DialogResult.Yes ? enumTimer.Yes : enumTimer.No;  
  51.   
  52.                switch (timer)  
  53.                {  
  54.                    case enumTimer.Yes:  
  55.                        return true;  
  56.                    case enumTimer.No:  
  57.                        return false;  
  58.                }  
  59.            } while (true);  
  60.        }  
  61.   
  62.        protected override void SetTheTimerDuration()  
  63.        {  
  64.            MessageBox.Show("Timer is set for default duration");  
  65.        }  
  66.    } 
 To use the hook, it is overriden in the subclass and subclasses provides their own functionality.
 
Summary

Use abstract method when your subclass MUST provide an implementation of the method or step in algorithm. Hooks should be used when a certain step is optional. With hooks, there is no obligation for subclasses to implement them. They can if they wish to.