重构--改善既有代码的设计--读书笔记1
2011-01-31 17:07
381 查看
重构--改善既有代码的设计--读书笔记1
看了第一章的,敲出了所有的代码,共4版,自己理解写的比较少。以后慢慢在以后各章中补充吧。第一章看的还算顺利,可能代码太少了,还体会不深。ver1
package Refactoring_Impr; import java.util.Enumeration; import java.util.Vector; public class C1_ver1 { 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 arg) { _priceCode = arg; } public String getTitle() { return _title; }; } 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; } } class Customer { private String _name; private Vector<Rental> _rentals = new Vector<Rental>(); 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<Rental> rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "/n"; while (rentals.hasMoreElements()) { double thisAmount = 0; Rental each = (Rental) 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" + 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; } } }
提取出accountFor()
拿到第一版本的代码,首先第一印象是statement()函数太长了。将长函数切分为几个短函数,当有新的功能函数需要实现时更好重用。
运用Extract Method提取switch代码段。
在大函数里面的局部变量,不会被修改的可以作为新的小函数的入参。
重构技术以微小的步伐前进,方便查错。
将accountFor()移到到Rental类中,因为他只用到了Rental中的信息。
使用了委托测试新修改后的代码。
移去原有的多余临时变量thisAccount,改成rental.getCharge(),这涉及到了重构与性能的问题。(在P69会再讨论) Replace temp with query
提取常客积点代码
点数计算的方式只与影片的类型有关。变化不会很多,先放到Rental中。
ver2
package Refactoring_Impr; import java.util.Enumeration; import java.util.Vector; public class C1_ver2 { 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 arg) { _priceCode = arg; } public String getTitle() { return _title; }; } 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 int getFrequentRenterPoints() { if ((getMovie().getPriceCode() == Movie.NEW_RELEASE) && getDaysRented() > 1) return 2; else return 1; } public double getCharge() { double result = 0; 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; } } class Customer { private String _name; private Vector<Rental> _rentals = new Vector<Rental>(); 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<Rental> rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "/n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += each.getFrequentRenterPoints(); // show figures for this rental result += "/t" + each.getMovie().getTitle() + "/t" + String.valueOf(each.getCharge()) + "/n"; totalAmount += each.getCharge(); } // add footer lines result += "Amount owed is " + String.valueOf(totalAmount) + "/n"; result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points"; return result; } } }
去除临时变量,totalAmount和frequentRenterPoints这两个临时变量
这样多带来了2次循环,但是提取成函数可以增加复用性。有利有弊
增加了一个htmlStatement()函数证明这点
多态取代switch
null
ver3
package Refactoring_Impr; import java.util.Enumeration; import java.util.Vector; public class C1_ver3 { 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 String getTitle() { return _title; } public int getFrequentRenterPoints(int daysRented) { if ((getPriceCode() == Movie.NEW_RELEASE) && daysRented > 1) return 2; else return 1; } double getCharge(int daysRented) { double result = 0; 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; } } class Rental { private Movie _movie; private int _daysRented; public Rental(Movie movie, int daysRented) { _movie = movie; _daysRented = daysRented; } public Movie getMovie() { return _movie; } public int getFrequentRenterPoints() { return _movie.getFrequentRenterPoints(_daysRented); } public double getCharge() { return _movie.getCharge(_daysRented); } } class Customer { private String _name; private Vector<Rental> _rentals = new Vector<Rental>(); public Customer(String name) { _name = name; }; public void addRental(Rental arg) { _rentals.addElement(arg); } public String getName() { return _name; } public String statement() { Enumeration<Rental> rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "/n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); // show figures for this rental result += "/t" + each.getMovie().getTitle() + "/t" + String.valueOf(each.getCharge()) + "/n"; } // add footer lines result += "Amount owed is " + String.valueOf(getTotalCharge()) + "/n"; result += "You earned " + String.valueOf(getTotalFrequentRenterPoints()) + " frequent renter points"; return result; } public String htmlStatement() { Enumeration<Rental> rentals = _rentals.elements(); String result = "<H1>Rentals for <EM>" + getName() + "</EM></H1><P>/n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); // show figures for each rental result += each.getMovie().getTitle() + ": " + String.valueOf(each.getCharge()) + "<BR>/n"; } // add footer lines result += "<P>You owe <EM>" + String.valueOf(getTotalCharge()) + "</EM><P>/n"; result += "On this rental you earned <EM>" + String.valueOf(getTotalFrequentRenterPoints()) + "</EM> frequent renter points<P>"; return result; } private double getTotalCharge() { double result = 0; Enumeration<Rental> rentals = _rentals.elements(); while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); result += each.getCharge(); } return result; } private int getTotalFrequentRenterPoints() { int result = 0; Enumeration<Rental> rentals = _rentals.elements(); while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); result += each.getFrequentRenterPoints(); } return result; } } }
继承
因为影片类型变化较大,且他们就好像在回答一种问题。采用继承体系。
ver4
package Refactoring_Impr; import java.util.Enumeration; import java.util.Vector; import Refactoring_Impr.C1_ver2.Rental; public class C1_ver4 { 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 Price _price; public Movie(String title, int priceCode) { _title = title; setPriceCode(priceCode); } public double getCharge(int daysRented) { return _price.getCharge(daysRented); } int getFrequentRenterPoints(int daysRented) { return _price.getFrequentRenterPoints(daysRented); } public void setPriceCode(int arg) { switch (arg) { case REGULAR: _price = new RegularPrice(); break; case CHILDRENS: _price = new ChildrensPrice(); break; case NEW_RELEASE: _price = new NewReleasePrice(); break; default: throw new IllegalArgumentException("Incorrect Price Code"); } } public String getTitle() { return _title; }; } abstract class Price { abstract double getCharge(int daysRented); int getFrequentRenterPoints(int daysRented) { return 1; } } class ChildrensPrice extends Price { double getCharge(int daysRented) { double result = 1.5; if (daysRented > 3) result += (daysRented - 3) * 1.5; return result; } } class NewReleasePrice extends Price { double getCharge(int daysRented) { return daysRented * 3; } int getFrequentRenterPoints(int daysRented) { return (daysRented > 1) ? 2 : 1; } } class RegularPrice extends Price { double getCharge(int daysRented) { double result = 2; if (daysRented > 2) result += (daysRented - 2) * 1.5; return result; } } 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 int getFrequentRenterPoints() { return _movie.getFrequentRenterPoints(_daysRented); } public double getCharge() { return _movie.getCharge(_daysRented); } } class Customer { private String _name; private Vector<Rental> _rentals = new Vector<Rental>(); 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<Rental> rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "/n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); frequentRenterPoints += each.getFrequentRenterPoints(); // show figures for this rental result += "/t" + each.getMovie().getTitle() + "/t" + String.valueOf(each.getCharge()) + "/n"; totalAmount += each.getCharge(); } // add footer lines result += "Amount owed is " + String.valueOf(totalAmount) + "/n"; result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points"; return result; } } }
相关文章推荐
- 重构(改善既有代码的设计)-- 读书笔记1
- 读书摘录之《重构-改善既有代码的设计》简要摘录
- “重构-改善既有代码的设计”笔记
- 《重构-改善既有代码的设计》 读书心得
- 处理概括关系(读书摘要——重构改善既有代码的设计)
- 《重构 改善既有代码的设计》学习笔记 1
- 大型重构(读书摘要——重构改善既有代码的设计)
- 读重构-改善既有代码的设计笔记
- 重新组织你的函数(读书摘要——重构改善既有代码的设计)
- 简化条件表达式(读书摘要——重构改善既有代码的设计)
- 《重构 改善既有代码的设计》笔记
- 代码坏味道 重构: 改善有效代码的设计--阅读笔记
- 重构—改善既有代码的设计第一天笔记
- 重构_改善既有代码的设计第二天笔记
- 笔记-重构-改善既有代码的设计(Refactoring - Improving the Design of Existing Code)
- 重构 改善既有代码的设计-学习笔记
- 《重构-改善既有代码的设计》8.13笔记
- 【笔记】《重构-改善既有代码的设计》
- 《重构 改善即有代码的设计》笔记
- 《重构-改善既有代码的设计》学习笔记(一)