《重构 改善既有代码的设计》读书笔记1

首先我们看重构之前的,共有三个类,Customer,Movie,Rental。全都是自己写的数据类。

// Rental: 表示某个顾客租了一部影片
public class Rental
{
private Movie _movie;
private int _daysRented;

public Rental(Movie movie, int daysRented)
{
_movie = movie;
_daysRented = daysRented;
}

public int getDaysRented()
{
return _daysRented;
}

public Movie getMovie()
{
return _movie;
}
}
// Movie: 纯数据类,代表一个影片
public class Movie
{
public static final int CHILDRENS = 2;
public static final int REGULAR = 0;
public static final int NEW_RELEASE = 1;

private String _title;
private int _priceCode;

public Movie(String title, int priceCode)
{
_title = title;
_priceCode = priceCode;
}

public int getPriceCode()
{
return _priceCode;
}

public void setPriceCode(int priceCode)
{
_priceCode = priceCode;
}

public String getTitle()
{
return _title;
}
}
// Customer: 顾客
public class Customer
{
private String _name;
private Vector<Rental> _rentals = new Vector<Rental>();

public Customer(String name)
{
_name = name;
}

public void addRental(Rental rental)
{
_rentals.add(rental);
}

public String getName()
{
return _name;
}

public String statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;

Enumeration<Rental> rentals = _rentals.elements();

String result = "Rental record for " + getName() + "\n";

while(rentals.hasMoreElements())
{
double thisAmount = 0;
Rental each = rentals.nextElement();

// 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 for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ thisAmount + "\n";
totalAmount += thisAmount;
}

// add footer lines
result += "Amount owed is" + totalAmount + "\n";
result += "You earned " + frequentRenterPoints + "frequent renter points";
return result;
}
}

我们可以看到,Customer中的statement()函数过于复杂,这时我们就开始想要重构了。

首先我们看到,很明显的就是statement()中的switch语句,我们应该把它放到单独的一个函数中,所以我们要对switch处进行重构。

第一次重构:提取函数后的Customer类

// Customer: 顾客
public class Customer
{
private String _name;
private Vector<Rental> _rentals = new Vector<Rental>();

public Customer(String name)
{
_name = name;
}

public void addRental(Rental rental)
{
_rentals.add(rental);
}

public String getName()
{
return _name;
}

public String statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;

Enumeration<Rental> rentals = _rentals.elements();

String result = "Rental record for " + getName() + "\n";

while(rentals.hasMoreElements())
{
double thisAmount = 0;
Rental each = rentals.nextElement();

thisAmount += amountFor(each);

// 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 for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ thisAmount + "\n";
totalAmount += thisAmount;
}

// add footer lines
result += "Amount owed is" + totalAmount + "\n";
result += "You earned " + frequentRenterPoints + "frequent renter points";
return result;
}

private double amountFor(Rental each)
{
double thisAmount = 0;
// 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;
}

return thisAmount;
}
}

之后我们会发现amountFor()中的一些变量的名字不是很好,所以我们进行重命名

    private double amountFor(Rental aRental)
{
double result = 0;
// determine amounts for each line
switch(aRental.getMovie().getPriceCode())
{
case Movie.REGULAR:
result += 2;
if(aRental.getDaysRented() > 2)
{
result += (aRental.getDaysRented() - 2) * 1.5;
}
break;

case Movie.NEW_RELEASE:
result += aRental.getDaysRented() * 3;
break;

case Movie.CHILDRENS:
result += 1.5;
if(aRental.getDaysRented() > 3)
{
result += (aRental.getDaysRented() - 3) * 1.5;
}
break;
}

return result;
}

之后我们发现,amountFor()在Customer类中,可是却没有使用来自Customer类的信息,而是使用了来自Rental类的信息,所以我们需要考虑将amountFor()搬移到Rental类中

在这里我们同时改了一下函数名:amountFor() -> getCharge()

新的Rental:

// Rental: 表示某个顾客租了一部影片
public class Rental
{
private Movie _movie;
private int _daysRented;

public Rental(Movie movie, int daysRented)
{
_movie = movie;
_daysRented = daysRented;
}

public int getDaysRented()
{
return _daysRented;
}

public Movie getMovie()
{
return _movie;
}

public double getCharge()
{
double result = 0;
// determine amounts for each line
switch(getMovie().getPriceCode())
{
case Movie.REGULAR:
result += 2;
if(getDaysRented() > 2)
{
result += (getDaysRented() - 2) * 1.5;
}
break;

case Movie.NEW_RELEASE:
result += getDaysRented() * 3;
break;

case Movie.CHILDRENS:
result += 1.5;
if(getDaysRented() > 3)
{
result += (getDaysRented() - 3) * 1.5;
}
break;
}

return result;
}
}

新的Customer中的statement:

public String statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;

Enumeration<Rental> rentals = _rentals.elements();

String result = "Rental record for " + getName() + "\n";

while(rentals.hasMoreElements())
{
double thisAmount = 0;
Rental each = rentals.nextElement();

thisAmount += each.getCharge();

// 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 for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ thisAmount + "\n";
totalAmount += thisAmount;
}

// add footer lines
result += "Amount owed is" + totalAmount + "\n";
result += "You earned " + frequentRenterPoints + "frequent renter points";
return result;
}

之后我们发现,stateme()中的thisAmount显得有点多余了,接受each.getCharge()的执行结果,然后就不会有任何修改,所以我们运用Replace Temp With Query把thisAmount去掉

新的statement():

public String statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;

Enumeration<Rental> rentals = _rentals.elements();

String result = "Rental record for " + getName() + "\n";

while(rentals.hasMoreElements())
{
Rental each = rentals.nextElement();

// 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 for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ each.getCharge() + "\n";
totalAmount += each.getCharge();
}

// add footer lines
result += "Amount owed is" + totalAmount + "\n";
result += "You earned " + frequentRenterPoints + "frequent renter points";
return result;
}

下一步对“常客积分计算”做类似的处理,积分的计算视影片的种类而有所不同不过不像收费规则(getCharge())有那么多变化,我们将常客积分计算的任务交给Rental:

Rental中新增加的函数:

    public int getFrequentRentalPoints()
{
int frequentRenterPoints = 0;
frequentRenterPoints++;
if(getMovie().getPriceCode() == Movie.NEW_RELEASE
&& getDaysRented() > 1)
{
frequentRenterPoints++;
}

return frequentRenterPoints;
}

Customer的statement函数:

public String statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;

Enumeration<Rental> rentals = _rentals.elements();

String result = "Rental record for " + getName() + "\n";

while(rentals.hasMoreElements())
{
Rental each = rentals.nextElement();

frequentRenterPoints += each.getFrequentRentalPoints();

// show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ each.getCharge() + "\n";
totalAmount += each.getCharge();
}

// add footer lines
result += "Amount owed is" + totalAmount + "\n";
result += "You earned " + frequentRenterPoints + "frequent renter points";
return result;
}

之后我们需要去除临时变量:

Customer中的statement函数以及新增加的getTotalCharge和getTotalFrequentRenterPoints函数

    public String statement()
{
Enumeration<Rental> rentals = _rentals.elements();

String result = "Rental record for " + getName() + "\n";

while(rentals.hasMoreElements())
{
Rental each = rentals.nextElement();

// show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ each.getCharge() + "\n";
}

// add footer lines
result += "Amount owed is" + getTotalCharge() + "\n";
result += "You earned " + getTotalFrequentRenterPoints() + "frequent renter points";
return result;
}

private int getTotalFrequentRenterPoints()
{
int result = 0;
for(int n=0; n<_rentals.size(); n++)
{
result += _rentals.get(n).getFrequentRentalPoints();
}
return result;
}

private double getTotalCharge()
{
double result = 0;
for(int n=0; n<_rentals.size(); n++)
{
result += _rentals.get(n).getCharge();
}

return result;
}
原文地址:https://www.cnblogs.com/xiaobo68688/p/2316266.html