zoukankan      html  css  js  c++  java
  • 重构:第一个案例

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

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

  • 相关阅读:
    转ihone程序内发邮件,发短信,打开链接等
    plist 文件的读写
    转object c语法速成
    转iphone项目之间的引用。
    object c求nsstring 长度和去掉前后空格的方法
    object c runtime中类类型和消息支持检查
    转NSDictionary类使用
    设置UITableview 浮动的 header
    NSString 类型plist转为NSDictionary
    ObjectiveC Unicode 转换成中文
  • 原文地址:https://www.cnblogs.com/zhangweia/p/2737614.html
Copyright © 2011-2022 走看看