Enums vs Subclasses,它是面向对象的设计?

时间:2015-12-06 03:42:08

标签: java oop enums subclass

这是我用长度计算器编写的代码,用于表示不同类型单位的长度。我希望它以面向对象的方式进行设计。

public class Length {

    private final double value;
    private final Unit unit;

    public Length(double value, Unit unit) {
        this.value = value;
        this.unit = unit;
    }

    @Override
    public boolean equals(Object obj) {
        Length length = (Length) obj;
        return this.unit.toMM(this.value) == length.unit.toMM(length.value);
    }

    public Length add(Length added) {
        return new Length(this.unit.toMM(this.value) + added.unit.toMM(added.value), Unit.mm);
    }

    public Length subtract(Length another) {
        return new Length(this.unit.toMM(this.value) - another.unit.toMM(another.value), Unit.mm);
    }

}

enum Unit {
    m(1000), cm(10), mm(1);
    private final int rate;

    Unit(int rate) {
        this.rate = rate;
    }

    public double toMM(double value) {
        return rate * value;
    }
}

我使用枚举Unit并让不同的单位m/cm/mm作为其成员。

但我读了这篇关于"OOP vs Non-OOP"的文章,它有一个类似的例子,标记为非OOP:

public class Person {

    private boolean _male; // true means male, false means female.

    public Person (boolean genderFlag) {
        _male = genderFlag;
    }

    public String getGender () {
        return _male? "male": "female";
    }
}

哪个不是枚举,但方法非常相似,在内部使用一些状态来表示不同的类型。

它给出了使用子类的OOP示例:

public abstract class APerson {
    public abstract String getGender();
}

public class Man extends APerson {
    public String getGender() {
        return "male";
    }
}

public class Woman extends APerson {
    public String getGender() {
        return "female";
    }
}

应用他的想法,我认为我的代码应该重写为:

interface Unit {
    public double toMM(double value);
}

public class Meter extends Unit {
    public double toMM(double value) {
        return 1000 * value;
    }
}

public class Centimeter extends Unit {
    public double toMM(double value) {
        return 10 * value;
    }
}

public class Millimeter extends Unit {
    public double toMM(double value) {
        return value;
    }
}

我可以感觉到我的代码的两个设计之间存在一些差异,但仍然无法准确地说出它是什么。

有些问题:

  1. enum的第一个版本不被视为OOP吗?
  2. 带有子类的第二个版本真正的好处是什么?
  3. 我们是否应该始终考虑这种情况的第二个版本?

3 个答案:

答案 0 :(得分:2)

我没有权利开始发表评论,因此在答题部分写下我的意见。

IMO,你所做的是正确的事。使用枚举,您可以使用能够在枚举变量中改变特性(在您的示例中为速率)。因此,您不再需要if else条件,就像我们亲自做的那样。此外,通过使用枚举,您已经使代码变得更好,并且不会通过类爆炸造成您的代码。

回答你的问题: (a)它被认为是哎呀 (b)当你不知道手头的物体数量时,你可以使用第二种方法。即如果我们知道明天人们可以拿出一个新的儿童班。在您的情况下,长度可以以mm,cm等为单位进行测量,并且这些参数的数量是事先已知的。因此,以这种方式编码是非常好的。 (c)取决于您的设计方式。第二种方式也是正确的。

答案 1 :(得分:1)

我认为这有点基于意见。

基本思想是在" enum" (或字符串常量,或其他)情况下,你不具备oop允许的灵活性,而只是一种通过对象的属性而不是其类型进行识别的方法。让男人/女人课而不是sex作为班级成员是一个很好的做法,因为它允许你进一步扩展你的代码(即如果你想跟踪男人的胡子长度 - 这个属性是没有意义的妇女)。

但是,拥有一个对象可能与其他方法一样糟糕。在您的具体情况下,我认为您做了一些过度工程。我建议遵循迭代方法,我将使用person示例来说明它。

最初,实现一个具有属性sex的类(枚举类型就好了)。如果您开始在不同类型之间看到分离(在属性或方法方面),则可以在类型之间执行所需的分隔。

在你的具体情况下,我认为为不同单位设置不同的课程有点不切实际(难以扩展,因为你需要为每个单元设一个课程 - 想想像皮米,飞秒计等等)不必要。但是,更好的方法是将内部长度存储在某个标准单位(即米)中,并使构造函数/ setter / getter中的转换成所需的任何单位。

答案 2 :(得分:1)

  1. enum的第一个版本不被视为OOP吗?
  2. 不,第一个版本 是面向对象的设计。然而,后者肯定是更多面向对象,利用继承来确定行为特征。

    根据你提到的那篇文章,我会说作者认为前者不是面向对象的设计,但是你会在这个问题上获得大量的答案;你被警告了。

    1. 带有子类的第二个版本的真正好处是什么?
    2. 正如文章所指出的那样,不必询问一个州就不那么复杂了,这在malefemale例子中有很好的说明。 然而,这并不会自动地降低复杂性"代码。较小的概念表面区域可以在代码库的复杂性方面产生显着差异。因此,仅仅因为某些东西正在使用继承或其他面向对象的设计技术,它并不一定意味着它是有益的。

      1. 我们是否应该始终考虑这种情况的第二个版本?
      2. 简单明了,没有'。你永远不能说绝对话题(*排队鼓点讽刺)。当你的hello world程序受到界面的影响时,为了保持它的严格面向对象,这并不一定意味着它是一个好的设计。有些情况适合面向对象的结构,有些则不适合;它确实需要根据具体情况来确定。