使用Java抽象方法避免代码重复

时间:2014-06-19 13:10:44

标签: java abstract-methods

我有一个班级(让他们说车辆)有一个相当多的子类(Car,Bike,..)。每个子类都存储有关子类类型的特定信息(轮胎数量,......)。

我想确保已经强制执行所有这些信息(在编译时)。 所以我不想在子类的构造函数中指定这些数据(因为我可能忘记设置其中的一些)。我可以将这些信息放在Vehicle的构造函数中,但这会使代码混乱很多,因为我有很多这些参数。

public class Vehicle {
  int numberOfTires;

  public Vehicle(int numberOfTires, ...) {
    ...
  }

}

public class Bike {
  public Bike() {
    super(2,...);
    ...
  }

}

我最终得到了完全不可读的构造函数。它还会为每个实例存储此信息,即使它特定于子类。

另一种方法是引入抽象静态getter / setter并将信息存储在子类中。

public class Vehicle {

  ...
  abstract public int getNumberOfTires();

}

public class Bike {

    static int numberofTires = 2;

    ...

    public int getNumberOfTires() {
      return numberOfTires;
  }

}

这看起来更清晰,并且还存储每个子类的信息而不是每个实例,但是子类中会有很多代码重复。现在,所有子类都包含~20个setter / getters,但几乎没有真正的功能。有没有一种清除方法可以避免这种情况?也许使用Factory方法或类似方法?

3 个答案:

答案 0 :(得分:0)

在你的鞋子里,我是这样做的

public abstract class Vehicle {
    public abstract int getNumberOfTires();
}

public class Bike extends Vehicle {

    @Override
    public int getNumberOfTires() {
        return 2;
    }

}

public class Car extends Vehicle {

    @Override
    public int getNumberOfTires() {
        return 4;
    }

}

答案 1 :(得分:0)

在我看来,你在这里谈论的是常数,例如不应该在运行时更改的值。在Java中,常量是具有以下限定符的变量:static final,以及private / public。然后,你不会需要设置器,因为例如Bike除了2个轮子之外什么都不会。

我没有真正看到有很多getter和setter的问题,你的Bike - 类有一组描述它的属性,而且它们都是必需的。如下所示:

public abstract class Vehicle {
    public abstract int numberOfTires();
    public abstract boolean hasEngine();
}

public class Bike extends Vehicle {

    private static final int NUMBER_OF_TIRES = 2;
    private static final boolean HAS_ENGINE = false;

    public int numberOfTires() {
        return NUMBER_OF_TIRES;
    }

    public boolean hasEngine() {
        return HAS_ENGINE;
    }
}

这些变量是您所代表的实体的属性,并且根据面向对象的原则,它们属于该类的成员。

所有域类都有许多变量,在大多数情况下,它们至少需要一个getter,没有办法解决这个问题。尽管如此,保持域类尽可能小是很好的,不一定是关于代码行,它代表的概念。如果域类变大,则将其分解,并且属于一起的组变量是单独的类。然后每个较小的类将具有一个构造函数,其中包含有限数量的变量和实例创建

如果在限制子类中代码量方面的所有重要性,您可以执行类似下面的代码。我不确定我是否会推荐它,而且我不认为我在实践中这样做。

public abstract class VehicleInfo {
    public abstract int numberOfWheels();
}

public class BikeInfo extends VehicleInfo {
    @Override
    public int numberOfWheels() {
        return 2;
    }
}

public class CarInfo extends VehicleInfo {
    @Override
    public int numberOfWheels() {
        return 4;
    }
}

public class Vehicle {
    final VehicleInfo info;
    Vehicle(final VehicleInfo info) {
        this.info = info;
    }

    public int numberOfWheels() {
        return info.numberOfWheels();
    }
}

public class Bike extends Vehicle {

    public Bike() {
        super(new BikeInfo());
    }
}

public class Car extends Vehicle {

    public Car() {
        super(new CarInfo());
    }
}

这样所有的getter都位于超类(以及info-classes)中,子类可以保持干净。

答案 2 :(得分:0)

你应该在Vehicule课程中输入一切常见内容。如果轮胎数量是您所有Vehicule的共同属性,那么它就属于那里。

使用factory pattern,您可以避免在每次需要Bike Vehicule类的实例时编写,因为工厂会这样做。这意味着设置Bike参数的代码写在一个地方BikeFactory类。

这会使创建Bike的行看起来像

Bike yourBike = BikeFactory.getInstance().create();

而不是

Bike yourBike = new Bike(numberOfTires, ... );

工厂将拥有一个看起来像上面一行的行或者一堆调用setter的行。我建议你使用setter,只使用一个没有参数的new Bike()构造函数。

工厂,方法和工厂作为单身人士的命名仅作为示例,可以在您的应用程序中实现。

如前所述,您还可以使用另一个类作为参数,但这只会将您的参数设置的麻烦移到其他地方。