Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 面向对象设计:可扩展和可维护的汽车商店系统_Java_Oop_Design Patterns - Fatal编程技术网

Java 面向对象设计:可扩展和可维护的汽车商店系统

Java 面向对象设计:可扩展和可维护的汽车商店系统,java,oop,design-patterns,Java,Oop,Design Patterns,我昨天接受了一次采访,问了一个问题: 赛车存储系统: 该系统存储玩家可用的汽车信息 两种换档策略:手动/自动 两种燃料:汽油/柴油 设计一个能够生产玩家要求的汽车的系统(如果 玩家想要一辆手动换档并燃用柴油的汽车,你的 系统应提供一个符合要求的汽车实例)。 系统应具有良好的可扩展性和可维护性 我的想法和解决方案: 我的想法是需求包含两个属性:装备和燃料。我计划制作一个包含属性和相应行为的抽象类。考虑到可伸缩性,将有一个界面可移动,其中包含汽车可以做的行为 如果将来添加了任何新属性,可以创建一

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

赛车存储系统:

该系统存储玩家可用的汽车信息

  • 两种换档策略:手动/自动
  • 两种燃料:汽油/柴油
设计一个能够生产玩家要求的汽车的系统(如果 玩家想要一辆手动换档并燃用柴油的汽车,你的 系统应提供一个符合要求的汽车实例)。 系统应具有良好的可扩展性和可维护性

我的想法和解决方案:

我的想法是需求包含两个属性:装备和燃料。我计划制作一个包含属性和相应行为的抽象类。考虑到可伸缩性,将有一个界面
可移动
,其中包含汽车可以做的行为

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

以下是我所做的: 接口包含常规行为,当前仅具有
showSpecs()

public interface Movable {
    public String showSpecs();
}
抽象类包含属性
fuel
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());
    }
}
面试官回答说,我提供的解决方案不可扩展,很难维护,但没有提供细节,所以我仍然对自己犯了哪些错误以及如何改进感到困惑

谁能帮我分享一下你的想法,并指出我应该改进什么


谢谢

我会用两个类回答这个问题,
Car
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
是不可变的,并且还包含表示其内部状态所需的枚举,因此这些属性不能泄漏到上下文/对象之外,因为它们在上下文/对象中是有意义的,所以以后更容易维护

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

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

汽车可以这样构造:

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

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

当他提到可伸缩性和可维护性时,我想他可能期待类似可插拔类的东西。所以我认为这种战略模式可能是意料之中的。如果传输或注入需要执行一些真正的逻辑,我可以假设它们是行为,而不仅仅是状态。因此,这一实现会产生结果

公共接口传输策略{
公共无效传输();
}
公共类AutomaticTransmission实现传输策略{
公共无效传输(){
//在这里做一些真正的逻辑
打印(“自动…”);
}
}
公共类手册变速箱执行变速箱策略{
公共无效传输(){
print(“我们喜欢它…”);//这只是一个非常简单的逻辑示例
}
}
公共接口注入策略{
公开无效注入();
}
公共类柴油喷射实施喷射策略{
公共图书馆{
印刷品(“柴油机”);
}
}
公共级汽油注入实施注入策略{
公共图书馆{
打印(“汽油…”);
}
}
公车{
公共无效生成(传输策略传输,注入策略注入){
//设置其他部分
传输。传输();
//设置其他部分
injection.injection();
//其他部分
}
}
//--------------在某些客户的某个地方--------------------
汽车=新车();
//实际上,要真正实现可配置,请在此处使用工厂方法。
汽车制造(新手动变速器(),新汽油喷射器());

如果这是意料之中的,那么只要使用lambdas或命令模式,它也会被创建。

我可能会向他施压,要求他定义一个比“好”稍微好一点的需求。你在需求方面过于复杂了,因为似乎不需要
可移动
汽车
:只需定义
赛车
类;给它两个字段;给它一个构造函数。定义燃油和汽车字段值的枚举。但是可伸缩性——我很难理解实际需要什么:每次需要实例时都调用构造函数;仅仅调用构造函数似乎是必要和足够的。我不喜欢使用普通的
String
s作为属性。更好地使用枚举(或者其他一些,这取决于这些实例的实际使用方式)。我不太喜欢这些需求,因为它们没有告诉我们如何使用这些实例。这使得设计不仅仅是通用的东西变得困难。也许他们期待工厂模式或战略模式。谁知道…@AndyTurner谢谢Andy的回复。我曾经问过人们期望什么样的可伸缩性,得到的答案是“添加坦克”。我没有提到细节,因为一位面试官看到了源代码,他说这不是他期望的答案。这个问题对我来说很模糊,我问了几个问题,但没有得到明确的回答。我认为它可能是开放的,因为“可伸缩性”和“可维护性”对我来说太宽了。谢谢塔哈的回答,+1!这里的大多数类型都没有意义。传输策略没有逻辑!要求中没有具体说明。感谢@StuPointerException提供答案,这很有帮助,+1!拥有私有字段,然后拥有这些字段的访问器方法有什么意义?一个人不需要广告