【问题标题】:improvement of program through inheritance通过继承改进程序
【发布时间】:2016-11-19 01:51:10
【问题描述】:

我编写了一个程序,它从文件中读取信息并将信息存储在我自己制作的集合类中。我的程序运行良好,但是我想知道是否可以做些什么来改进我的程序并通过继承和其他 Java 功能防止重复代码。这是我的课。我添加了 cmets 来解释每个类的作用。

abstract class Order { //superclass
 private int quantity; //instance variables

 public Order(int quantity) { //constructor
  this.quantity = quantity;
}

 public int getQuantity() { // instance method
  return quantity;
}

 public abstract double totalPrice();

 public String toString() {
  return "quantity: " + quantity;
}

} //super Class Order

class Coffee extends Order { //subclass 
 private String size; //instance variables

 public Coffee (int quantity, String size) { //constructor
  super(quantity);
  this.size = size;
}

 public double totalPrice() { //instance method to calculate price for the item
  double priceSmall = 1.39;
  double priceMed = 1.69;
  double priceLar = 1.99;
  double total = 0;

  if (size.equals("small")) { 
   total = priceSmall * getQuantity();
  } else {
   if (size.equals("medium")) {
    total = priceMed * getQuantity();
  } else {
    if(size.equals("large")) {
      total = priceLar * getQuantity();
    }
  }
}
  return total;
} //totalPrice


public String toString() {
 return "Coffee ("+ size + "): " + super.toString() ;
}

} //coffee sub-class

class Donuts extends Order { //sub-class
 private double price; //instance variables
 private String flavour;

public Donuts(int quantity, double price, String flavour) { //constructor
 super(quantity);
 this.price = price;
 this.flavour = flavour;
}


public double totalPrice() { //instance method to calculate price
 double total = 0;
 int quantity = getQuantity();

 if(quantity < 6) {
   total = (price * quantity);
   double tax = 0.07 * total;
   total += tax;
 } else {
   total = price * quantity;
 }
 return total;
} //totalPrice

public String toString() {
 return "Donuts("+ flavour + "): " + super.toString() + ", price: " + price;
}

} //class Donuts

 class Sandwich extends Order { //Sub-class
  private double price; // instance variables
  private String filling;
  private String bread;

 // constructor
  public Sandwich (int quantity, double price, String filling, String bread)   {
   super(quantity);
   this.price = price;
  this.filling = filling;
  this.bread = bread;
 }

  public double totalPrice() { //instance method
   double total = 0;
   int quantity = getQuantity();

   total = (price * quantity);
   double tax = 0.07 * total;
   total += tax;

   return total;
  } //totalPrice


  public String toString() {
   return "Sandwich ("+ filling + ") ( " + bread + "): "+ super.toString() + 
  ", price: " + price ;
 }

} // Sandwich class

  class Pop extends Order { //sub-class
   private String size;
   private String brand;

   public Pop(int quantity, String size, String brand) { //constructor
    super(quantity);
    this.size = size;
    this.brand = brand;
   }

   public double totalPrice() { //instance method
    double priceSmall = 1.79;
    double priceMed = 2.09;
    double priceLar = 2.49;
    double total = 0;

  if (size.equals("small")) { 
    total = priceSmall * getQuantity();
 } else {
  if (size.equals("medium")) {
    total = priceMed * getQuantity();
  } else {
    if(size.equals("large")) {
      total = priceLar * getQuantity();
    }
  }
}
 return total;
} //totalPrice

 public String toString() {
  return "Pop ("+ brand + ") (" + size + "): " + super.toString() ;
 }
} // class Pop

有四种产品,即咖啡、甜甜圈、三明治和汽水,我正在存储它们的订单,然后打印它们的总价。

我正在阅读的文件示例如下:

咖啡,3,中等

甜甜圈,7,0.89,巧克力

流行,5,大,Splat!可乐

三明治、1、3.89、神秘肉、37粒全麦

我的程序有点长,但我希望 SO 社区可以帮助我改进我的程序。我希望改进的是,我有totalPrice() 方法,我在每个类中都覆盖了它。但是如果仔细观察coffee 类和pop 类在属性上有些相似。 donut 类和 sandwiches 类也是如此。有什么办法可以防止这些类中的代码重复吗? 如果需要我愿意提供的解释,我希望一切都是不言自明的。

【问题讨论】:

    标签: java oop inheritance abstract-class code-duplication


    【解决方案1】:

    在 OO 系统中有时会过度使用继承。一般来说,组合是一种更好的技术 - 请阅读“继承与组合”。

    对于这种情况,您尝试将商店中的库存商品视为订单很奇怪,而且可能没有帮助。订单有与之关联的商品,但商品本身并不是真正的订单。

    在这方面,您可以拥有一个具有名称和价格的类 StoreItem。您还可以允许该类具有影响价格的可选大小属性。因此,对于商店商品,您可以调用 item.getName() 和 item.getPrice()。当您构建商店商品时,您可以只使用名称和价格来初始化它,或者使用名称、尺寸和价格来初始化那些具有尺寸的商品。

    然后您可以只拥有一个 Store 类,并且该商店有一个物品清单 - 一个可用物品的列表。为项目列表制作订单,您的成本计算可能在订单类中发生一次。它只是遍历它的项目列表并询问每个项目的价格。

    使用此解决方案,您最终会在某个地方使用 Item、Store、Order 和一个主程序,但要将您的问题扩展到包括更多项目,您根本不需要添加任何新类。

    【讨论】:

    • 从你的回答来看,你有点暗示我没有任何主要的代码重复?我明白你对StoreItem 课程的看法。
    • 嗯,不,复制与其说是可扩展性问题,不如说是可扩展性问题——要在解决方案中添加项目,您需要添加类。但是,对于此解决方案的尺寸如何影响价格,您确实有重复,但可以通过仅使用单个 StoreItem 类来消除。
    【解决方案2】:

    虽然您的程序也很好,但它们也可以根据规范为您的问题提供多种解决方案。

    您指定要避免重复的第一件事,我看到重复,特别是在方法 totalPrice() 中,如果您必须对其添加一些更改,这可能会导致问题,您将影响所有类。例如,您想在总价中添加 1% 的折扣。考虑到这一点,我建议进行如下更改:

    //add utility interface which can be used by all Concrete product classes
    interface PriceCalculator {
    
        static double totalPrice(Map<String, Double> priceMap,String size, int quantity) throws Exception{
            Double rate=priceMap.get(size);
            if(rate==null){
                throw new Exception("something really bad happened.Missing price");
            }
    
            return (rate * quantity);
        }
    
    }
    
    class Coffee extends Order  { //subclass 
        private String size; //instance variables
        private Map<String, Double> priceMap=new HashMap<>();
    
        public Coffee (int quantity, String size) { //constructor
            super(quantity);
            this.size = size;
            priceMap.put("priceSmall", 1.39);
            priceMap.put("priceMed", 1.69);
            priceMap.put("priceLar", 1.39);
        }
    
        @Override
        public double totalPrice() { //instance method to calculate price for the item
            try {
                return PriceCalculator.totalPrice(priceMap, size, getQuantity());
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        } //totalPrice
    
    
        public String toString() {
            return "Coffee ("+ size + "): " + super.toString() ;
        }
    
    } //coffee sub-class
    

    如果需要,另一个规范是使定价不硬编码。您可以通过使用 Properties 类从外部文件加载大小价格的键值对来做到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 2011-12-28
      • 2016-04-22
      • 1970-01-01
      相关资源
      最近更新 更多