类设计-面向对象的编程问题

时间:2019-01-18 16:55:00

标签: class oop class-design

这是在采访中问到的。

有不同的公共汽车制造商。每个总线都有不同的型号,每个型号只有2个变体。因此,不同的制造商具有仅2个变体的不同型号。面试官让我设计一个只有课程的独立程序。她提到我不应该考虑数据库,也不必编写数据库。例如,它可能是带有输入和输出的基于控制台的程序。

制造商,型号和型号信息应保存在内存中(硬编码值适用于该独立程序)。她想观察课堂和我的问题解决方法。

她告诉我要集中精力为该系统实现三种API或方法。

第一个是获取有关特定总线的信息。输入将是制造商名称,型号名称和型号名称。给定这三个值,应向客户显示有关特定公共汽车的信息,例如其价格,型号,年份等。

第二个API是比较两条总线,输出将以表格格式并排列出功能。输入将与第一个API的输入相同,即两个总线的制造商名称,型号名称和变体名称。

第三个方法是按价格(> = price)搜索公交车,并获取满足条件的公交车列表。

她还补充说,API应该是可扩展的,我应该在这种情况下设计解决方案。

这是我设计班级的方式:

class Manufacturer {
    private String name;
    private Set<Model> models;
    // some  more properties related to manufacturer
}

class Model {
    private String name;
    private Integer year;
    private Set<Variant> variants;
    // some more properties related to model
}

class Variant {
    private String name;
    private BigDecimal price;
    // some more properties related to variant
}

class Bus {
    private String manufacturerName;
    private String modelName;
    private String variantName;
    private Integer year;
    private BigDecimal price;
    // some more additional properties as required by client
}

class BusService {

    // The first method
    public Bus getBusInformation(String manufacturerName, String modelName, String variantName) throws Exception {
        Manufacturer manufacturer = findManufacturer(manufacturerName);
        //if(manufacturer == null) throw a valid exception
        Model model = findModel(manufacturer);
        // if(model == null) throw a valid exception
        Variant variant = findVariant(model);
        // if(variant == null) throw a valid exception
        return createBusInformation(manufacturer, model, variant);
    }

}

她强调只有2个变体,不会再有其他变体,它应该是可扩展的。在学习完这些课程之后,她说她了解我的方法,而我不必实现其他API /方法。我意识到她对我设计它们的方式没有印象。

了解我所犯的错误会很有帮助,以便我可以从中学习。

2 个答案:

答案 0 :(得分:0)

我想说您对Bus类的表示受到严格限制,Variant,Model,Manufacturer应该是到类的硬链接,而不是字符串。然后获取每个名称的名称。

从巴士bus {1}或外界的角度来看

E.G。 this.variant.GetName()

通过将总线限制为固定部分的字符串,即使在总线类内部,您也必须进行查找,这在规模上比简单的内存引用要慢得多。

就您的API而言(虽然我没有示例),但是获取总线信息的一种方法受到限制。如果总线的组成发生变化(各种变化,引入了新的组件类),则需要对该函数进行适当的重写,而如果其他函数的编写类似,则这两个都必须全部重写。

这将需要一些思考,但是针对此问题的通用方法可以根据输入来动态获取信息,这使得以后添加/删除组件更加容易。这将是您的面试官最关注的高级技术和语言技能的领域。以正确的方式在此处实现泛型,委托等,可以使您将来对API的维护更加容易。 (对不起,我没有例子)

我不会说您的方法一定很糟糕,但是字符串成员变量可能是唯一的主要问题。

答案 1 :(得分:0)

I interpreted your 3 requirements a bit differently (and I may be wrong). But it sounds like the overall desire is to be able to perform different searches against all Models, correct?

Also, sounds to me that as all Variants are Models. I suspect different variants would have different options, but nothing to confirm that. If so, a variant is just a subclass of a particular model. However, if variants end up having the same set of properties, then variant isn't anything more than an additional descriptor to the model.

Anyway, going on my suspicions, I'd have made Model the center focus, and gone with:

(base class)

abstract class Model {
    private Manufacturer manufacturer;
    private String name;
    private String variant;
    private Integer year;
    private BigDecimal price;
    // some more properties related to model
}

(manufacturer variants)

abstract class AlphaModel {
    AlphaModel() {
        this.manufacturer = new Manufacturer() { name = "Alpha" }
    }

    // some more properties related to this manufacturer
}

abstract class BetaModel {
    BetaModel() {
        this.manufacturer = new Manufacturer() { name = "Beta" }
    }

    // some more properties related to this manufacturer
}

(model variants)

abstract class AlphaBus : AlphaModel {
    AlphaBus() {
        this.name = "Super Bus";
    }
    // some more properties related to this model
}

abstract class BetaTruck : BetaModel {
    BetaTruck() {
        this.name = "Big Truck";
    }
    // some more properties related to this model
}

(actual instances)

class AlphaBusX : AlphaBus {
    AlphaBusX() {
        this.variant = "X Edition";
    }
    // some more properties exclusive to this variant
}

class AlphaBusY : AlphaBus {
    AlphaBusY() {
        this.variant = "Y Edition";
    }
    // some more properties exclusive to this variant
}

class BetaTruckF1 : BetaTruck {
    BetaTruckF1() {
        this.variant = "Model F1";
    }
    // some more properties exclusive to this variant
}

class BetaTruckF2 : BetaTruck {
    BetaTruckF2() {
        this.variant = "Model F2";
    }
    // some more properties exclusive to this variant
}

Then finally:

var data = new Set<Model> {
    new AlphaBusX(),
    new AlphaBusY(),
    new BetaTruckF1(),
    new BetaTruckF2()
}

API #1:

var result = data.First(x => x.manufacturer.name = <manufactuer> 
                          && x.name = <model>
                          && x.variant = <variant>);

API #2:

var result1 = API#1(<manufacturer1>, <model1>, <variant1>);
var result2 = API#1(<manufacturer2>, <model2>, <variant2>);

API #3:

var result = data.Where(x => x.price >= <price>);