《重构改善既有代码的设计》第一个重构案例
来源:互联网 发布:资生堂淘宝有旗舰店吗 编辑:程序博客网 时间:2024/05/16 05:53
重构之前
Movie(影片)
public class Movie { //儿童片 public static final int CHILDRENS=0; //普通片 public static final int REGULAR=1; //新片 public static final int NEW_RELEASE=2; private String title; private int priceCode; public Movie(String title, int priceCode) { this.title = title; this.priceCode = priceCode; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public void setPriceCode(int priceCode) { this.priceCode = priceCode; }}
Rental(租赁)
public class Rental { private Movie movie; private int dayRented; public Rental(Movie movie, int dayRented) { this.movie = movie; this.dayRented = dayRented; } public Movie getMovie() { return movie; } public int getDayRented() { return dayRented; } }
Customer(顾客)
class Customer { private String _name; private Vector _rentals = new Vector(); public Customer(String name) { _name = name; } public void addRental(Rental arg) { _rentals.addElement(arg); } public String getName() { return _name; } public String statement(){ double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "\n"; while (rentals.hasMoreElements()) { double thisAmount = 0; Rental each = (Rental) rentals.nextElement(); /** * 租碟的价格是根据碟的类型进行计算的, * 一般的碟: * 2块钱起租赁,超过两天每天1块五 * 新碟: * 每天三块 * 儿童碟: * 不足四天都是1.5,超过四天(包括)每天1.5 */ //determine amounts for each line 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; } } // add frequent renter points frequentRenterPoints ++; // add bonus for a two day new release rental if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) { frequentRenterPoints ++; } // show figures fo this rental result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(thisAmount) + "\n"; totalAmount += thisAmount; } //add footer lines result += "Amount owed is " + String.valueOf(totalAmount) + "\n"; result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points"; return result; }}
开始重构
建立可靠的测试环境
重构第一步:增加方法,获取单个影片租赁花了费用
重构第二步:修改变量名称
重构第三步:因为这个方法只使用Rental类,没有使用Customer类,所以把这个方法从Customer类移到Rental类
重构第四步:搬移后,去除参数,同时改变函数名称
重构第五步:测试,看看有没有错误
重构第六步:将thisAmount直接使用each.getCharge()代替
重构第七步:提炼“常客积分计算”,也是把这个方法写到Rental类
重构第八步:把“获取总积分”提炼出来,把这个方法写到Customer类
重构第九步:将租期长度作为参数传入getCharge方法
重构第十步:将影片相关的费用、积分方法Move到Movie类中,将Rental的属性daysRented作为参数。
重构第十一步:运用多态取代与价格相关的条件逻辑。
创建Price价格类,作为抽象类给多种影片类型继承,关联到Movie影片类中
Rental(租赁)
public class Rental { private Movie movie; private int dayRented; public Rental(Movie movie, int dayRented) { this.movie = movie; this.dayRented = dayRented; } public Movie getMovie() { return movie; } public void setMovie(Movie movie) { this.movie = movie; } public int getDayRented() { return dayRented; } public void setDayRented(int dayRented) { this.dayRented = dayRented; } int getFrequentRenterPoints() { return movie.getFrequentRenterPoints(getDayRented()); }}
Customer(顾客)
public class Customer { private String name; // 动态数组 Vector _rentals = new Vector(); public Customer(String name) { super(); this.name = name; } public String getName() { return name; } public void addRentals(Rental arg) { _rentals.addElement(arg); } public String statement() { double totalAmount = 0; int frequentRenterPoints = 0; // Enumeration接口定义了从一个数据结构得到连续数据的手段 Enumeration rentals = _rentals.elements(); String result = "Rental Record for" + getName() + "\n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(each.getMovie().getPrice().getCharge(each.getDayRented())) + "\n"; } result += "Amount owed is " + String.valueOf(getTotalCharge()) + "\n"; result += "You earned " + String.valueOf(getTotalFrequentRenterPoints()) + "frequent renter points"; return result; } private int getTotalFrequentRenterPoints(){ int result=0; Enumeration rentals=_rentals.elements(); while(rentals.hasMoreElements()){ Rental each=(Rental)rentals.nextElement(); result+=each.getMovie().getFrequentRenterPoints(each.getDayRented()); } return result; } private double getTotalCharge(){ double result =0; Enumeration rentals=_rentals.elements(); while(rentals.hasMoreElements()){ Rental each=(Rental)rentals.nextElement(); result+=each.getMovie().getPrice().getCharge(each.getDayRented()); } return result; }}
Movie(影片)
public class Movie { // 儿童片 public static final int CHILDRENS = 0; // 普通片 public static final int REGULAR = 1; // 新片 public static final int NEW_RELEASE = 2; private String title; private int priceCode; public Movie(String title, int priceCode) { this.title = title; setPriceCode(priceCode); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getPriceCode() { return priceCode; } int getFrequentRenterPoints(int daysRented) { if ((getPriceCode() == Movie.NEW_RELEASE) && daysRented > 1) return 2; else return 1; } private Price price; public void setPriceCode(int arg) { switch (arg) { case REGULAR: price = new RegularPrice(); break; case CHILDRENS: price = new ChildrenPrice(); break; case NEW_RELEASE: price = new NewReleasePrice(); break; default: throw new IllegalArgumentException("Incorrect Price Code"); } } public Price getPrice() { return price; } public void setPrice(Price price) { this.price = price; }}
Price类
运用多态取代与价格相关的条件逻辑。
创建Price价格类,作为抽象类给多种影片类型继承,关联到Movie影片类中,
Price类:
abstract class Price { abstract int getPriceCode(); abstract double getCharge(int daysRenter);}class ChildrenPrice extends Price { int getPriceCode() { return Movie.CHILDRENS; } double getCharge(int daysRented) { double result = +1.5; if (daysRented > 3) { result += (daysRented - 3) * 1.5; } return result; }}class NewReleasePrice extends Price { int getPriceCode() { return Movie.NEW_RELEASE; } double getCharge(int daysRented) { return daysRented * 3; }}class RegularPrice extends Price { int getPriceCode() { return Movie.REGULAR; } double getCharge(int daysRented) { double result = 2; if (daysRented > 2) { result += (daysRented - 2) * 1.5; } return result; }}
测试
public class Test{ public static void main(String[] args) { Movie mov1 = new Movie("metal",2); mov1.setPriceCode(2); Rental ren = new Rental(mov1,8); Movie mov2 = new Movie("apple",1); mov2.setPriceCode(1); Rental xxx = new Rental(mov2,6); Customer cus = new Customer("Lee"); cus.addRental(ren); cus.addRental(xxx); System.out.println(cus.statement()); }}
阅读全文
0 0
- 《重构改善既有代码的设计》第一个重构案例
- 重构-改善既有代码的设计——第一章 重构,第一个案例
- 重构—改善既有代码的设计001:重构,第一个案例
- 重构改善既有代码的设计--重构第一个案例
- 《重构--改善既有代码的设计》--重构,第一个案例(1)
- 《重构-改善代码既有的设计》重构,第一个案例
- 《重构:改善既有代码的设计》案例一
- <<重构改善既有的代码设计>>第一章节
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构:改善既有代码的设计
- 重构--改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计
- 重构-改善既有代码的设计+
- 重构--改善既有代码的设计
- 如何自己组装电脑(从配件到整机)来省下一大笔钱
- hdu5667 Sequence矩阵连乘
- 题目1010:A + B
- 软件工程(C编码实践篇)学习总结
- windows系统下安装centos linux系统
- 《重构改善既有代码的设计》第一个重构案例
- less-Variable Interpolation(变量插值)
- 选项卡效果
- Java中的==和equals方法
- Ubuntu教程
- MySQL 之 SQL 语句优化学习
- Eclipse中查看JDK源码
- 36. 编写完成fun函数实现将一行字符串中的最短的单词输出。此行字符串从主函数传递给该函数。
- echarts柱状图虚线显示