《重构 改善既有代码的设计》读书笔记2
2012-01-08 16:41
621 查看
我们继续重构,接下来我们遇到的问题是switch语句,书上说最好不要在另一个对象的属性基础上运用switch语句。如果不得不使用,也应该在对象自己的数据上使用而不是在别人的对象上使用。
我们看到Rental的getCharge()里边的switch语句中的选择条件是getMovie().getPriceCode(),所以我们需要将getCharge()放到Movie类中。
下边是新增加的Movie中的getCharge()和修改过的Rental中的getCharge():
之后,我们继续重构,我们以相同的方法处理常客积分的计算,这样我们就把根据影片类型而变化的所有东西都放到了Movie类中。
继续重构,我们来到了继承。
我们有数种影片类型,它们以不同的方式回答相同的问题。这听起来很像子类的工作。我们可以建立Movie的三个子类,每个子类都有自己的计算方法。
下边是UML图
继续重构:
首先我们使用Replace Type Code WithState/Strategy,第一步骤是针对类型代码使用Self Encapsulate Field,确保任何时候都通过取值函数和设置函数来访问类型代码。
我们直接修改Movie的构造函数:
修改为:
接下来,我们需要新建4个类:
然后我们就可以使用新建的这些类了,我们需要修改Movie类中的“价格代号”访问函数,让他们使用新建的类。
下边是修改前的样子:
这意味着我们必须在Movie类中保存一个Price对象,而不再是保存一个_priceCode变量了,此外我们还需要修改访问函数:
接下来我们要对getCharge()进行Move Method,从Movie转移到Price中
转移前的代码:
新的Price,ChildrenPrice,RegularPrice和NewReleasePrice类:
OK,所有的准备工作都做完了,我们来修改一下Movie的getCharge()函数:
修改前:
修改后:
OK,我们继续用同样的方法处理getFrequentRenterPoints()
首先我们在Price类中添加函数:
接着我们需要重写NewReleasePrice中的函数:
OK,做好准备我们就可以修改Movie中的getFrequentRenterPoints了
OK,我们的重构到此结束了。
我们看到Rental的getCharge()里边的switch语句中的选择条件是getMovie().getPriceCode(),所以我们需要将getCharge()放到Movie类中。
下边是新增加的Movie中的getCharge()和修改过的Rental中的getCharge():
// method in Movie public double getCharge(int daysRented) { double result = 0; // determine amounts for each line switch(getPriceCode()) { case Movie.REGULAR: result += 2; if(daysRented > 2) { result += (daysRented - 2) * 1.5; } break; case Movie.NEW_RELEASE: result += daysRented * 3; break; case Movie.CHILDRENS: result += 1.5; if(daysRented > 3) { result += (daysRented - 3) * 1.5; } break; } return result; }
// Method in Rental public double getCharge() { return _movie.getCharge(_daysRented); }
之后,我们继续重构,我们以相同的方法处理常客积分的计算,这样我们就把根据影片类型而变化的所有东西都放到了Movie类中。
// Movie中增加的函数 public int getFrequentRenterPoints(int daysRented) { if((getPriceCode() == Movie.NEW_RELEASE) && daysRented > 1) { return 2; } else { return 1; } }
// Rental中修改的函数 public int getFrequentRentalPoints() { return _movie.getFrequentRenterPoints(_daysRented); }
继续重构,我们来到了继承。
我们有数种影片类型,它们以不同的方式回答相同的问题。这听起来很像子类的工作。我们可以建立Movie的三个子类,每个子类都有自己的计算方法。
下边是UML图
继续重构:
首先我们使用Replace Type Code WithState/Strategy,第一步骤是针对类型代码使用Self Encapsulate Field,确保任何时候都通过取值函数和设置函数来访问类型代码。
我们直接修改Movie的构造函数:
public Movie(String title, int priceCode) { _title = title; _priceCode = priceCode; }
修改为:
public Movie(String title, int priceCode) { _title = title; setPriceCode(priceCode); }
接下来,我们需要新建4个类:
public abstract class Price { abstract int getPriceCode(); }
public class RegularPrice extends Price { @Override int getPriceCode() { return Movie.REGULAR; } }
public class NewReleasePrice extends Price { @Override int getPriceCode() { return Movie.NEW_RELEASE; } }
public class ChildrensPrice extends Price { @Override int getPriceCode() { return Movie.CHILDRENS; } }
然后我们就可以使用新建的这些类了,我们需要修改Movie类中的“价格代号”访问函数,让他们使用新建的类。
下边是修改前的样子:
private int _priceCode; public int getPriceCode() { return _priceCode; } public void setPriceCode(int priceCode) { _priceCode = priceCode; }
这意味着我们必须在Movie类中保存一个Price对象,而不再是保存一个_priceCode变量了,此外我们还需要修改访问函数:
private Price _price; public int getPriceCode() { return _price.getPriceCode(); } public void setPriceCode(int movieType) { switch(movieType) { case REGULAR: _price = new RegularPrice(); break; case CHILDRENS: _price = new ChildrensPrice(); break; case NEW_RELEASE: _price = new NewReleasePrice(); break; } }
接下来我们要对getCharge()进行Move Method,从Movie转移到Price中
转移前的代码:
// Method in Movie public double getCharge(int daysRented) { double result = 0; // determine amounts for each line switch(getPriceCode()) { case Movie.REGULAR: result += 2; if(daysRented > 2) { result += (daysRented - 2) * 1.5; } break; case Movie.NEW_RELEASE: result += daysRented * 3; break; case Movie.CHILDRENS: result += 1.5; if(daysRented > 3) { result += (daysRented - 3) * 1.5; } break; } return result; }
新的Price,ChildrenPrice,RegularPrice和NewReleasePrice类:
public abstract class Price { abstract int getPriceCode(); abstract double getCharge(int daysRented); }
public class ChildrensPrice extends Price { @Override int getPriceCode() { return Movie.CHILDRENS; } @Override double getCharge(int daysRented) { double result = 1.5; if(daysRented > 3) { result += (daysRented - 3) * 1.5; } return result; } }
public class NewReleasePrice extends Price { @Override int getPriceCode() { return Movie.NEW_RELEASE; } @Override double getCharge(int daysRented) { return daysRented * 3; } }
public class RegularPrice extends Price { @Override int getPriceCode() { return Movie.REGULAR; } @Override double getCharge(int daysRented) { double result = 2; if(daysRented > 2) { result += (daysRented - 2) * 1.5; } return result; } }
OK,所有的准备工作都做完了,我们来修改一下Movie的getCharge()函数:
修改前:
public double getCharge(int daysRented) { double result = 0; // determine amounts for each line switch(getPriceCode()) { case Movie.REGULAR: result += 2; if(daysRented > 2) { result += (daysRented - 2) * 1.5; } break; case Movie.NEW_RELEASE: result += daysRented * 3; break; case Movie.CHILDRENS: result += 1.5; if(daysRented > 3) { result += (daysRented - 3) * 1.5; } break; } return result; }
修改后:
public double getCharge(int daysRented) { return _price.getCharge(daysRented); }
OK,我们继续用同样的方法处理getFrequentRenterPoints()
首先我们在Price类中添加函数:
public abstract class Price { abstract int getPriceCode(); abstract double getCharge(int daysRented); int getFrequentRenterPoints(int daysRented) { return 1; } }
接着我们需要重写NewReleasePrice中的函数:
@Override int getFrequentRenterPoints(int daysRented) { if(daysRented > 1) { return 2; } else { return 1; } }
OK,做好准备我们就可以修改Movie中的getFrequentRenterPoints了
public int getFrequentRenterPoints(int daysRented) { return _price.getFrequentRenterPoints(daysRented); }
OK,我们的重构到此结束了。
相关文章推荐
- 重构 改善既有代码的设计读书笔记之一 重构原则
- 《重构 改善既有代码的设计》读书笔记一
- 《重构--改善既有代码的设计》读书笔记之三:分解并重组statement() part2
- 『重构--改善既有代码的设计』读书笔记----Move Method
- 《重构,改善既有代码的设计》读书笔记
- 『重构--改善既有代码的设计』读书笔记----Remove Middle Man
- 《重构:改善代码的既有设计》读书笔记
- 『重构--改善既有代码的设计』读书笔记----Introduce Explaning Variable
- 『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data
- 『重构--改善既有代码的设计』读书笔记----代码坏味道【4】
- 《重构--改善既有代码的设计》读书笔记之五:运用多态取代条件逻辑(if/else , switch)
- 《重构 改善既有代码的设计》读书笔记及心得体会
- 『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field
- 『重构--改善既有代码的设计』读书笔记----Replace Data Value with Object
- [读书笔记] 重构改善既有代码的设计(5)
- 『重构--改善既有代码的设计』读书笔记----Inline Class
- 『重构--改善既有代码的设计』读书笔记----Inline Method
- 【重构-改善既有代码的设计0】读书笔记
- 『重构--改善既有代码的设计』读书笔记----Replace Array with Object
- 重构 改善既有代码的设计读书笔记之二 需要重构的情况