Java 通过继承改进程序

Java 通过继承改进程序,java,oop,inheritance,abstract-class,code-duplication,Java,Oop,Inheritance,Abstract Class,Code Duplication,我已经编写了一个程序,从文件中读取信息并将其存储在我自己制作的集合类中。我的程序运行得很好,但是我想知道是否有什么可以做的来改进我的程序,并通过继承和其他Java特性防止重复代码。这是我的课。我添加了注释来解释每个类的功能 abstract class Order { //superclass private int quantity; //instance variables public Order(int quantity) { //constructor this.quanti

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

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
抽象类顺序{//超类
私有int数量;//实例变量
公共秩序(整数数量){//
这个。数量=数量;
}
public int getQuantity(){//实例方法
退货数量;
}
公开摘要双总价();
公共字符串toString(){
返回“数量:”+数量;
}
}//超类顺序
类Coffee扩展了顺序{//子类
私有字符串大小;//实例变量
公共咖啡(整数数量,字符串大小){//constructor
超级(数量);
这个。大小=大小;
}
public double totalPrice(){//计算项目价格的实例方法
双倍价格小=1.39;
双倍价格MED=1.69;
双倍价格=1.99;
双倍合计=0;
如果(size.equals(“small”){
总计=价格小*获取数量();
}否则{
if(尺寸等于(“中等”)){
总计=价格*获取数量();
}否则{
如果(大小等于(“大”)){
总计=价格*获取数量();
}
}
}
返回总数;
}//总价
公共字符串toString(){
返回“Coffee(“+size+”):+super.toString();
}
}//咖啡小班
类甜甜圈扩展顺序{//子类
private double price;//实例变量
私人串味;
公共甜甜圈(整数数量,双倍价格,串味){//
超级(数量);
这个价格=价格;
这个。味道=味道;
}
public double totalPrice(){//计算价格的实例方法
双倍合计=0;
int quantity=getQuantity();
如果(数量<6){
总计=(价格*数量);
双重税=0.07*总计;
总额+=税金;
}否则{
总价=价格*数量;
}
返回总数;
}//总价
公共字符串toString(){
返回“甜甜圈(“+flavor+”):+super.toString()+”,价格:“+price;
}
}//类甜甜圈
类三明治扩展了顺序{//子类
private double price;//实例变量
私人字符串填充;
私人面包;
//建造师
公共三明治(整数数量、双倍价格、串馅、串面包){
超级(数量);
这个价格=价格;
这个。填充=填充;
这个面包=面包;
}
public double totalPrice(){//实例方法
双倍合计=0;
int quantity=getQuantity();
总计=(价格*数量);
双重税=0.07*总计;
总额+=税金;
返回总数;
}//总价
公共字符串toString(){
返回“三明治(“+filling+”)(+bread+”):+super.toString()+
,价格:“+价格;
}
}//夹心阶层
类Pop扩展了顺序{//子类
私有字符串大小;
自有品牌;
公共Pop(整数数量、字符串大小、字符串品牌){//constructor
超级(数量);
这个。大小=大小;
这个品牌=品牌;
}
public double totalPrice(){//实例方法
双倍价格小=1.79;
双倍价格MED=2.09;
双倍价格=2.49;
双倍合计=0;
如果(size.equals(“small”){
总计=价格小*获取数量();
}否则{
if(尺寸等于(“中等”)){
总计=价格*获取数量();
}否则{
如果(大小等于(“大”)){
总计=价格*获取数量();
}
}
}
返回总数;
}//总价
公共字符串toString(){
返回“Pop(“+brand+”)(+size+”):+super.toString();
}
}//类流行音乐
有四种产品,即咖啡、甜甜圈、三明治和汽水,我正在存储它们的订单,然后打印它们的总价

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

咖啡,3杯,中等

甜甜圈,7,0.89,巧克力

砰,5,大,啪!可乐

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

我的课程有点长,但我希望社区能帮助我改进我的课程。我希望改进的是,我有
totalPrice()
方法,我在每个类中重写该方法。但是如果你仔细观察,
coffee
class和
pop
class在属性上有些相似。
甜甜圈
类和
三明治
类也是如此。有什么方法可以防止这些类中的代码重复?
如果需要解释的话,我希望一切都是不言自明的。继承有时在OO系统中被过度使用。一般来说,组合是一种更好的技术——阅读“继承与组合”

特别是在这种情况下,您试图将商店中的库存商品视为订单,这很奇怪,而且可能没有帮助。订单中有与其关联的项目,但这些项目本身并不是真正的订单

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

然后您就可以有一个Store类,Store有一个物品清单——一个可用物品的列表。订单是为项目列表生成的,您的成本计算可以在order类中进行一次。它只是循环浏览它的商品列表,并询问每个商品的价格


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

尽管您的程序也很好,而且它们可以是基于规范的问题的多个解决方案

您指定要做的第一件事
//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