代码改变世界

重构-改善既有代码的设计(一)switch statements

2010-03-19 19:03  Virus-BeautyCode  阅读(2612)  评论(4编辑  收藏  举报

  《重构-改善既有代码的设计》是一本好书,值得大家去反复看几遍,对后面学习设计模式有很好的帮助。设计模式猛一看,会很晕,云里雾里的,所以可以从重构开始,一点一点改善代码的设计,然后重构到模式,这样可以理解的更透侧,更容易消化。

  书中会列举出很多的坏味道bad smell,然后重构这些bad smell,增加复用性。其中一个就是当你使用switch的时候,尤其是case的东西定义了枚举类型的话,很多时候都可以用面向对象的多态很好的解决。要不然就是当你多一个枚举值的时候,需要修改原来的每一个switch,在每个里面添加一个case。

  近来在写一段程序的时候,大概需求是员工,有几个种类的员工,工程师,销售人员。设计好数据库就直接使用代码生成工具,生成了一大堆代码,设计的时候考虑到工程师或者销售人员数据量会很大,所以就放在了两个表中。

  这样就生成连个类engineer和salesman,和一些类的操作代码,就是一些add、delete、modify和get。

  就开始写后面的业务代码了,写的过程中发现engineer和salesman还是有很多是一样的,比如说username、password、logonname、birthday等等,就在业务层定义了一个employee类,类里面有一个属性叫做employeeType,初始化employee的时候会赋值,就是表明当前员工是engineer还是salesman。

 

 

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.
Text;

namespace ConsoleApplication2
{
    enum employeeType1
    {
        engineer,
        salesman
    }
    class employee11
    {
        private  employeeType _empType;
        private 
int _id;
        
public employee11(employeeType empType)
            : this(empType, 
0)
        {

        }
        
public employee11(int id)
            : this(employeeType.engineer, id)
        {

        }
        
public employee11(employeeType empType, int id)
        {
            this._empType 
= empType;
            this._id 
= id;
        }
        
public void PrintSalary()
        {
            switch (_empType)
            {
                
case employeeType.engineer:
                    engineer1 e 
= new engineer1(); 
                    e.PrintSalary();
                    
break;
                
case employeeType.salesman:
                    salesman1 s 
= new salesman1();
                    s.PrintSalary();
                    
break;
            }
        }
        
public void PrintName()
        {
            switch (_empType)
            {
                
case employeeType.engineer:
                    engineer1 e 
= new engineer1();
                    e.PrintName();
                    
break;
                
case employeeType.salesman:
                    salesman1 s 
= new salesman1();
                    s.PrintName();
                    
break;
            }
        }
    }
    class engineer1
    {

        
public  void PrintSalary()
        {
            Console.WriteLine("your salary 
is {0}", 1000);
        }
        
public void PrintName()
        {
            Console.WriteLine("your name 
is {0}", "shiwenbin");
        }
    }
    class salesman1
    {
        
public void PrintSalary()
        {
            Console.WriteLine("your salary 
is {0}", 2000);
        }
        
public void PrintName()
        {
            Console.WriteLine("your name 
is {0}", "swb");
        }
    }
}

 

 

 

  如果后面要添加一个新员工类型,比如说boss,这样的话,首先要修改枚举employeeType1,然后要建立一个boss类,然后写上操作代码,还要在员工类employee11中的所有switch中都添加一个case,判断是否boss,然后调用boss的方法。

  新添加一个员工类型,修改代码是必然的,但是可以控制在一定的范围内,代码应该对修改封闭,对增加开发,这也是一个代码设计原则。有一种办法,例如面向对象的多态,可以很好的解决这个问题,使得下次增加员工类型的话,只是修改枚举量和新建一个员工类,其他的什么都不用动了。只要将上面的类改造为下面的内容。

  

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.
Text;

namespace ConsoleApplication2
{
    enum employeeType
    {
        engineer,
        salesman
    }
    class employee1
    {
        protected employeeType _empType;
        protected 
int _id;
        
public employee1(employeeType empType):this(empType,0)
        {

        }
        
public employee1(int id):this(employeeType.engineer,id )
        {

        }
        
public employee1(employeeType empType, int id)
        {
            this._empType 
= empType;
            this._id 
= id;
        }
        
public virtual void PrintName()
        {

        }
        
public virtual void PrintSalary()
        {

        }
        
public virtual void Print()
        {
            Console.WriteLine("haha");
        }
        
public override string ToString()
        {
            
return string.Format("id is :{0}; type is {1}", _id, _empType);
        }
    }
    class engineer : employee1
    {

        
public engineer(int id)
            : base(employeeType.engineer)
        {
            this._id 
= id;
        }
        
public engineer()
            : base(employeeType.engineer)
        {
        }
        
public override void PrintName()
        {
            Console.WriteLine("i am {
0}", _empType.ToString());
        }
        
public override void PrintSalary()
        {
            Console.WriteLine("your salary 
is {0}", 1000);
        }
        
public override string ToString()
        {
            
return string.Format("id is :{0}; type is {1}", _id, _empType);
        }
    }
    class salesman : employee1
    {

        
public salesman(int id)
            : base(employeeType.salesman)
        {
            this._id 
= id;
        }
        
public salesman()
            : base(employeeType.engineer)
        {
        }
        
public override void PrintName()
        {
            Console.WriteLine("i am {
0}", _empType.ToString());
        }
        
public override void PrintSalary()
        {
            Console.WriteLine("your salary 
is {0}", 2000);
        }
        
public override string ToString()
        {
            
return string.Format("id is :{0}; type is {1}", _id, _empType);
        }
    }
    class Program
    {
        static void Main(string
[] args)
        {
            engineer emp1 
= new engineer(123);
            emp1.PrintName();
            emp1.PrintSalary();
            emp1.
Print();
            Console.WriteLine(emp1.ToString());
            Console.WriteLine("
------------------------------");
            salesman emp2 = new salesman(456);
            emp2.PrintSalary();
            emp2.
Print();
            Console.WriteLine(emp2.ToString());
            Console.WriteLine("
------------------------------");
            Console.ReadLine();
        }
    }
}

 

 

  

 

  也就是利用了继承和虚函数来实现多态,来实现对修改封闭,对增加开放。