《重构-改善既有代码的设计》是一本好书,值得大家去反复看几遍,对后面学习设计模式有很好的帮助。设计模式猛一看,会很晕,云里雾里的,所以可以从重构开始,一点一点改善代码的设计,然后重构到模式,这样可以理解的更透侧,更容易消化。
书中会列举出很多的坏味道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。
代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
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的方法。
新添加一个员工类型,修改代码是必然的,但是可以控制在一定的范围内,代码应该对修改封闭,对增加开发,这也是一个代码设计原则。有一种办法,例如面向对象的多态,可以很好的解决这个问题,使得下次增加员工类型的话,只是修改枚举量和新建一个员工类,其他的什么都不用动了。只要将上面的类改造为下面的内容。
代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->
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();
}
}
}
也就是利用了继承和虚函数来实现多态,来实现对修改封闭,对增加开放。