使用许多子类重构抽象Java类

1 java refactoring abstract-class design-patterns

我正在寻找关于重构这种情况的最佳方法的想法(更好的设计,最小的努力).从以下示例开始抽象类(实际有更多字段,方法和抽象方法):

abstract class Car
{
    private int manufactureYear;
    // ... many more fields that are hard to clone

    public Car(int manYear)
    {
        this.manufactureYear = manYear;
    }

    abstract public Color getColor();
    abstract public int getNumCylinders();
}
Run Code Online (Sandbox Code Playgroud)

有很多子类(比如100)扩展了这个类.这些儿童课程被认为是汽车的"规格".这是两个例子:

class CarOne extends Car
{
    private static Color COLOR = Color.Red;
    private static int CYLINDERS = 4;

    public CarOne(int manYear)
    {
        super(manYear);
    }

    public final Color getColor();
    {
        return COLOR;
    }

    public final int getNumCylinders() 
    {
        return CYLINDERS;
    }
}

class CarOneThousand extends Car
{
    private static Color COLOR = Color.Black;
    private static int CYLINDERS = 6;

    public CarOneThousand(int manYear)
    {
        super(manYear);
    }

    public final Color getColor();
    {
        return COLOR;
    }

    public final int getNumCylinders() 
    {
        return CYLINDERS;
    }
}
Run Code Online (Sandbox Code Playgroud)

在运行时期间,汽车对象被实例化并使用:

CarOne carObject = new CarOne(2009);
carObject.getColor();
carObject.getNumCylinders();
Run Code Online (Sandbox Code Playgroud)

然而,在获得一些外部数据后,我发现汽车被重新粉刷并且引擎发生了变化.汽车的新规格变为:

class ModCar extends Car
{
    private static Color COLOR = Color.Blue; 
    private static int numCylinders = 8;

    public ModCar (int manYear)
    {
        super(manYear);
    }

    public final Color getColor();
    {
        return COLOR;
    }

    public final int getNumCylinders() 
    {
        return numCylinders;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以真的需要将这些规范"应用"到新的,carObject而不需要修改现有的字段manufactureDate.问题是如何最小化这些100多个子类的更改代码(最好不要触及它们),同时能够carObject在运行时更新.

注意我被赋予了这个代码的工作,所以我没有在这个条件下写它开始.

Sin*_*hot 8

根据描述和示例,您不恰当地使用继承.看起来您正在创建许多类,您应该使用单个类和许多对象实例.如果是这样,您也不需要设计模式来解决问题.如果没有进一步澄清问题,这应该足够了:

class Car
{
    private int manufactureYear;
    private Color color;
    private int numCylinders;

    public int getManufactureYear() { return manufactureYear; }
    public void setManufactureYear(int manufactureYear) { this.manufactureYear = manufactureYear; }

    public Color getColor() { return color; }
    public void setColor(Color color) { this.color = color; }

    public int getNumCylinders() { return numCylinders; }
    public void setNumCylinders(int numCylinders) { this.numCylinders = numCylinders; }
}
Run Code Online (Sandbox Code Playgroud)

示例用法:

// make a blue 6-cylinder:
Car blue6 = new Car();
blue6.setColor(BLUE);
blue6.setCylinders(6);

// make a red 4-cylinder:
Car red4 = new Car();
red4.setColor(RED);
red4.setCylinders(4);

// Uh-oh, they painted my red car!
red4.setColor(YELLOW);
Run Code Online (Sandbox Code Playgroud)

如果要最小化更改,可以使用上面重构的Car类,然后清理子类以便它们利用它.就像是:

class CarOne extends Car { // extends my version of Car...

    private static Color COLOR = Color.Red;
    private static int CYLINDERS = 4;

    public CarOne() {
      setColor(COLOR);
      setNumCylinders(CYLINDERS );
    }

    // getters deleted, base class has them now
}
Run Code Online (Sandbox Code Playgroud)

由于实际上有一个基类,我的猜测是99%的代码没有引用具体的汽车类(只有基类),所以你应该能够相当容易地改变事物.当然,很难说没有看到真正的代码.

  • Nit pick:应该是:blue6.setEngine(Engine.V6); 汽缸确实是发动机的一个属性,而不是汽车.有些属性是不可变的,比如`manufactureYear`,并且在创建对象后无法更改.类不应该为这些属性公开setter. (2认同)