auto commit

This commit is contained in:
CyC2018 2018-03-04 14:43:31 +08:00
parent dc31eaa0d7
commit a22f778f32
6 changed files with 44 additions and 13 deletions

View File

@ -109,37 +109,68 @@
在重构前,需要先构建好可靠的测试环境,确保安全地重构。 在重构前,需要先构建好可靠的测试环境,确保安全地重构。
重构是以微小的步伐修改程序,如果犯下错误,很容易便可以发现它 重构需要以微小的步伐修改程序,如果重构过程发生错误,很容易就能发现错误
**案例分析** **案例分析**
影片出租店应用程序,包括三个类Movie、Rental 和 CustomerRental 包含租赁的 Movie 以及天数 影片出租店应用程序,需要计算每位顾客的消费金额
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//a758c8b2-0ac7-438f-90c2-3923ffad6328.png"/> </div><br> 包括三个类Movie、Rental 和 CustomerRental 包含租赁的 Movie 以及天数。
最开始的实现是把所有的计费代码都放在 Customer 类中,在变化发生时,需要对这部分代码进行更改。本案例中可能发生的变化有:一种类别的计费方式发生改变;添加新的电影类别。考虑到计费代码可能存在于多处,一旦发生改变时,就需要对所有计费代码进行修改。 <br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//25d6d3d4-4726-47b1-a9cb-3316d1ff5dd5.png"/> </div><br>
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//9e5e3cc6-3107-4051-b584-8ff077638fe6.png"/> </div><br> 最开始的实现是把所有的计费代码都放在 Customer 类中。
以下是继承 Movie 的多态方案。但是由于一部 Movie 的类别会动态改变,因此这种方案不可行 可以发现,该代码没有使用 Customer 类中的任何信息,更多的是使用 Rental 类的信息,因此第一个可以重构的点就是把具体计费的代码移到 Rental 类中,然后 Customer 类的 getTotalCharge() 方法只需要调用 Rental 类中的计费方法即可
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//2a502516-5d34-4eef-8f39-916298a60035.png"/> </div><br>
引入 Price 来反应类别信息,通过组合的方式在 Movie 中加入 Price 对象,这样每种类别的计费方式都封装在不同的 Price 子类中,并且 Movie 对象也可以动态改变类别。这种方式可以很好地适应上述提到的变化。 ```java
class Customer...
double getTotalCharge() {
while (rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental) rentals.nextElement();
switch (each.getMovie().getPriceCode()) {
case Movie.REGULAR:
thisAmount += 2;
if (each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
}
```
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//c02a83b8-a6b9-4d00-a509-6f0516beaf5e.png"/> </div><br> 使用 switch 的准则是只能在对象自己的数据上使用而不能在另一个对象的数据基础上使用。解释如下switch 使用的数据通常是一组相关的数据,例如上面的代码使用了 Movie 的多种类别数据。当这组类别的数据发生改变时,例如上面的代码中增加 Movie 的类别或者修改一种 Movie 类别的计费方法,就需要修改 switch 代码。如果允许违反了准则,就会有多个地方的 switch 使用了这部分的数据,那么需要打开所有的 switch 代码进行修改。
重构后的时序图和类图: 以下是继承 Movie 的多态解决方案,这种方案可以解决上述的 switch 问题,因为每种电影类别的计费方式都被放到了对应 Movie 子类中,当变化发生时,只需要去修改对应子类中的代码即可。
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//95f4559c-3d2a-4176-b365-4fbc46c76cf1.png"/> </div><br> <br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//76b48b4c-8999-4967-893b-832602e73285.png"/> </div><br>
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//293b9326-02fc-4ad8-8c79-b4a7b5ba60d3.png"/> </div><br> 但是由于 Movie 可以在其生命周期内修改自己的类别,一个对象却不能在生命周期内修改自己所属的内,因此这种方案不可行。可以通过使用策略模式来解决这种问题(原书写的是使用状态模式,但是这里应该为策略模式,具体可以参考设计模式内容)。
下图中Price 有多种实现Movie 组合了一个 Price 对象,并且在运行时可以改变组合的 Price 对象,从而使得它的计费方式发生改变。
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//2a842a14-e4ab-4f37-83fa-f82c206fe426.png"/> </div><br>
重构后整体的类图和时序图如下:
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//4440ad24-625b-489a-96c1-e5ab1b06a30f.png"/> </div><br>
<br><div align="center"> <img src="https://github.com/CyC2018/InterviewNotes/blob/master/pics//8c139711-3500-4f71-8456-c1adaf429ad0.png"/> </div><br>
# 第二章 重构原则 # 第二章 重构原则
重构是对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。 重构是对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构的好处:改进软件设计;使软件更容易理解;帮助找到 bug提高编程速度。 重构的好处:改进软件设计;使软件更容易理解;帮助找到 Bug提高编程速度。
三次法则:第一次做某件事时只管去做;第二次做类似事情时可以去做;第三次再做类似的事,就应该重构。 三次法则:第一次做某件事时只管去做;第二次做类似事情时可以去做;第三次再做类似的事,就应该重构。

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB