(11) - 替换switch语句
用switch语句时,当通过增加一个新类对基于switch结构的系统进行修改时,程序员可能会忘记将其添加到现有的所有switch结构中。每次新增和删除一个类都需要修改系统中的所有switch结构,但追踪这些语句非常耗时,而且也容易出错。这是就多态性编成而言的。
重构后
01.
public
boolean
isLeap(
int
year) {
02.
return
(year %
4
==
0
&& year %
100
!=
0
) || (year %
400
==
0
);
03.
}
04.
05.
public
static
int
getMonthDays(
int
year,
int
month) {
06.
int
numberDays =
0
;
07.
08.
switch
(month) {
09.
case
1
:
10.
case
3
:
11.
case
5
:
12.
case
7
:
13.
case
8
:
14.
case
10
:
15.
case
12
:
16.
numberDays =
31
;
17.
break
;
18.
19.
case
4
:
20.
case
6
:
21.
case
9
:
22.
case
11
:
23.
numberDays =
30
;
24.
break
;
25.
26.
case
2
:
27.
numberDays = isLeap(year) ?
29
:
28
;
28.
break
;
29.
}
30.
31.
return
numberDays;
32.
}
01.
public
boolean
isLeap(
int
year) {
02.
return
(year %
4
==
0
&& year %
100
!=
0
) || (year %
400
==
0
);
03.
}
04.
05.
private
int
getFebruaryDays(
int
year) {
06.
return
this
.isLeap(year) ?
29
:
28
;
07.
}
08.
09.
public
int
getMonthDays(
int
year,
int
month) {
10.
int
[] months =
new
int
[] {
31
,
this
.getFebruaryDays(year),
31
,
30
,
31
,
30
,
11.
31
,
31
,
30
,
31
,
30
,
31
};
12.
13.
return
months[month];
14.
}
(12) - 使用对象分装参数
当一个方法参数太多时,我一般认为超过4个的时候
重构后
1.
public
int
getRemainMinutes(
int
hour,
int
minute,
2.
int
fromHour,
int
fromMinute
3.
int
toHour,
int
toMinute) {
4.
......
1.
public
int
getRemainMinutes(DatePart datePart) {
2.
......
谈(13) - 封装集合操作
01.
public
Class Group{
02.
03.
private
List userList =
new
ArrayList();
04.
05.
public
void
setUserList(List userList){
06.
this
.userList = userList;
07.
}
08.
09.
public
List getUserList(){
10.
return
this
.userList;
11.
}
12.
}
01.
public
Class Group{
02.
03.
private
List userList =
new
ArrayList();
04.
05.
public
void
setUserList(List userList){
06.
this
.userList = userList;
07.
}
08.
09.
public
List getUserList(){
10.
return
this
.userList;
11.
}
12.
13.
public
void
addUser(User user){
14.
this
.getUserList().add(user);
15.
user.setGroup(
this
);
16.
}
17.
18.
public
void
removeUser(User user){
19.
this
.getUserList().remove(user);
20.
user.setGroup(
null
);
21.
}
22.
}
(14) - 使用委派代替继承
当子类从关系上根本不是父类的继承时
Child 和Sanitation (公共设施)是没有逻辑上的父子关系,因为小孩不可能是一个公共设施吧!所以我们为了完成这个功能可以考虑使用委派的方式。
同理,如果反过来,委派的对象明显应该是子类,就应该改成继承
01.
public
class
Sanitation
02.
{
03.
public
String WashHands()
04.
{
05.
return
"Cleaned!"
;
06.
}
07.
}
08.
09.
public
class
Child
extends
Sanitation
10.
{
11.
12.
}
01.
public
class
Sanitation
02.
{
03.
public
String WashHands()
04.
{
05.
return
"Cleaned!"
;
06.
}
07.
}
08.
09.
public
class
Child
10.
{
11.
private
Sanitation sanitation;
12.
13.
public
Child()
14.
{
15.
sanitation =
new
Sanitation();
16.
}
17.
18.
public
String WashHands()
19.
{
20.
return
sanitation.WashHands();
21.
}
22.
}
(15) - 面向接口编程
超过一个的类要使用某一个类中部分方法时,我们应该解开它们之间的依赖,让调用者使用接口,这很容易实现也可以降低代码的耦合性
重构后
01.
public
class
ClassRegistration
02.
{
03.
public
void
Create() {
04.
//代码
05.
}
06.
07.
public
void
Transfer() {
08.
//代码
09.
}
10.
}
11.
12.
public
class
RegistrationProcessor
13.
{
14.
public
void
;P rocessRegistration(ClassRegistration registration)
15.
{
16.
registration.Create();
17.
registration.Transfer();
18.
}
19.
}
01.
public
interface
IClassRegistration
02.
{
03.
public
void
Create();
04.
05.
public
void
Transfer();
06.
}
07.
08.
public
class
ClassRegistration
implements
IClassRegistration
09.
{
10.
public
void
Create()
11.
{
12.
//代码
13.
}
14.
15.
public
void
Transfer()
16.
{
17.
//代码
18.
}
19.
}
20.
21.
public
class
RegistrationProcessor
22.
{
23.
public
void
;P rocessRegistration(IClassRegistration registration)
24.
{
25.
registration.Create();
26.
registration.Transfer();
27.
}
28.
}
(16) - 用策略模式代替if else和switch
好处是隔开耦合,以注入的形式实现功能,这使增加功能变得更加容易和简便,同样也增强了整个系统的稳定性和健壮性。
但并不是所有情况都要这么改,而是从意义上符合策略模式。
重构后
但并不是所有情况都要这么改,而是从意义上符合策略模式。
01.
public
class
ClientCode{
02.
public
double
CalculateShipping()
03.
{
04.
ShippingInfo shippingInfo =
new
ShippingInfo();
05.
return
shippingInfo.CalculateShippingAmount(State.Alaska);
06.
}
07.
}
08.
09.
public
enum
State
10.
{
11.
Alaska,
12.
NewYork,
13.
Florida
14.
}
15.
16.
public
class
ShippingInfo
17.
{
18.
public
double
CalculateShippingAmount(State shipToState)
19.
{
20.
if
(shipToState == State.Alaska)
return
GetAlaskaShippingAmount();
21.
else
if
(shipToState == State.NewYork)
return
GetNewYorkShippingAmount();
22.
else
if
(shipToState == State.Florida)
return
GetFloridaShippingAmount();
23.
else
return
0d;
24.
}
25.
26.
private
double
GetAlaskaShippingAmount()
27.
{
28.
return
15d;
29.
}
30.
31.
private
double
GetNewYorkShippingAmount()
32.
{
33.
return
10d;
34.
}
35.
36.
private
double
GetFloridaShippingAmount()
37.
{
38.
return
3d;
39.
}
40.
}
01.
public
class
ClientCode
02.
{
03.
public
IShippingInfo ShippingInfo;
04.
05.
public
double
CalculateShipping()
06.
{
07.
return
ShippingInfo.CalculateShippingAmount(State.Alaska);
08.
}
09.
}
10.
11.
public
enum
State
12.
{
13.
Alaska,
14.
NewYork,
15.
Florida
16.
}
17.
18.
public
class
ShippingInfo
implements
IShippingInfo
19.
{
20.
private
Map shippingCalculations;
21.
22.
public
ShippingInfo(List shippingList)
23.
{
24.
shippingCalculations =
new
HashMap();
25.
for
(IShippingCalculation calc : shippingList)
26.
{
27.
shippingCalculations.put(calc.state(), calc);
28.
}
29.
}
30.
31.
public
double
CalculateShippingAmount(State shipToState)
32.
{
33.
return
shippingCalculations.get(shipToState).Calculate();
34.
}
35.
}
36.
37.
public
interface
IShippingCalculation
38.
{
39.
State state();
40.
41.
double
Calculate();
42.
}
43.
44.
public
class
AlaskShippingCalculation
implements
IShippingCalculation
45.
{
46.
public
State State()
47.
{
48.
return
State.Alaska;
49.
}
50.
51.
public
double
Calculate()
52.
{
53.
return
15d;
54.
}
55.
}
56.
57.
public
class
NewYorkShippingCalculation
implements
IShippingCalculation
58.
{
59.
public
State State()
60.
{
61.
return
State.NewYork;
62.
}
63.
64.
public
double
Calculate()
65.
{
66.
return
10d;
67.
}
68.
}
69.
70.
public
class
NewYorkShippingCalculation
implements
IShippingCalculation
71.
{
72.
public
State State()
73.
{
74.
return
State.Florida;
75.
}
76.
77.
public
double
Calculate()
78.
{
79.
return
13
;
80.
}
81.
}
(17) - 分解复杂判断
把原来复杂的条件判断等语句用尽快返回等方式简化代码
重构后
01.
public
interface
ISecurityChecker{
02.
public
boolean
CheckPermission(String user, String permission);
03.
}
04.
public
class
Security
05.
{
06.
public
ISecurityChecker securityChecker;
07.
08.
public
Security(ISecurityChecker securityChecker) {
09.
this
.securityChecker = securityChecker;
10.
}
11.
12.
public
boolean
HasAccess(String user, String permission, List exemptions)
13.
{
14.
boolean
hasPermission =
false
;
15.
if
(user !=
null
)
16.
{
17.
if
(permission !=
null
)
18.
{
19.
if
(exemptions.size() ==
0
)
20.
{
21.
if
(securityChecker.CheckPermission(user, permission) || exemptions.contains(permission))
22.
{
23.
hasPermission =
true
;
24.
}
25.
}
26.
}
27.
}
28.
return
hasPermission;
29.
}
30.
}
01.
public
interface
ISecurityChecker
02.
{
03.
public
boolean
CheckPermission(String user, String permission);
04.
}
05.
public
class
Security
06.
{
07.
public
ISecurityChecker securityChecker;
08.
09.
public
Security(ISecurityChecker securityChecker) {
10.
this
.securityChecker = securityChecker;
11.
}
12.
13.
public
boolean
HasAccess(String user, String permission, List exemptions)
14.
{
15.
if
(user ==
null
|| permission ==
null
)
return
false
;
16.
if
(exemptions.contains(permission))
return
true
;
17.
return
securityChecker.CheckPermission(user, permission);
18.
}
19.
}
(18) - 契约式设计
契约式设计规定方法应该对输入和输出进行验证,这样你便可以保证你得到的数据是可以工作的,一切都是按预期进行的,如果不是按预期进行,异常或是错误就应该被返回,下面我们举的例子中,我们方法中的参数可能会值为
null
的情况,在这种情况下由于我们没有验证,
NullReferenceException
异常会报出
重构后
01.
public
class
Customer
02.
{
03.
public
double
balance;
04.
05.
public
double
getBalance()
06.
{
07.
return
balance;
08.
}
09.
10.
public
void
setBalance(
double
balance)
11.
{
12.
this
.balance = balance;
13.
}
14.
}
15.
16.
public
class
CashRegister
17.
{
18.
public
double
TotalOrder(List products, Customer customer)
19.
{
20.
double
total =
0
;
21.
for
(Double prise : products)
22.
{
23.
total += prise;
24.
}
25.
total += customer.getBalance();
26.
return
total;
27.
}
28.
}
01.
public
class
CashRegister
02.
{
03.
public
double
TotalOrder(List products, Customer customer)
04.
{
05.
if
(customer ==
null
)
throw
new
IllegalArgumentException(
"Customer cannot be null"
);
06.
07.
if
(products ==
null
|| products.isEmpty())
throw
new
IllegalArgumentException(
"Must have at least one product to total"
);
08.
09.
double
total =
0
;
10.
for
(Double prise : products)
11.
{
12.
total += prise;
13.
}
14.
total += customer.getBalance();
15.
return
total;
16.
}
17.
}
(19) - 除去上帝类
当一个类职责太大,方法实在太多,可以考虑细化成多个类
重构后
01.
public
class
CustomerService
02.
{
03.
public
double
calculateOrderDiscount()
04.
{
05.
//实现
06.
}
07.
08.
public
boolean
customerIsValid()
09.
{
10.
//实现
11.
}
12.
13.
public
boolean
register()
14.
{
15.
//实现
16.
}
17.
18.
public
boolean
forgotPassword()
19.
{
20.
//实现
21.
}
22.
}
01.
public
class
CustomerOrderService
02.
{
03.
public
double
calculateOrderDiscount()
04.
{
05.
//实现
06.
}
07.
08.
public
boolean
customerIsValid()
09.
{
10.
//实现
11.
}
12.
}
13.
14.
public
class
CustomerRegistrationService
15.
{
16.
public
boolean
register()
17.
{
18.
//实现
19.
}
20.
21.
public
boolean
forgotPassword()
22.
{
23.
//实现
24.
}
25.
}
(20) - 尽快返回
当条件判断对性能消耗较大时,这种的写法得尽可能避免
重构后
01.
public
boolean
test()
02.
{
03.
boolean
result;
04.
if
(条件判断) result =
true
;
05.
else
(条件判断) result =
false
;
06.
else
(条件判断) result =
true
;
07.
else
(条件判断) result =
false
;
08.
else
(条件判断) result =
true
;
09.
else
(条件判断) result =
false
;
10.
else
result =
true
;
11.
return
result;
12.
}
01.
public
boolean
test()
02.
{
03.
if
(条件判断)
return
true
;
04.
else
(条件判断)
return
false
;
05.
else
(条件判断)
return
true
;
06.
else
(条件判断)
return
false
;
07.
else
(条件判断)
return
true
;
08.
else
(条件判断)
return
false
;
09.
else
return
true
;
10.
}