即使我认为我理解单一责任原则和高/低凝聚力原则,以下问题仍然引起我一些困惑
1)假设在Planet
类中随意/随意放置Bird
和Car
属性(即Car
内没有代码需要或对返回的两个对象进行操作通过这两个属性) - 换句话说,Planet
和Bird
属性不属于Car类
a)
SRP 表明该对象应该只有一个原因需要改变。
public class Car
{
public void StartEngine()
{ ... }
private Planet Planet
{
get { ... }
}
private Bird Bird
{
get { ... }
}
}
Car
班级是否违反了SRP?我会说它不会破坏SRP,因为对Planet
或Bird
实例的任何更改都不会传播到Car
类?
b)
凝聚力指的是如何密切相关的方法和阶级 变量属于一个类。在高度凝聚力的所有方法中 和类级变量一起使用来完成特定的 任务。在具有低内聚功能的类中随机插入 进入一个班级并用来完成各种不同的任务
假设即使Car
类包含这两个随机属性,它仍然只完成一个特定任务(或几个密切相关的任务):
我们会说Car
具有低内聚,即使它仍然执行特定任务(或几个密切相关的任务)吗?
2)假设Planet
实例的方法使用Bird
和Car
属性来完成特定任务,然后Car
具有高内聚力,尽管从概念上讲这两个属性不属于Car
(因此,如果将Planet
和Bird
实例作为参数传递给方法,则会更好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
的机会(至少在第一个问题上)无论是否包含或汇总Planet
和Bird
个实例,都一样?
b)在Car
的第二个问题方法中,对两个属性进行操作以执行单个特定任务,那么它们在概念上是否至少在某种程度上相关?您是否会说即使在第二个问题类中低内聚,即使它只执行单个任务(并且正在使用这两个属性来完成任务)?
答案 0 :(得分:1)
1)
我会说Car
无法容纳Planet
和Bird
。这样汽车有两个不同的职责:汽车功能和持有一些奇怪的物体。
应该有一些其他对象/类可以保存世界中的对象:例如:class WorldContainer
2) 我会说你的两个例子都有很低的凝聚力。应该使用其他一些界面来管理汽车和一些不同的对象。将它们粘合在一起的界面。
答案 1 :(得分:1)
汽车类确实具有较低的凝聚力,因为它指的是与其责任完全不同的类。它还具有更高的耦合表面,因为由于Planet和Bird是公开的,所以您已经为消费者提供了访问这些属性的权限,这意味着您现在正在向任何消费者添加两个“更改原因”,无论是否是汽车内部使用这些。
无论如何,如果仅仅因为汽车现在有责任“获取行星或鸟类的方式”,而忽视任何耦合/凝聚力论点,SRP就会受到侵犯。
答案 2 :(得分:1)
SRP意味着一个班级应该只有一个改变的理由。
因此,Car类中的修改应该意味着Car概念模型发生了变化。
但是,当你把伯德和星球封装在车里时(更糟的是如果它们是私人的),所以现在Car class有三个理由要改变:
这里的问题有两个组成部分:
或者,简单来说(我希望你这样做是一个教学练习),所显示的架构根本没有意义。
聚合示例(在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类中)。刚开始,每个类的版本控制都会非常混乱。
所以,你不应该违反的纯度不是为了它而写在书中的。这种纯度是(或应该是)源于挣扎于机器指令的人类。一般而言,面向对象和软件体系结构不适用于机器,而是适用于开发人员(思想)。