以下将以6次重构的操作来实现一个简单的案例。
例子:这是一个影片出租店用的程序,计算每一个顾客的消费金额并打印详单。操作者告诉程序:顾客租了哪些影片,租期多长,程序便根据租赁时间和影片的类型算出费用。影片分为三类:普通片,儿童片和新片。除了计算费用,还要为常客计算积分,积分会根据租片的种类是否为新片而有所不同。
- 首先提个问题:什么时候重构?
- 看代码实现上面案例如下:
Movie.java(影片实体类)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31public class Movie {
public static final int CHILEDRENS = 2;
public static final int REGULAR = 0;
public static final int NEW_RELEASE = 1;
public Movie(String title, int priceCode) {
this.title = title;
this.priceCode = priceCode;
}
private String title;
private int priceCode;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getPriceCode() {
return priceCode;
}
public void setPriceCode(int priceCode) {
this.priceCode = priceCode;
}
}
Rental.java(租赁类)
1 | public class Rental { |
Customer.java(顾客租赁类)
1 | public class Customer { |
以上代码实现完全没有问题,但是能如果遇到以下这两个问题,就会突出臃肿,可扩展性差,难以维护等缺点了。
- 如果计费标准变化了?
- 就需要找到每条case中的计费方式,整个switch语句会十分庞大。
- 如果想输出statement()中某个数据显示到表单或者被其他地方引用?
- 没有任何方法独立提出来,导致重复引用的计算多处出现。
如果你发现自己需要为程序添加一个特性,而代码的结构使你无法很方便地达到目的,那就先重构那个程序,使特性的添加比较容易进行,然后再添加特性。
###重构(一)
分解并重组statement()
1 | public String statement() { |
每次做完一次这样的修改都要编译并测试。这次测试发现错误了吧。故意把返回的double改成了int类型。
就是为了告诉我们每次修改都要非常小心,并且编译测试,不但不会浪费时间,反而会节省大量的调试时间。
###重构(二)
修改函数名称/参数名称
1 | private double amountFor(Rental rental){ |
任何一个傻瓜都可以写出计算机可以理解的代码,唯有写出人类容易理解的代码,才是优秀的程序员。
###重构(三)
搬移函数(移动到它该到的地方去)
1 | public class Customer { |
Rental.java类
1 | public class Rental { |
重构(四)
提炼函数(越细小的函数功能越明确)/去除临时变量(使结构更清晰)
1 | public String statement() { |
Rental.java类
1 | public class Rental { |
###重构(五)
多态来提炼switch()语句
这里不直接抽象Movie类,是因为Movie类有自己的属性和生命周期。所以State模式的应用可以很好的解决这个问题。
Movie.java类
1 | public class Movie { |
Price.java类
1 | abstract class Price { |
NewReleasePrice.java类
1 | public class NewReleasePrice extends Price { |
其他两个实现类同NewReleasePrice类,就不列出来了。
###重构(六)
继承
1 | abstract class Price { |
NewReleasePrice.java类
1 | public class NewReleasePrice extends Price { |
前面列出的技术点仅仅只是一个起点,使你登堂入室之前的大门。如果没有这些技术,你根本无法对运行的程序进行任何设计上的改动。有了这些技术,你仍然做不到,但起码可以开始尝试了。