面向对象设计:可扩展和易维护的汽车销售系统

huangapple go评论72阅读模式
英文:

Object oriented Design: Scalable and maintainable car store system

问题

我之前的思路和解决方案:

我考虑到需求包含了两个属性:变速器和燃料。我计划创建一个包含这些属性及其对应行为的抽象类。考虑到可扩展性,我会创建一个名为 Movable 的接口,其中包含了车辆可以执行的行为。

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

以下是我已经完成的部分:

一个包含通用行为的接口,目前只有 showSpecs() 方法。

public interface Movable {
    public String showSpecs();
}

一个包含属性 fuelgear 的抽象类。

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());
    }
}

面试官回复说我提供的解决方案不具有可扩展性,难以维护,但没有提供细节,所以我仍然不清楚我犯了什么错误以及如何改进。

有人能帮忙分享一下您的想法,并指出我应该改进什么吗?

谢谢!

英文:

I had an interview yesterday and had asked an OOD question:

> Race-Car Store System:
>
> The system stores information about cars available for players.
>
> - Two types of gear changing strategies: manual/automatic.
> - Two types of fuel: gasoline/diesel.
>
> Design a system that can produce cars requested by players (If the
> player wants a car with manual gear changing and burn diesel, your
> system should provide one instance of the car meets the requirements).
> The system should have good scalability and maintainability.

My thoughts and solution:

My thought is the requirement contains two attributes: gear and fuel. I plan to make an abstract class contains the attributes and corresponding behaviors. Considering scalability would have an interface Movable which contains behaviors what a car can do.

If any new attribute is added in the future, either create a new abstract class contains the new attribute or add the attribute into the existing abstract class, if there's new behaviors are required, I would either create new interface or add the behavior into existing interface.

Here's what I have done:
An interface contains general behaviors, currently has showSpecs() only.

public interface Movable {
    public String showSpecs();
}

An abstract class contains attributes fuel and 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();
}

Now the race car class implementaion:

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();
    }
}

Below is the main class I have:

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());
    }
}

The interviewer replied that the solution I provided is not scalable and hard to maintain but didn't provide details so I am still confused about what mistakes I made and how to improve it.

Can anyone help share your thoughts and point out what am I supposed to improve?

Thanks!

答案1

得分: 1

我会用2个类来回答这个问题,CarCarBuilder

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类中。

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

可以按以下方式构造汽车:

//默认汽车:
Car car = new CarBuilder().build();

//定制汽车:
Car car = new CarBuilder().withFuelType(Car.Fuel.DEISEL).withGearBox(Car.Gears.AUTOMATIC).build();
英文:

I would have answered this question with 2 classes, Car and 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);
   }
}

Scalability and maintainability is achieved by the fact that these are the only 2 classes that need to be changed in the future, should requirements change. Car is immutable and also contains the enums required to represent its internal state, so these attributes can't leak out of the context/object in which they make sense so make it easier to maintain in the future.

The builder class, while basic in its current form, can be extended to accommodate more complex construction requirements without leaking implementation details into the Car class.

The default values are optional, but might make sense.

A car can be constructed as such:

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

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

答案2

得分: 1

我认为他可能在提到可扩展性和可维护性时,是在期望类似可插拔类的东西。所以我认为可能期望了策略模式。如果期望传输或注入执行一些真正的逻辑,我可以将它们视为行为,而不仅仅是状态。因此,结果就是这个实现。

public interface TransmissionPolicy {
   public void transmit();
}

public class AutomaticTransmission implements TransmissionPolicy {
   public void transmit() {
      //在这里执行一些真正的逻辑
      print("automatic...");
   }
}

public class ManualTransmission implements TransmissionPolicy {
   public void transmit() {
      print("we love it..."); //仅为一个真正简单逻辑的示例
   }
}

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) {
       //设置其他部分
       transmission.transmit();
       //设置其他部分
       injection.inject();
       //其他部分
    }
}


//--------------在某些客户端的某个地方--------------------
Car car = new Car();
//实际上,要实现真正的可配置性,在这里使用工厂方法。
car.make(new ManualTransmission(), new GasolineInjection());

如果这是期望的结果,那么仅使用Lambda表达式或命令模式也可以实现。

英文:

I thought that maybe he was expecting something like pluggable classes when he mentioned scalable and maintainable. So I think maybe this strategy pattern was expected. If transmission or injection is expected to do some real logic, I can assume them as behaviors instead of just state. Thus results with this implementation.

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());

If that was expected then with just lambdas or command pattern it would be made also.

huangapple
  • 本文由 发表于 2020年7月25日 04:29:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/63081022.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定