读书笔记 | 重构第一章第一个案例

原始代码:

Customer类

package char1.version01;

import java.util.Enumeration;
import java.util.Vector;

public class Customer {
    private String _name;
    private Vector _rentals = new Vector<>();

    public Customer(String _name) {
        this._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 thisAmout = 0;
            Rental each = (Rental) rentals.nextElement();

            //
            switch (each.get_movie().getPriceCode()) {
                case Movie.REGULAR:
                    thisAmout += 2;
                    if (each.getDaysRented() > 2) {
                        thisAmout += (each.getDaysRented() - 2) * 1.5;
                    }
                    break;
                case Movie.NEW_RELEASE:
                    thisAmout += each.getDaysRented() * 3;
                    break;
                case Movie.CHILDRENS:
                    thisAmout += 1.5;
                    if (each.getDaysRented() > 3) {
                        thisAmout += (each.getDaysRented() - 3) * 1.5;
                    }
                    break;
            }
            // 加积分
            frequentRenterPoints++;
            //
            if ((each.get_movie().getPriceCode() == Movie.NEW_RELEASE) && each.getDaysRented() > 1) {
                frequentRenterPoints++;
            }
            result += " " + each.get_movie().getTitle() + "\t" + String.valueOf(thisAmout) + "\n";
            totalAmount += thisAmout;
        }
        // footer lines
        result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
        result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";
        return result;

    }
}

Movie 类

package char1.version01;

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 arg) {
        _priceCode = arg;
    }

    public String getTitle() {
        return _title;
    }

}

Rental 类

package char1.version01;

public class Rental {
    private  Movie _movie;
    private  int _daysRented;

    public Rental(Movie _movie, int _daysRented) {
        this._movie = _movie;
        this._daysRented = _daysRented;
    }

    public Movie get_movie() {
        return _movie;
    }

    public Rental set_movie(Movie _movie) {
        this._movie = _movie;
        return this;
    }

    public int getDaysRented() {
        return _daysRented;
    }

    public Rental setDaysRented(int _daysRented) {
        this._daysRented = _daysRented;
        return this;
    }
}

测试类:

package char1.version01;

public class Test {

    public static void main(String[] args) {
        Customer c = new Customer("zhangs");
        // 常规0 儿童2 新1
        Movie movie0 = new Movie("Love",0);
        Movie movie1 = new Movie("NEW",1);
        Movie movie2 = new Movie("CHILD",2);

        Rental rental1 = new Rental(movie0,4);
        Rental rental2 = new Rental(movie1,5);
        Rental rental3 = new Rental(movie2,6);

        c.addRental(rental1);
        c.addRental(rental2);
        c.addRental(rental3);

        System.out.println(c.getName());
        System.out.println(c.statement());
    }
}


重构后的代码

Customer 类

package char1.version04;

import java.util.Enumeration;
import java.util.Vector;

public class Customer {
    private String _name;
    private Vector _rentals = new Vector<>();

    public Customer(String _name) {
        this._name = _name;
    }

    public void addRental(Rental arg) {
        _rentals.addElement(arg);
    }

    public String getName() {
        return _name;
    }

    public String statement() {
        Enumeration rentals = _rentals.elements();
        String result = "Rental Record for" + getName() + "\n";
        while (rentals.hasMoreElements()) {

            Rental each = (Rental) rentals.nextElement();
            result += " " + each.get_movie().getTitle() + "\t" + each.getCharge() + "\n";
        }
        result += "Amount owed is " + getTotalCharge() + "\n";
        result += "You earned " + getTotalFrequentRenterPoints() + " frequent renter points";
        return result;

    }

    private double getTotalCharge() {
        double result = 0;
        Enumeration rentals = _rentals.elements();
        while (rentals.hasMoreElements()) {
            Rental each = (Rental) rentals.nextElement();
            result += each.getCharge();
        }
        return result;
    }

    private int getTotalFrequentRenterPoints() {
        int result = 0;
        Enumeration rentals = _rentals.elements();
        while (rentals.hasMoreElements()) {
            Rental each = (Rental) rentals.nextElement();
            result += each.getFrequentRenterPoints();
        }
        return result;
    }
}


Movie 类

package char1.version04;

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;
    private Price _price;

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


    public int getPriceCode() {
        return _price.getPriceCode();
    }

    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 String getTitle() {
        return _title;
    }


    double getCharge(int dayRented) {

        return _price.getCharge(dayRented);
    }

    int getFrequentRenterPoints(int daysRented) {

        return _price.getFrequentRenterPoints(daysRented);
    }

}

Price 类

package char1.version04;


abstract class Price {
    abstract int getPriceCode();

    abstract double getCharge(int dayRented);

    int getFrequentRenterPoints(int daysRented) {
        return 1;
    }
}

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;
    }

    int getFrequentRenterPoints(int daysRented) {
        return daysRented > 2 ? 2 : 1;
    }
}


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;
    }
}

Rental 类

package char1.version04;

public class Rental {
    private Movie _movie;
    private int _daysRented;

    public Rental(Movie _movie, int _daysRented) {
        this._movie = _movie;
        this._daysRented = _daysRented;
    }

    public Movie get_movie() {
        return _movie;
    }

    public Rental set_movie(Movie _movie) {
        this._movie = _movie;
        return this;
    }

    public int getDaysRented() {
        return _daysRented;
    }

    public Rental setDaysRented(int _daysRented) {
        this._daysRented = _daysRented;
        return this;
    }

    double getCharge() {

        return _movie.getCharge(_daysRented);
    }

    int getFrequentRenterPoints() {
        return _movie.getFrequentRenterPoints(_daysRented);
    }
}

测试类不用改。

  • 如果你发现自己需要为程序添加一个新特性,而代码结构使你无法很方便地达成目的,那就先重构那个程序,使特性的添加比较容易,然后再添加特性。

  • 重构前,先检查自己是否有一套可靠的测试机制。这些测试必须有自我检验的能力。

  • 重构技术就是以微小的步伐修改程序,如果你犯下错误,很容易便可以发现它。

  • 任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员。
    (把自己的理解嵌入代码中,这样才不会遗忘我曾经理解的东西)

这个例子中用到的重构方法:

  • Extract Method 提取方法
  • Move Method 移动方法
  • Replace Conditional With Polymorphism 用多态替代条件表达式
  • Replace Type Code with State/Strategy 用状态/策略设计模式代替类型代码
  • Replace Temp with Query 用查询替换临时变量
  • ……

你可能感兴趣的:(读书笔记 | 重构第一章第一个案例)