• 重构:第一个案例


           在写重构的学习笔记之前,首先我们需要向伟大的软件设计师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;
        }
    
    }

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

  • 相关阅读:
    docker 部署aps.net MVC到windows容器
    docker 搭建私有仓库 harbor
    解决关于:Oracle数据库 插入数据中文乱码 显示问号???
    ionic cordova build android error: commamd failed with exit code eacces
    cordova build android Command failed with exit code EACCES
    Xcode 10 iOS12 "A valid provisioning profile for this executable was not found
    使用remix发布部署 发币 智能合约
    区块链: 编译发布智能合约
    mac 下常用命令备忘录
    JQuery fullCalendar 时间差 排序获取距当前最近的时间。
  • 原文地址:https://www.cnblogs.com/zhangweia/p/2737614.html
Copyright © 2020-2023  润新知