这是糟糕的oop设计吗?

这是糟糕的oop设计吗?,oop,Oop,假设我有一个名为iVihicle的接口 从这个接口,我衍生出几个具体的类型,比如公共汽车和汽车(都可以移动、减速、关闭发动机等)。我的界面没有字段 如果有一个类别包含字段(例如,车辆最高速度),并将其用于每种具体类型,这会是一种糟糕的设计吗?这会是一个糟糕的设计吗?另外,如果我在这个类中存储状态(例如使用字段),那么它必须是静态的吗 谢谢你说的是一个抽象类,不,它的设计不错。这就是它们的用途(基本上是接口,但有一些基本的实现) 状态不必静态存储。每次创建汽车、公共汽车等时,都会有该类的完整实现(

假设我有一个名为iVihicle的接口

从这个接口,我衍生出几个具体的类型,比如公共汽车和汽车(都可以移动、减速、关闭发动机等)。我的界面没有字段

如果有一个类别包含字段(例如,车辆最高速度),并将其用于每种具体类型,这会是一种糟糕的设计吗?这会是一个糟糕的设计吗?另外,如果我在这个类中存储状态(例如使用字段),那么它必须是静态的吗


谢谢

你说的是一个抽象类,不,它的设计不错。这就是它们的用途(基本上是接口,但有一些基本的实现)


状态不必静态存储。每次创建汽车、公共汽车等时,都会有该类的完整实现(以派生类之一的形式)。

只是为了澄清一些混淆

接口不能有字段

但是,它可以具有属性。属性,这些属性必须由实现接口的对象通过代码实现

除非您计划通过接口将对对象的引用转换回具体类型,否则您应该将一些有意义的属性放入接口中,否则您将无法访问它们

换句话说,如果您有:

IVehicle vehicle = GetVehicle();
// want to get speed of vehicle?
Car car = (Car)vehicle;
Double speed = car.Speed;
公共属性应该放在公共接口中。因为车辆是一个移动的物体,所以速度在那里是有意义的

然而,发动机的数量对飞机和一些船只来说是有意义的,但对汽车来说则没有意义,因此这种类型的信息可能需要定位到一些更具体的接口中

静态意味着在实例之间共享,我怀疑这是个好主意

但是,使用接口而不仅仅是类层次结构来将对象的访问和使用与其实际类型和标识分离开来的总体计划是一个好主意,并且会带来良好的设计

最好的计划是选择对您的模型有意义的抽象级别,然后继续。您可以很容易地过度设计这样的解决方案。例如,您可能意识到有些车辆根本没有发动机,有些车辆可以在多个维度上移动(即,不仅向前/向后,而且向上/向下、侧向等),选择适合您车型的级别是一个良好的开端


例如,如果你要对一个县必须处理的交通问题进行建模,那么飞机是否可以向前/向后移动,或者是否有垂直旋转的发动机都是没有意义的,所以你可能不应该尝试将其设计到解决方案中。

你是针对特定语言的。在C++中,没有接口,但可以使用抽象类,比如接口。

< P>我将添加<代码> TopSturiest//C>到接口,作为这样的属性:

interface IVehicle
{
    void Move();
    void SlowDown();
    void SwitchOffEngine();

    Int32 TopSpeed { get; }
}
class Car : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
        get { return 120; }
    }
}

class Bus : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
        get { return 98; }
    }
}
interface IVehicle
{
  void accelerate();
}

sealed class VehicleProperties
{
  const int topSpeed;
}

class VehicleImplementation : IVehicle
{
  //const data
  const VehicleProperties vehicleProperties;
  //non-const instance/state data
  int currentSpeed;
  //ctor
  VehicleImplementation(VehicleProperties vehicleProperties)
  {
    this.vehicleProperties = vehicleProperties;
  }
  //implement IVehicle methods
  void accelerate()
  {
    if (currentSpeed => vehicleProperties.topSpeed)
      return;
    ... else todo: accelerate ...
  }
}

class Car : VehicleImplementation
{
  //static properties associated with the Car type
  static VehicleProperties carProperties = new VehicleProperties(120);
  //ctor
  Car()
    : VehicleImplementation(carProperties)
  {}
  //IVehicle methods already implemented by
  //the VehicleImplementation base class
}
然后在具体实体中实现接口,如下所示:

interface IVehicle
{
    void Move();
    void SlowDown();
    void SwitchOffEngine();

    Int32 TopSpeed { get; }
}
class Car : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
        get { return 120; }
    }
}

class Bus : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
        get { return 98; }
    }
}
interface IVehicle
{
  void accelerate();
}

sealed class VehicleProperties
{
  const int topSpeed;
}

class VehicleImplementation : IVehicle
{
  //const data
  const VehicleProperties vehicleProperties;
  //non-const instance/state data
  int currentSpeed;
  //ctor
  VehicleImplementation(VehicleProperties vehicleProperties)
  {
    this.vehicleProperties = vehicleProperties;
  }
  //implement IVehicle methods
  void accelerate()
  {
    if (currentSpeed => vehicleProperties.topSpeed)
      return;
    ... else todo: accelerate ...
  }
}

class Car : VehicleImplementation
{
  //static properties associated with the Car type
  static VehicleProperties carProperties = new VehicleProperties(120);
  //ctor
  Car()
    : VehicleImplementation(carProperties)
  {}
  //IVehicle methods already implemented by
  //the VehicleImplementation base class
}
我认为这是最好的方法,不需要基类


我之所以认为这是最好的方法,是因为
TopSpeed
是一个特定于实现的属性,在基类中没有任何意义。由于基类将要求任何实现以任何方式设置此值,因此我认为最好更改接口以包含它。

I second DannySmurf,抽象类非常有用。我经常在类库中使用隐藏接口模式后面的抽象类,这样我就可以将所有实现类,甚至抽象父类,作为内部类,也就是说,我根本不向客户机公开实现

如果有一个类别包含字段(例如,车辆最高速度),并将其用于每种具体类型,这会是一种糟糕的设计吗?这会是一个糟糕的设计吗

不,设计不错。另一种方法是为每个字段设置一个抽象/纯虚拟属性(例如,top speed)。。。如果您有很多这样的属性,并且这些属性很简单(例如,只返回一个数字,实际上不做任何复杂的事情),那么您对包含专门属性值的类的想法似乎比拥有更多抽象/纯虚拟属性更简单

另外,如果我在这个类中存储状态(例如使用字段),那么它必须是静态的吗

如果它是静态的,当且仅当它应用于类的每个实例时,这是可以的。例如,可以将“最高速度”定义为静态(所有总线具有相同的最高速度),但不能定义为“当前速度”(不同的总线在任何给定时刻以不同的速度运行)


说清楚一点,我想你建议的设计是这样的:

interface IVehicle
{
    void Move();
    void SlowDown();
    void SwitchOffEngine();

    Int32 TopSpeed { get; }
}
class Car : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
        get { return 120; }
    }
}

class Bus : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
        get { return 98; }
    }
}
interface IVehicle
{
  void accelerate();
}

sealed class VehicleProperties
{
  const int topSpeed;
}

class VehicleImplementation : IVehicle
{
  //const data
  const VehicleProperties vehicleProperties;
  //non-const instance/state data
  int currentSpeed;
  //ctor
  VehicleImplementation(VehicleProperties vehicleProperties)
  {
    this.vehicleProperties = vehicleProperties;
  }
  //implement IVehicle methods
  void accelerate()
  {
    if (currentSpeed => vehicleProperties.topSpeed)
      return;
    ... else todo: accelerate ...
  }
}

class Car : VehicleImplementation
{
  //static properties associated with the Car type
  static VehicleProperties carProperties = new VehicleProperties(120);
  //ctor
  Car()
    : VehicleImplementation(carProperties)
  {}
  //IVehicle methods already implemented by
  //the VehicleImplementation base class
}

在你的情况下,你没有破坏OO-

IVehicle定义了“如果你是一辆汽车,你应该做什么?”

AbstractVehicle定义“如果你是一辆车,这是你应该能够做到的最低限度,也是你应该做到的”

Concrete vehicle定义“我是一辆车,这是我做事情的方式,因为我是一辆车”


您不需要将所有属性都设置为静态。像“最大速度”或“最高速度”之类的东西可以保持静止,但你也可以将它们保持为常量

我认为应该使用超类而不是接口。因此,IVehicle接口很可能是冗余的,您应该只拥有名为Vehicle的抽象超类。 由于每个车辆都可以移动,因此可以测量其速度,因此可以将速度作为字段添加到超类中


该速度场绝不是静态的,因为它将为车辆的每个具体实例实例化;如果您有两条总线,它们可能具有不同的速度,因此该字段不能是静态的,但必须特定于实例。

另一种方法,以及我如何区分常见场景的抽象类和接口,是:

-所有cus