提问者:小点点

面向对象设计:可扩展和可维护的汽车存储系统


我昨天接受了一次采访,问了一个问题:

赛车商店系统:

该系统存储有关可供玩家使用的汽车的信息。

  • 两种换档策略:手动/自动
  • 两种燃料:汽油/柴油

设计一个可以生产玩家要求的汽车的系统(如果玩家想要一辆手动换挡、燃烧柴油的汽车,你的系统应该提供一辆符合要求的汽车实例),系统应该具有良好的可扩展性和可运维性。

我的想法和解决方案:

我的想法是需求包含两个属性:齿轮和燃料。我计划制作一个抽象类包含属性和相应的行为。考虑到可扩展性,将有一个接口Moable,其中包含汽车可以做的行为。

如果将来添加任何新属性,要么创建一个包含新属性的新抽象类,要么将该属性添加到现有的抽象类中,如果需要新的行为,我将创建新接口或将行为添加到现有接口中。

这是我所做的:一个接口包含一般行为,目前只有show Specs()

public interface Movable {
    public String showSpecs();
}

抽象类包含属性< code>fuel和< code>gear

public abstract class Car implements Movable {
    String gear;
    String fuel;

    abstract void setFuel(String fuel);

    abstract String getFuel();

    abstract void setGear(String gear);

    abstract String getGear();
}

现在赛车类实现:

public class RaceCar extends Car {
    public RaceCar(String fuel, String gear) {
        this.fuel = fuel;
        this.gear = gear;
    }

    public void setFuel(String fuel) {
        this.fuel = fuel;
    }

    public String getFuel() {
        return this.fuel;
    }

    public void setGear(String gear) {
        this.gear = gear;
    }

    public String getGear() {
        return this.gear;
    }

    public String showSpecs() {
        StringBuilder sb = new StringBuilder();
        sb.append("Gear:").append(this.gear);
        sb.append("Fuel:").append(this.fuel);
        return sb.toString();
    }
}

以下是我拥有的主要类:

public class Main {
    public static void main(String[] args) {
        System.out.println("get started...");
        Car car = new RaceCar("diseal", "automatic");
        System.out.println(car.showSpecs());
    }
}

面试官回答说,我提供的解决方案不可扩展,难以维护,但没有提供细节,所以我仍然对我犯了什么错误以及如何改进它感到困惑。

有人能帮助分享你的想法并指出我应该改进什么吗?

谢谢!


共2个答案

匿名用户

我会用两个类来回答这个问题,即< code>Car和< code>CarBuilder:

public final class Car {

    private final Fuel fuel;
    private final Gears gears;

    public Car(Fuel fuel, Gears gears) {
        this.fuel = fuel;
        this.gears = gears;
    }

    public Fuel getFuel() {
        return fuel;
    }

    public Gears getGears() {
        return gears;
    }

    enum Fuel {
        GASOLINE,
        DEISEL
    }

    enum Gears {
        AUTOMATIC,
        MANUAL
    }
}

public class CarBuilder {

   //sensible defaults:
   private Car.Fuel fuel = Car.Fuel.GASOLINE;
   private Car.Gears gears = Car.Gears.MANUAL;

   public CarBuilder() {
   }

   public CarBuilder withFuelType(Car.Fuel fuel) {
       this.fuel = fuel;
       return this;
   }

   public CarBuilder withGearBox(Car.Gears gears) {
       this.gears = gears;
       return this;
   }

   public Car build() {
      return new Car(this.fuel, this.gears);
   }
}

Car是不可变的,还包含表示其内部状态所需的枚举,因此这些属性不能从它们有意义的上下文/对象中泄露出去,因此将来更容易维护。

构建器类虽然是当前形式的基本类,但可以扩展以适应更复杂的构造要求,而不会将实现细节泄漏到Car类中。

默认值是可选的,但可能有意义。

汽车可以这样构造:

//Default car:
Car car = new CarBuilder().build();

//Customised car:
Car car = new CarBuilder().withFuelType(Car.Fuel.DEISEL).withGearBox(Car.Gears.AUTOMATIC).build();

匿名用户

我想,当他提到可伸缩和可维护时,他可能期待的是可插入类之类的东西。所以我认为这种策略模式是意料之中的。如果期望传输或注入做一些真正的逻辑,我可以假设它们是行为而不仅仅是状态。因此导致了这种实现。

public interface TransmissionPolicy {
   public void transmit();
}

public class AutomaticTransmission implements TransmissionPolicy {
   public void transmit() {
      //do some real logic here
      print("automatic...");
   }
}

public class ManualTransmission implements TransmissionPolicy {
   public void transmit() {
      print("we love it..."); //just an example of really simple logic
   }
}

public interface InjectionPolicy {
    public void inject();
}

public class DieselInjection implements InjectionPolicy {
    public void inject() {
       print("diesel");
    }
}

public class GasolineInjection implements InjectionPolicy {
    public void inject() {
       print("gasoline...");
    }
}

public class Car {
    public void make(TransmissionPolicy transmission, InjectionPolicy injection) {
       //set other parts
       transmission.transmit();
       //set other parts
       injection.inject();
       //other parts
    }
}


//--------------somewhere in some clients client --------------------
Car car = new Car();
//actually, to be really configurable use a factory method here.
car.make(new ManualTransmission(), new GasolineInjection());

如果这是预期的,那么只有lambdas或命令模式也会被制造出来。