重构-改善既有代码的设计(一)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.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.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();
}
}
}
也就是利用了继承和虚函数来实现多态,来实现对修改封闭,对增加开放。