Refactoring: More and more long switch ... case and if ... else if ... else

Source: Internet
Author: User

In the code, there is often a conditional expression for a type code, such as a switch, a case or if ... else. As the business logic of the project grows and the code changes over the long term, these conditional judgment logic tends to become more verbose. Especially when the same logical judgment appears in multiple places (the structure is shown below), the readability and ease of maintenance of the code will become very bad. Each time you modify it, you must find all the places that have logical branches and modify them.

1 Switch(type)2 {3      Case "1":4         ...5          Break;6      Case "2":7         ...8          Break;9      Case default:Ten         ... One          Break; A } -  - ... ... the ... ... -  - Switch(type) - { +      Case "1": -         ... +          Break; A      Case "2": at         ... -          Break; -      Case default: -         ... -          Break; -}

When this happens in the code, you should consider refactoring it (another argument: try to refactor the switch ... case statement to avoid it appearing in your code).

To reconstruct the conditional expression of the type code judgment, we need to introduce the object-oriented polymorphic mechanism. The first way: use subclasses to replace conditional expressions .

As an example, we explain the process of refactoring in the employee category, which calculates the salary of different role employees. The original class structure to be refactored is as follows:

1  Public classEmployee_ori2 {3     Private int_type;4 5     Private Const intENGINEER =1;6     Private Const intSalesman =2;7     Private Const intMANAGER =3;8 9     Private decimal_basesalary =10000;Ten     Private decimal_royalty = -; One     Private decimal_bonus = -; A  -      PublicEmployee_ori (inttype) -     { the          This. _type =type; -     } -  -      Public decimalgetemployeesalary () +     { -         varMonthlysalary =0m; +  A         Switch( This. _type) at         {  -              CaseENGINEER: -Monthlysalary =_basesalary; -                  Break; -              Casesalesman: -Monthlysalary = _basesalary +_royalty; in                  Break; -              CaseMANAGER: toMonthlysalary = _basesalary +_bonus; +                  Break; -         } the  *         returnmonthlysalary; $     }Panax Notoginseng}

The method Getemployeesalary () returns the salary of the month according to the different roles of the employee, of course, the logic here is only indicative, do not delve into.

The class structure after refactoring with the subclass method is this:

The following details unfold. First, the host-class Employee class with type code is the base class, and subclasses are established for each role.

1  Public classengineer_sub:employee_sub2 {3     ...4 }5 6  Public classsalesman_sub:employee_sub7 {8     ...9 }Ten  One  Public classmanager_sub:employee_sub A { -     ... -}

At the same time, the constructor of the Employee base class is transformed into a static Create factory function.

1  Public StaticEmployee_sub Create (inttype)2 {3Employee_sub employee =NULL;4 5     Switch(type)6     {7          CaseENGINEER:8Employee =Newengineer_sub ();9              Break;Ten          Casesalesman: OneEmployee =Newsalesman_sub (); A              Break; -          CaseMANAGER: -Employee =Newmanager_sub (); the              Break; -     } -  -     returnemployee; +}

The static factory method also contains a switch logic. In the reconstructed code, the switch is judged only in this place, and is only involved in the process of object creation, and does not involve any business logic, so it is acceptable.

Each role subclass will overwrite the Getemployeesalary () method in the base class and apply its own rules to calculate the salary.

1 Private decimal 10000 ; 2 3  Public Override decimal getemployeesalary () 4 {5     return _basesalary; 6 }

In this way, the Getemployeesalary () method in the base class Employee has no practical meaning and turns it into an abstract method.

1  Public Abstract decimal getemployeesalary ();

The subclass has completely replaced the bloated switch expression. If Engineer, salesman or Manager have new behavior, you can add methods to their subclasses. or follow the new Employee Type, which can be implemented entirely by adding a new subclass. Here, the separation of services and their use is realized through polymorphism.

However, in some cases, such as when the object type needs to change in the life cycle (refinement to this example, such as Engineer promoted to Manager) or the type host class already has subclasses, the method of using subclass refactoring will not work. In this case, the second method is applied: replace the conditional expression with State/strategy .

Again, the first class structure after the method is refactored:

Extract a Employeetype class, type code of the host class Employee to reference it.

1  Public class employee_state 2 {3     // employee ' s type can be changed 4     Private NULL ; 5 }

Employeetype is the base class, with the specific employee type as its subclass. The Employeetype class contains a static factory method that creates an employee type create.

1  Public StaticEmployeetype_state Create (inttype)2 {3Employeetype_state Emptype =NULL;4 5     Switch(type)6     {7          CaseENGINEER:8Emptype =Newengineertype_state ();9              Break;Ten          Casesalesman: OneEmptype =Newsalesmantype_state (); A              Break; -          CaseMANAGER: -Emptype =Newmanagertype_state (); the              Break; -     } -  -     returnEmptype; +}

The method of calculating the employee's salary getemployeesalary () moves from employee class to employee type base class Employeetype. The method is override for each individual employee type class. Considering that Employeetype has no specific business logic meaning, the Getemployeesalary () method in Employeetype is changed to an abstract method.

1  Public classengineertype_state:employeetype_state2 {3     Private decimal_basesalary =10000;4 5      Public Override decimalgetemployeesalary ()6     {7         return_basesalary;8     }9}

Finally, attach the schematic code, click here to download.

Resources:

"Refactoring to improve existing code design" Martin Fowler

Refactoring: More and more long switch ... case and if ... else if ... else

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.