当前位置: 首页 > 知识库问答 >
问题:

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

岳均
2023-03-14

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

赛车商店系统:

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

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

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

我的想法和解决方案:

我的想法是需求包含两个属性:齿轮和燃料。我计划制作一个抽象类包含属性和相应的行为。考虑到可扩展性,将有一个接口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个答案

濮阳宏硕
2023-03-14

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

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或命令模式也会被制造出来。

狄承望
2023-03-14

我会用两个类来回答这个问题,即< 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();
 类似资料:
  • 我在面试时遇到了这个问题,我不知道如何正确地回答它。问题是,我们有一个家具系统,我们可以管理不同的家具。每种家具都有自己的“代号”材料(如:木头、铁)和“代号”名称、“代号”类型(如:椅子、书桌、桌子)。 对于每一种家具,我们都可以调用和。首先,我在顶部绘制名为和的基类。在家具下面,我放了不同类型的家具,如桌子,椅子和做同样的事情材料类。如下图所示。 然后,我说如果我们要生产一件像这样的新家具,我

  • 互联网做得太棒了,以至于大多数人将它看作像太平洋这样的自然资源,而不是什么人工产物。上一次出现这种大规模且无差错的技术, 你还记得是什么时候吗? ——阿兰·凯在接受Dobb博士杂志采访时说(2012年) [TOC] 现今很多应用程序都是 数据密集型(data-intensive) 的,而非 计算密集型(compute-intensive) 的。因此CPU很少成为这类应用的瓶颈,更大的问题通常来自数

  • 问题内容: 我们正在使用SQL Server 2008,其中一项要求是在为系统定义的实体上具有可扩展的用户定义属性。例如,我们可能有一个名为Doctor的实体,我们希望系统管理员能够定义通常不在系统中的其他属性。这些属性很可能是链接父表或联接表的查询条件所必需的。 将有定义属性(名称,描述,类型)等的表,但是我的问题是实际数据值的存储。 我不是DBA(只是一个假装成程序员的DBA),但我首先想到的

  • 校招上岸过了很久决定把之前面试梳理一下面经,希望帮助大家顺利校招上岸。 背景:双非本+产品设计专业+大厂实习 一面: 自我介绍(主要讲述实习经历+教育背景) 讲解作品集(以实习项目为主) 对于跨部门协同工作的相关问题(沟通方式+注意点) 掌握的软件工具 性格优缺点 实习期做过最自豪的事情是什么 与开发对接经验与技巧 项目中遇到的问题以及解决方式 总体感觉一面非常良好,小哥哥很好沟通,中间有聊是想为

  • 7.4 面向对象设计* 理解了面 向 对象的基 本 概念之后 , 就可以应 用 这些概念 来 进行面向 对 象 设 计(object-oriented design,简称 OOD)。 传统的程序设计方法是结构化的自顶向下设计,其思想是将软件系统分解为若干个功能, 每个功能都是对数据的一个操作过程。功能又可以划分为若干个子功能,如此反复分解下去, 直至每个功能所对应的操作过程显而易见为止。在分解功能

  • Navicat 为维护 MongoDB 对象提供完整的解决方案。 在主窗口的导航窗格中或对象选项卡中选择对象。 右击已选择的对象。 选择“维护”,然后从弹出式菜单中选择一个维护选项。 结果显示在弹出的窗口中。 数据库 选项 描述 修复数据库 通过放弃无效或损坏的数据来重新生成数据库和索引。 集合 选项 描述 压缩集合 对集合中的所有数据和索引进行重写和碎片整理。 验证集合 通过扫描集合的数据和索引