Open/closed principle

When creating classes, we need to ensure that the class prohibits any breaking modifications by needing to change internal code. We say that such a class is closed. If we need to change it somehow, we can do so by extending the class. This extensibility is where we say that the class is open for extensions.

Getting ready

You will create a class that determines the skills of a trooper by looking at the class of trooper. We will show you the way many developers create such a class and the way it can be created using the open/closed principle.

How to do it…

  1. Create a class called StarTrooper:
    public class StarTrooper
    {
        
    }
  2. To this class, add an enumerator called TrooperClass to identify the type of trooper we want to return the skills of. Also, create a List<string> variable to contain the skills of the specific trooper class. Finally, create a method called GetSkills that returns the specific set of skills for the given trooper class.

    The class is quite straightforward, but the implementation of the code is something we see a lot. Sometimes, instead of a switch statement, you will see a whole lot of if else statements. While the functionality of the code is clear, it is not easy to add another class of trooper to the StarTrooper class without changing code. Assume that you now have to add an additional Engineer class to the StarTrooper class. You would have to modify the TrooperClass enumeration and the code in the switch statement.

    This changing of code can cause you to introduce bugs into code that was previously working fine. We now see that the StarTrooper class is not closed and can't be extended easily to accommodate additional TrooperClass objects:

    public enum TrooperClass { Soldier, Medic, Scientist }
    List<string> TroopSkill;
    
    public List<string> GetSkills(TrooperClass troopClass)
    {
        switch (troopClass)
        {
            case TrooperClass.Soldier:
            return TroopSkill = new List<string>(new string[] { "Weaponry", "TacticalCombat", "HandToHandCombat" });
    
            case TrooperClass.Medic:
            return TroopSkill = new List<string>(new string[] { "CPR", "AdvancedLifeSupport" });
    
            case TrooperClass.Scientist:
            return TroopSkill = new List<string>(new string[] { "Chemistry", "MollecularDeconstruction", "QuarkTheory" });
    
            default:
                return TroopSkill = new List<string>(new string[] { "none" });
        }
    }
  3. The solution to this problem is inheritance. Instead of having to change code, we extend it. Start off by rewriting the above StarTrooper class and create a Trooper class. The GetSkills method is declared as virtual:
    public class Trooper
    {
        public virtual List<string> GetSkills()
        {
            return new List<string>(new string[] { "none" });
        }
    }
  4. Now, we can easily create derived classes for the Soldier, Medic, and Scientist trooper classes available. Create the following derived classes that inherit from the Trooper class. You can see that the override keyword is used when creating the GetSkills method:
    public class Soldier : Trooper
    {
        public override List<string> GetSkills()
        {
             return new List<string>(new string[] { "Weaponry", "TacticalCombat", "HandToHandCombat" });
        }
    }
    
    public class Medic : Trooper
    {
        public override List<string> GetSkills()
        {
            return new List<string>(new string[] { "CPR", "AdvancedLifeSupport" });
        }
    }
    
    public class Scientist : Trooper
    {
        public override List<string> GetSkills()
        {
            return new List<string>(new string[] { "Chemistry", "MollecularDeconstruction", "QuarkTheory" });
        }
    }
  5. The code becomes extremely easy to implement when extending the class to add an additional class of Trooper. If we now want to add the Engineer class, we would simply override the GetSkills method after inheriting from the Trooper class created earlier:
    public class Engineer : Trooper
    {
    public override List<string> GetSkills()
        {
            return new List<string>(new string[] { "Construction", "Demolition" });
        }
    }

How it works…

The classes derived from the Trooper class are extensions of the Trooper class. We can say that each class is closed, because modifying it does not necessitate changing the original code. The Trooper class is also extensible because we have been able to easily extend the class by creating derived classes from it.

Another by-product of this design is smaller, more manageable code that is easier to read and understand.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.77.158