美文网首页
读书笔记 | 重构第一章第一个案例

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

作者: 车湾里 | 来源:发表于2020-08-23 16:07 被阅读0次

    原始代码:

    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 用查询替换临时变量
    • ……

    相关文章

      网友评论

          本文标题:读书笔记 | 重构第一章第一个案例

          本文链接:https://www.haomeiwen.com/subject/oczijktx.html