重构:第一个案例

       在写重构的学习笔记之前,首先我们需要向伟大的软件设计师Martin Fowler致敬,是他带给了我们重构的思想,敏捷的思想。

       重构--改善既有代码的设计。意味着对现有运行中的代码进行新的修改、设计。这对很多项目经理来说是不可思议的,因为他们一直奉行的是软件业的一句经典“如果代码可以运行,就不要去修改它”在这条“真理”的引导下,当出现新的功能,新的BUG的时候,后续的程序员总是在原有的基础上修修补补,导致代码越来越庞大,业务逻辑越来越不明了,到最后维护的人员终于看不懂代码逻辑了,程序员开始抓狂了,白头发开始白了,职业病来了,项目死了。曾经在CSDN上流传着这样几个关于代码注释的笑话。1. //这段代码的实现逻辑,作为开发者的我已经不知道为什么这样设计了,请不要试图去理解这段代码并去修改它  2.//如果你试图修改这段代码,但却导致了系统其他地方的BUG,请在下面的计数器上加一,以提醒下一位程序员不要动试图去修改它的念头。

       什么时候我们的代码需要重构了?

        我在看一本UI设计书《写给大家看的设计书》中提到,要学会设计其实很简单,主要是掌握3把斧! a. 你需要知道哪里需要修改   b. 你需要知道该怎么样去修改  c. 实践、动手去修改它。我们学习并利用重构也是一样,首先你的知道代码中的坏味道,其实你的知道怎样去掉这些坏味道,最后动手去修改它。

         首先我们通过一个简单的例子来给大家分享重构的过程和乐趣。题目是这样的:这是一个影片出租店德程序,计算每一位顾客的消费金额并打印详单。操作者告诉程序,顾客租了那些影片,租期多长,程序根据租期多长以及影片的类型算出费用。影片分为三类:普通片、儿童片、新片。除了计算费用外,还要为顾客计算积分,不同类型的积分不同。

        先看一个不优秀的代码设计: 依据题意,我们定义3个类Customer(顾客)  Rental(租赁)  Movice(电影)

image  image image

Customer  类

   1:  public class Customer {
   2:      
   3:      /** 顾客的姓名 **/
   4:      private String name;
   5:      
   6:      public String getName() {
   7:          return name;
   8:      }
   9:   
  10:      /** 租赁的所有影片和租期 **/
  11:      private List rentals = new ArrayList();
  12:      
  13:      public Customer(String _name){
  14:          name = _name;
  15:      }
  16:      
  17:      /** 添加租赁影片的租赁关系 **/
  18:      public void addMovice(Rental _rental){
  19:          rentals.add(_rental);
  20:      }
  21:      
  22:      /** 生成账单 **/
  23:      public void createBill(){
  24:          
  25:          double totalAmount = 0;
  26:          int renterPoint = 0;
  27:          String billInfo = "";
  28:          
  29:          for (Rental _rental : rentals) {
  30:              double thisAmount = 0;
  31:              int thisPoint = 0;
  32:              int type = _rental.getMovice().getType();
  33:              
  34:              switch (type) {
  35:              case Movice.CHILDREN:
  36:                  thisAmount += 2;
  37:                  if(_rental.getDaysRental() > 2){
  38:                      thisAmount += (_rental.getDaysRental() -2) * 1.5;
  39:                  }
  40:                  break;
  41:              case Movice.NEW:
  42:                  thisAmount += _rental.getDaysRental() * 3;
  43:                  break;
  44:              case Movice.NORMAL:
  45:                  thisAmount += 1.5;
  46:                  if(_rental.getDaysRental() > 3){
  47:                      thisAmount += (_rental.getDaysRental() - 3) * 1.5;
  48:                  }
  49:                  break;
  50:              default:
  51:                  break;
  52:              }
  53:              
  54:              thisPoint ++;
  55:              if(type == Movice.NEW && _rental.getDaysRental() > 1){
  56:                  thisPoint ++;
  57:              }
  58:              
  59:              totalAmount += thisAmount;
  60:              renterPoint += thisPoint;
  61:              billInfo += "书名:" +  _rental.getMovice().getName() + "/t" +
  62:                         "价格:" + thisAmount + "/t" + 
  63:                         "积分:" + thisPoint + "/t" + 
  64:                         "天数:" + _rental.getDaysRental() + "/n";
  65:          }
  66:          
  67:          billInfo += "本次总价:" + totalAmount  + "/n" +
  68:                      "本次积分:" + renterPoint;
  69:          
  70:          System.out.println(billInfo);
  71:      }
  72:      
  73:  }

Rental 类

public class Rental {



    /** 租赁的影片 **/

    private Movice movice;

    

    /** 影片的租期 **/

    private int daysRental;

    

    public Rental(Movice _movice,int _daysRental){

        movice = _movice;

        daysRental = _daysRental;

    }

    

    public Movice getMovice() {

        return movice;

    }



    public int getDaysRental() {

        return daysRental;

    }

}
Movic类
public class Movice {



    public static final int NORMAL = 0;

    public static final int CHILDREN = 1;

    public static final int NEW = 2;



    /** 影片的名称 **/

    private String name;

    

    /** 影片的类型**/

    private int type;

    

    public String getName() {

        return name;

    }



    public int getType() {

        return type;

    }



    public Movice(int _type,String _name) {

        name = _name;

        type = _type;

    }

}

朋友们,从上面的代码,你们找到了那些代码的坏味道了?

     1.  Duplicated Code (重复代码):   单我需要创建另外一种账单的打印方式:比如按照XML的格式打印时候,我需要另外写一个函数,然后重复前面获取租赁电影的价钱和积分。

     2. Long Method (过长的方法)  :  Customer类的createBill 功能不单一,方法过长

     3. Customer类过多的魔鬼数字和字符,导致后续的字符和参数的替换不方便

     4. Switch Statements (Switch 惊悚现身): Customer通过Switch来判断影片的类型,随着影片的类型增多,Switch的判断必然增多

     5. 发散式变化 :单我的影片价格调整,积分调整的时候,我需要在Customer生成不同账单的函数中去修改。

     6. 依赖情节 : 这是一种“讲数据和对数据的操作行为包装在一起的技术”,有一种经典的气味是:函数对某个类的兴趣高过对自己所处的类的兴趣。

      7. 语法错误 : 代码语法的漏洞

如果你能发现以上的代码坏味道,甚至更多,那恭喜你,你已经开始进入了重构的大门。接下来我们通过重构来一步步优化代码。请记住:重构代码讲究一小步一小步的修改,测试。不要一开始就对整个结构进行调整,修改。

A. 通过分析代码的坏味道,我们发现第3点:魔鬼数字是最好修改的。替换Customer类中的魔鬼数字得到新的Customer类为:红色部分是我们添加的常量定义,替换到魔鬼数字和字符

   1:  public class Customer01 {
   2:      private String name;
 3:     private static final String BOOKNAME_STRING = "书名:";
 4:     private static final String PRICE_STRING = "价格:";
 5:     private static final String POINT_STRING = "积分:";
 6:     private static final String DAY_STRING = "天数";
 7:     private static final String TOTLEAMOUNT_STRING = "总价格:";
 8:     private static final String TOTLEPOINT_STRING = "总积分";
 9:     private static final String CHAT_T_STRING = "/t";
 10:     private static final String CHAT_N_STRING = "/n";
 11:     
 12:     private static final int MOVICE_CHILDREN_PRICE = 2;
           /** 儿童片租赁后可以使用的天数 **/
 13:     private static final int MOVICE_CHILDREN_DEADLINE = 2;
           /** 超过租赁天数后,应付的价钱 **/
 14:     private static final double MOVICE_CHILDREN_DELAY_PRICE = 1.5;
 15:     
 16:     private static final int MOVICE_NEW_PRICE = 3;
 17:     
 18:     private static final double MOVICE_NORMAL_PRICE = 1.5;        
 19:     private static final int MOVICE_NORMAL_DEADLINE = 3;
 20:     private static final double MOVICE_NORMAL_DEALY_PRICE = 1.5;    
 21:     
 22:     private static final int POINT_ADD_MIN_DAY = 1;
  23:      
  24:      public String getName() {
  25:          return name;
  26:      }
  27:   
  28:      private List rentals = new ArrayList();
  29:      
  30:      public Customer01(String _name){
  31:          name = _name;
  32:      }
  33:      
  34:      public void addMovice(Rental _rental){
  35:          rentals.add(_rental);
  36:      }
  37:      
  38:      
  39:      public void createBill(){
  40:          
  41:          double totalAmount = 0;
  42:          int renterPoint = 0;
  43:          StringBuffer billInfo = new StringBuffer();
  44:          
  45:          for (Rental _rental : rentals) {
  46:              double thisAmount = 0;
  47:              int thisPoint = 0;
  48:              int type = _rental.getMovice().getType();
  49:              
  50:              switch (type) {
  51:              case Movice.CHILDREN:
  52:                  thisAmount += MOVICE_CHILDREN_PRICE;
  53:                  if(_rental.getDaysRental() > MOVICE_CHILDREN_DEADLINE){
  54:                      thisAmount += (_rental.getDaysRental() - MOVICE_CHILDREN_DEADLINE) * MOVICE_CHILDREN_DELAY_PRICE;
  55:                  }
  56:                  break;
  57:              case Movice.NEW:
  58:                  thisAmount += _rental.getDaysRental() * MOVICE_NEW_PRICE;
  59:                  break;
  60:              case Movice.NORMAL:
  61:                  thisAmount += MOVICE_NORMAL_PRICE;
  62:                  if(_rental.getDaysRental() > MOVICE_NORMAL_DEADLINE){
  63:                      thisAmount += (_rental.getDaysRental() - MOVICE_NORMAL_DEADLINE) * MOVICE_NORMAL_DEALY_PRICE;
  64:                  }
  65:                  break;
  66:              default:
  67:                  break;
  68:              }
  69:              
  70:              thisPoint ++;
  71:              if(type == Movice.NEW && _rental.getDaysRental() > POINT_ADD_MIN_DAY){
  72:                  thisPoint ++;
  73:              }
  74:              
  75:              totalAmount += thisAmount;
  76:              renterPoint += thisPoint;
  77:              
  78:              billInfo.append(BOOKNAME_STRING +  _rental.getMovice().getName() + CHAT_T_STRING);
  79:              billInfo.append(PRICE_STRING + thisAmount + CHAT_T_STRING);
  80:              billInfo.append(POINT_STRING + thisPoint + CHAT_T_STRING);
  81:              billInfo.append(DAY_STRING + _rental.getDaysRental() + CHAT_N_STRING);
  82:              
  83:          }
  84:          
  85:          billInfo.append(TOTLEAMOUNT_STRING + totalAmount + CHAT_N_STRING);
  86:          billInfo.append(TOTLEPOINT_STRING + renterPoint + CHAT_N_STRING);        
  87:          System.out.println(billInfo);
  88:      }
  89:  }

   

B. 过长的方法:我们发现Customer类的createBill()方法过长,通过分析该方法后,我们发现该方法主要做了以下几件事情:1. 依次获得单个租赁碟片的价格 2. 依次获得单个碟片的积分 3. 按规程生成账单 因此我们通过抽取业务逻辑形成方法的方式修改Customer类的createBill()方法,同时我们发现String使用的错误,当添加多个字符串的时候,需要使用StringBuffer。结果如下:红色部分为修改的代码

   1:  public class Customer02 {
   2:      private String name;
   3:      private static final String BOOKNAME_STRING = "书名:";
   4:      private static final String PRICE_STRING = "价格:";
   5:      private static final String POINT_STRING = "积分:";
   6:      private static final String DAY_STRING = "天数";
   7:      private static final String TOTLEAMOUNT_STRING = "总价格:";
   8:      private static final String TOTLEPOINT_STRING = "总积分";
   9:      private static final String CHAT_T_STRING = "/t";
  10:      private static final String CHAT_N_STRING = "/n";
  11:      
  12:      private static final int MOVICE_CHILDREN_PRICE = 2;
  13:      private static final int MOVICE_CHILDREN_DEADLINE = 2;
  14:      private static final double MOVICE_CHILDREN_DELAY_PRICE = 1.5;
  15:      
  16:      private static final int MOVICE_NEW_PRICE = 3;
  17:      
  18:      private static final double MOVICE_NORMAL_PRICE = 1.5;        
  19:      private static final int MOVICE_NORMAL_DEADLINE = 3;
  20:      private static final double MOVICE_NORMAL_DEALY_PRICE = 1.5;    
  21:      
  22:      private static final int POINT_ADD_MIN_DAY = 1;
  23:      
  24:      public String getName() {
  25:          return name;
  26:      }
  27:   
  28:      private List rentals = new ArrayList();
  29:      
  30:      public Customer02(String _name){
  31:          name = _name;
  32:      }
  33:      
  34:      public void addMovice(Rental _rental){
  35:          rentals.add(_rental);
  36:      }
  37:      
  38:      /**
  39:       * <获得用户租赁的碟片的价格和积分,生成账单>
  40:       * <1. 获得单个租赁碟片的价格  >
  41:       * <2. 获得单个碟片的积分 >
  42:       * <3. 按规程生成账单>
  43:       */    
  44:   
  45:  private StringBuffer billInfo = new StringBuffer();
  46:      
  47:  public void createBill(){
 48:         
 49:         double totalAmount = 0;
 50:         int renterPoint = 0;
 51:         
 52:         
 53:         for (Rental _rental : rentals) {
 54:                     
 55:             totalAmount += getRentalPrice(_rental);
 56:             renterPoint += getRentalPoint(_rental);;            
 57:             createSingleBill(_rental);            
 58:         }
 59:         
 60:         addStatistics(totalAmount,renterPoint);        
 61:         
 62: }
 63:     
 64:     private double getRentalPrice(Rental _rental){
 65:         int type = _rental.getMovice().getType();
 66:         double thisAmount = 0;
 67:         
 68:         switch (type) {
 69:         case Movice.CHILDREN:
 70:             thisAmount += MOVICE_CHILDREN_PRICE;
 71:             if(_rental.getDaysRental() > MOVICE_CHILDREN_DEADLINE){
 72:                 thisAmount += (_rental.getDaysRental() - MOVICE_CHILDREN_DEADLINE) * MOVICE_CHILDREN_DELAY_PRICE;
 73:             }
 74:             break;
 75:         case Movice.NEW:
 76:             thisAmount += _rental.getDaysRental() * MOVICE_NEW_PRICE;
 77:             break;
 78:         case Movice.NORMAL:
 79:             thisAmount += MOVICE_NORMAL_PRICE;
 80:             if(_rental.getDaysRental() > MOVICE_NORMAL_DEADLINE){
 81:                 thisAmount += (_rental.getDaysRental() - MOVICE_NORMAL_DEADLINE) * MOVICE_NORMAL_DEALY_PRICE;
 82:             }
 83:             break;
 84:         default:
 85:             break;
 86:         }
 87:         return thisAmount;
 88:     }
 89:     
 90:     private int getRentalPoint(Rental _rental){
 91:         int thisPoint = 0;
 92:         thisPoint ++;
 93:         if(_rental.getMovice().getType() == Movice.NEW && _rental.getDaysRental() > POINT_ADD_MIN_DAY){
 94:             thisPoint ++;
 95:         }
 96:         return thisPoint;
 97:     }
 98:  
 99:     private void createSingleBill(Rental _rental){
 100:         billInfo.append(BOOKNAME_STRING +  _rental.getMovice().getName() + CHAT_T_STRING);
 101:         billInfo.append(PRICE_STRING + getRentalPrice(_rental) + CHAT_T_STRING);
 102:         billInfo.append(POINT_STRING + getRentalPoint(_rental) + CHAT_T_STRING);
 103:         billInfo.append(DAY_STRING + _rental.getDaysRental() + CHAT_N_STRING);
 104:     }
 105:     
 106:     private void addStatistics(double totalAmount,int renterPoint){
 107:         billInfo.append(TOTLEAMOUNT_STRING + totalAmount + CHAT_N_STRING);
 108:         billInfo.append(TOTLEPOINT_STRING + renterPoint + CHAT_N_STRING);
 109:         System.out.println(billInfo);
 110:     }
 111:   
 112:  }

C.  依赖情节,我们发现getRentalPrice(),getRentalPoint()都和租赁有关,和顾客没有关系,因为我们需要把其移到对应的类中去,修改为Customer类以及Rental类为:

public class Customer03 {

    private String name;

    private static final String BOOKNAME_STRING = "书名:";

    private static final String PRICE_STRING = "价格:";

    private static final String POINT_STRING = "积分:";

    private static final String DAY_STRING = "天数";

    private static final String TOTLEAMOUNT_STRING = "总价格:";

    private static final String TOTLEPOINT_STRING = "总积分";

    private static final String CHAT_T_STRING = "/t";

    private static final String CHAT_N_STRING = "/n";

    



    

    public String getName() {

        return name;

    }



    private List rentals = new ArrayList();

    

    public Customer03(String _name){

        name = _name;

    }

    

    public void addMovice(Rental03 _rental03){

        rentals.add(_rental03);

    }

    

    /**

     * <获得用户租赁的碟片的价格和积分,生成账单>

     * <1. 获得单个租赁碟片的价格  >

     * <2. 获得单个碟片的积分 >

     * <3. 按规程生成账单>

     */    



private StringBuffer billInfo = new StringBuffer();

    

public void createBill(){

        

        double totalAmount = 0;

        int renterPoint = 0;

                

        for (Rental03 _rental : rentals) {

                    

            totalAmount += _rental.getRentalPrice();

            renterPoint += _rental.getRentalPoint();;            

            createSingleBill(_rental);            

        }

        

        addStatistics(totalAmount,renterPoint);        

        

    }

    

    private void createSingleBill(Rental03 _rental){

        billInfo.append(BOOKNAME_STRING +  _rental.getMovice().getName() + CHAT_T_STRING);

        billInfo.append(PRICE_STRING + _rental.getRentalPrice() + CHAT_T_STRING);

        billInfo.append(POINT_STRING + _rental.getRentalPoint() + CHAT_T_STRING);

        billInfo.append(DAY_STRING + _rental.getDaysRental() + CHAT_N_STRING);

    }

    

    private void addStatistics(double totalAmount,int renterPoint){

        billInfo.append(TOTLEAMOUNT_STRING + totalAmount + CHAT_N_STRING);

        billInfo.append(TOTLEPOINT_STRING + renterPoint + CHAT_N_STRING);

        System.out.println(billInfo);

    }



}

Rental 类修改:

public class Rental03 {



    private Movice movice;

    private int daysRental;

    

    private static final int MOVICE_CHILDREN_PRICE = 2;

    private static final int MOVICE_CHILDREN_DEADLINE = 2;

    private static final double MOVICE_CHILDREN_DELAY_PRICE = 1.5;

    

    private static final int MOVICE_NEW_PRICE = 3;

    

    private static final double MOVICE_NORMAL_PRICE = 1.5;        

    private static final int MOVICE_NORMAL_DEADLINE = 3;

    private static final double MOVICE_NORMAL_DEALY_PRICE = 1.5;    

    

    private static final int POINT_ADD_MIN_DAY = 1;

    

    public Rental03(Movice _movice,int _daysRental){

        movice = _movice;

        daysRental = _daysRental;

    }

    

    public Movice getMovice() {

        return movice;

    }



    public int getDaysRental() {

        return daysRental;

    }
    public double getRentalPrice(){

        int type = getMovice().getType();

        double thisAmount = 0;

        

        switch (type) {

        case Movice.CHILDREN:

            thisAmount += MOVICE_CHILDREN_PRICE;

            if(getDaysRental() > MOVICE_CHILDREN_DEADLINE){

                thisAmount += (getDaysRental() - MOVICE_CHILDREN_DEADLINE) * MOVICE_CHILDREN_DELAY_PRICE;

            }

            break;

        case Movice.NEW:

            thisAmount += getDaysRental() * MOVICE_NEW_PRICE;

            break;

        case Movice.NORMAL:

            thisAmount += MOVICE_NORMAL_PRICE;

            if(getDaysRental() > MOVICE_NORMAL_DEADLINE){

                thisAmount += (getDaysRental() - MOVICE_NORMAL_DEADLINE) * MOVICE_NORMAL_DEALY_PRICE;

            }

            break;

        default:

            break;

        }

        return thisAmount;

    }

    

    public int getRentalPoint(){

        int thisPoint = 0;

        thisPoint ++;

        if(getMovice().getType() == Movice.NEW && getDaysRental() > POINT_ADD_MIN_DAY){

            thisPoint ++;

        }

        return thisPoint;

    }

}

D. 我们发现Rental类的getRentalPrice() 跟影片的类型和影片的价格有关,因此其更应该放到Movice类里面去,修改Rental类和Movice类为。通过迁移,租赁价格的修改都集中到了Movice类中。

public class Rental05 {



    private Movice05 movice;

    private int daysRental;





    

    private static final int POINT_ADD_MIN_DAY = 1;

    

    public Rental05(Movice05 _movice,int _daysRental){

        movice = _movice;

        daysRental = _daysRental;

    }

    

    public Movice05 getMovice() {

        return movice;

    }



    public int getDaysRental() {

        return daysRental;

    }

    

     public double getRentalPrice(){        

        return getMovice().getTotalPrice(getDaysRental());

    }

    

    public int getRentalPoint(){

        int thisPoint = 0;

        thisPoint ++;

        if(getMovice().getType() == Movice.NEW && getDaysRental() > POINT_ADD_MIN_DAY){

            thisPoint ++;

        }

        return thisPoint;

    }

}

Movice类

public class Movice05 {



    public static final int NORMAL = 0;

    public static final int CHILDREN = 1;

    public static final int NEW = 2;



    private static final int MOVICE_CHILDREN_PRICE = 2;

    private static final int MOVICE_NEW_PRICE = 3;    

    private static final double MOVICE_NORMAL_PRICE = 1.5;

    

    private static final int MOVICE_CHILDREN_DEADLINE = 2;

    private static final double MOVICE_CHILDREN_DELAY_PRICE = 1.5;    

    

    private static final int MOVICE_NORMAL_DEADLINE = 3;

    private static final double MOVICE_NORMAL_DEALY_PRICE = 1.5;

    

    private String name = "";

    private int type = 0;

    private int thisAmount = 0;

    

    public int getTotalPrice(int daysRental) {

        if(getType() == CHILDREN){

            thisAmount += MOVICE_CHILDREN_PRICE;

            if(daysRental > MOVICE_CHILDREN_DEADLINE){

                thisAmount += (daysRental - MOVICE_CHILDREN_DEADLINE) * MOVICE_CHILDREN_DELAY_PRICE;

            }

        }else if(getType() == NORMAL){

            thisAmount += MOVICE_NORMAL_PRICE ;

            if(daysRental > MOVICE_NORMAL_DEADLINE){

                thisAmount += (daysRental - MOVICE_NORMAL_DEADLINE) * MOVICE_NORMAL_DEALY_PRICE;

            }

        }else if(getType() == NEW){

            thisAmount += MOVICE_NEW_PRICE * daysRental;

        }

        return thisAmount;

    }



    public String getName() {

        return name;

    }



    public int getType() {

        return type;

    }



    public Movice05(int _type,String _name) {

        name = _name;

        type = _type;

    }

}

D. 到这里,我们发现惊悚的Switch类还没有处理掉。通过我们分析Switch主要是对不同的电影类型进行不同的处理,因此我们可以考虑抽取一个超级的电影类,不同的电影类型继承该类来解决Switch的问题。

public abstract class MoviceSuper {

    

    /** 影片的价格 **/

    public int price ;

    

    /** 影片的积分 **/

    public int point;

    

    /** 一步影片可以租多少天 **/

    public int rentalFreeDays;

    

    /** 超过租期了付的价钱**/

    public double delayDayPrice ;

    

    /** 电影的名称**/

    public String name;

    

    public String getName() {

        return name;

    }



    public MoviceSuper(String _name){

        name = _name;

    }

    

    /**

     * <获得租赁影片的价钱>

     * <总价格 = 单个影片的价格 + 延迟时每天应付的价格>

     * 

     * @param daysRental :租赁的天数

     * @return

     */

    public abstract double getRentalPrice(int daysRental);

    

    public abstract int getRentalPoint();

}

package com.chapter01;



public class MoviceChild extends MoviceSuper{



    private static final int POINT = 1;

    private static final int PRICE = 2;

    private static final int DEADLINE = 2;

    private static final double DELAY_PRICE = 1.5;

    

    public MoviceChild(String name) {

        super(name);

        // TODO Auto-generated constructor stub

        price = PRICE;

        

        rentalFreeDays = DEADLINE;

        

        delayDayPrice = DELAY_PRICE;

        

        point = POINT;

    }



    @Override

    public int getRentalPoint() {

        // TODO Auto-generated method stub

        return point;

    }



    @Override

    public double getRentalPrice(int daysRental) {

        // TODO Auto-generated method stub

        double thisAmount = 0;

        thisAmount += price;

        if(daysRental > rentalFreeDays){

            thisAmount += (daysRental - rentalFreeDays) * delayDayPrice;

        }

        return thisAmount;

    }



}
package com.chapter01;



public class MoviceNew extends MoviceSuper{



    private static final int PRICE = 3;    

    

    private static final int POINT = 2;

    

    public MoviceNew(String name) {

        super(name);

        

        price = PRICE;

        

        delayDayPrice = PRICE;

        

        rentalFreeDays = 0;

        

        point = POINT;

    }



    @Override

    public int getRentalPoint() {

        // TODO Auto-generated method stub

        return point;

    }



    @Override

    public double getRentalPrice(int daysRental) {

        // TODO Auto-generated method stub

        

        return daysRental * price;

    }



}
package com.chapter01;



public class MoviceNormal extends MoviceSuper{



    private static final int PRICE = 2;

    

    private static final int DEADLINE = 3;

    

    private static final double DEALY_PRICE = 1.5;

    

    private static final int POINT = 1;

    

    public MoviceNormal(String name) {

        super(name);

        

        price = PRICE;

        

        delayDayPrice = DEALY_PRICE;

        

        rentalFreeDays = DEADLINE;

        

        point = POINT;

    }



    @Override

    public int getRentalPoint() {

        // TODO Auto-generated method stub

        return point;

    }



    @Override

    public double getRentalPrice(int daysRental) {

        double thisAmount = 0;

        thisAmount += price ;

        if(daysRental > price){

            thisAmount += (daysRental - price) * delayDayPrice;

        }

        return thisAmount;

    }



}

通过我们一小步一小步的重构,让我们的程序更加优美,适应变化性更强。

你可能感兴趣的:(重构)