汽车类违反了单一责任原则吗?

时间:2013-01-14 19:08:46

标签: oop design-patterns single-responsibility-principle

即使我认为我理解单一责任原则和高/低凝聚力原则,以下问题仍然引起我一些困惑

1)假设在Planet类中随意/随意放置BirdCar属性(即Car内没有代码需要或对返回的两个对象进行操作通过这两个属性) - 换句话说,PlanetBird属性不属于Car类

a)

SRP 表明该对象应该只有一个原因需要改变。

public class Car
{
    public void StartEngine()
    { ... }

    private Planet Planet
    {
        get { ... }
    }

    private Bird Bird
    {
        get { ... }
    }
}

Car班级是否违反了SRP?我会说它不会破坏SRP,因为对PlanetBird实例的任何更改都不会传播到Car类?

b)

  凝聚力指的是如何密切相关的方法和阶级   变量属于一个类。在高度凝聚力的所有方法中   和类级变量一起使用来完成特定的   任务。在具有低内聚功能的类中随机插入   进入一个班级并用来完成各种不同的任务

假设即使Car类包含这两个随机属性,它仍然只完成一个特定任务(或几个密切相关的任务):

我们会说Car具有低内聚,即使它仍然执行特定任务(或几个密切相关的任务)吗?

2)假设Planet实例的方法使用BirdCar属性来完成特定任务,然后Car具有高内聚力,尽管从概念上讲这两个属性不属于Car(因此,如果将PlanetBird实例作为参数传递给方法,则会更好a Car对它们进行操作)

谢谢

HELTONBIKER:

1)

  当你把汽车中的鸟和行星封装起来时(更糟糕的是,如果他们是   私人),所以现在Car class有三个改变的理由:

我无法看到Car有三个原因需要改变,因为在我的第一个问题中Car's方法甚至不对这两个属性进行操作,因此对Planet's和{进行任何更改{1}}公共API不会影响Bird's类?

2)

Car

a)这令人困惑:由于修改了The problem here has two components: 1. Bird and Planet are contained (as opposed to aggregated) in Car class; 2. Bird and Planet are not conceptually related to Car, much less by some containment relationship. Car个实例,Planet不必修改Bird的机会(至少在第一个问题上)无论是否包含或汇总PlanetBird个实例,都一样?

b)在Car的第二个问题方法中,对两个属性进行操作以执行单个特定任务,那么它们在概念上是否至少在某种程度上相关?您是否会说即使在第二个问题类中低内聚,即使它只执行单个任务(并且正在使用这两个属性来完成任务)?

3 个答案:

答案 0 :(得分:1)

1) 我会说Car无法容纳PlanetBird。这样汽车有两个不同的职责:汽车功能和持有一些奇怪的物体。 应该有一些其他对象/类可以保存世界中的对象:例如:class WorldContainer

2) 我会说你的两个例子都有很低的凝聚力。应该使用其他一些界面来管理汽车和一些不同的对象。将它们粘合在一起的界面。

答案 1 :(得分:1)

汽车类确实具有较低的凝聚力,因为它指的是与其责任完全不同的类。它还具有更高的耦合表面,因为由于Planet和Bird是公开的,所以您已经为消费者提供了访问这些属性的权限,这意味着您现在正在向任何消费者添加两个“更改原因”,无论是否是汽车内部使用这些。

无论如何,如果仅仅因为汽车现在有责任“获取行星或鸟类的方式”,而忽视任何耦合/凝聚力论点,SRP就会受到侵犯。

答案 2 :(得分:1)

SRP意味着一个班级应该只有一个改变的理由。

因此,Car类中的修改应该意味着Car概念模型发生了变化。

但是,当你把伯德和星球封装在车里时(更糟的是如果它们是私人的),所以现在Car class有三个理由要改变:

  1. 修改汽车概念模型和/或行为;
  2. 修改Bird概念模型和/或行为;
  3. 修改Planet概念模型和/或行为;
  4. 这里的问题有两个组成部分:

    1. 鸟类和星球在Car class中包含(而不是聚合);
    2. 鸟与地球在概念上与汽车无关,更不用说与某种遏制关系。
    3. 或者,简单来说(我希望你这样做是一个教学练习),所显示的架构根本没有意义。


      聚合示例(在Python中)。非内聚类是在Car类定义之外定义的,它引用它们。汽车取决于鸟类和星球,但现在鸟类和星球本身存在。

      class Bird():
          hasWings = True
      
      class Planet():
          isFlat = False
      
      class Car():
          owner = Bird()
          substrate = Planet()
      

      参数传递的示例(只是汽车类,假设其他类与上面类似)。现在Car构造函数(python中的__init__方法)将实例作为参数。这可能是也可能不是。依赖和耦合仍然存在,但现在可能更具体。

      class Car():
          def __init__(bird, planet)
              owner = bird
              substrate = planet
      

      最后,整个内聚和耦合问题与软件本身并没有多大关系,而是与开发人员有关。编译器不介意你的名称空间,项目文件夹和文件分发是否混乱,只要它“编译”。但它不会像你那样做任何感觉(把一个Bird和一个Planet类放在一个Car类中)。刚开始,每个类的版本控制都会非常混乱。

      所以,你不应该违反的纯度不是为了它而写在书中的。这种纯度是(或应该是)源于挣扎于机器指令的人类。一般而言,面向对象和软件体系结构不适用于机器,而是适用于开发人员(思想)。