单一责任原则与移动方法重构

时间:2014-09-09 13:25:09

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

我似乎陷入了两个设计准则之中。

我有一个代表三维体积的类,它由块组成。此类提供简单的修改方法,例如 AddBlock RemoveBlock

我需要对这个课程做几件事

首先,我需要了解有关卷的某些聚合属性,使用 GetTotalWeight GetMaximumWidth 等方法。

其次,我需要对这些卷执行转换操作,例如 Shrink Trim ,这些操作几乎与名称告诉您的一样(无需进入细节,卷只是根据一些规则改变,通过添加或删除块)。这些操作中有很多逻辑。

我的问题是:如果我将这些查询和转换方法添加到 Volume 类,是否会破坏单一责任原则? 我的班级职责是:

  • 保存卷数据,允许简单修改(添加和删除块)
  • 提供有关卷的汇总信息
  • 为这些卷提供转换功能。

如果我认为这是太多的责任,并且 Volume 类应该只代表卷,我需要创建类,如 VolumeTrimmer 用于转换的VolumeShrinker 等,以及用于查询的 WeightCalculator

这最后一个选项似乎巧妙地将不同类别中的问题分开。但是,如果我查看 VolumeTrimmer Trim(音量v)的详细信息,它所做的就是通过音量调用操作。与此同时,我的 WeightCalculator CalculateWeight(Volume v)方法似乎主要关注 Volume

当我看到这种方法时,我觉得有必要使用移动方法重构。我查看代码并说“这个方法主要关注的是另一个类的属性,因此我最好将此方法移到这个类中”。但这会将责任带回 Volume 类!

关于如何解决这个问题的任何想法?我理解这些指导方针错了吗?

3 个答案:

答案 0 :(得分:2)

像往常一样,这类问题的唯一正确答案是:它取决于。

通常使用简单的数据容器类(如卷类),而不使用缩小,修剪等方法。

还可以选择在Volume类中使用Trimmer和Shrinker。这样,您可以将Volume及其操作很好地包含在单个类中,但也可以将复杂的方法分开,这可能有助于测试。

那么如何确定哪个是正确的设计呢?以下是一些指导性问题:

  1. 对于Shrinker等,你是否需要在Volume类中公开,否则将是私有的?如果是这样,这暗示了卷的方法

  2. Shrinker& Co是否有可替代的实施方案,可能用于测试目的或具有不同的性能特征?如果是这样,这暗示了单独的课程。

  3. Volume的客户端大多数时候都使用add / removeBlock mehtods和shrink AND trim方法吗?这会再暗示一个班级。

  4. Shrinker& Co每个只需要Volume的API子集吗?如果是这样,这暗示了单独的课程。

答案 1 :(得分:0)

据我了解,单一责任原则是相当随意的,因为高级语言的代码片段只能做一件事。 话虽如此,似乎您的VolumeTrimmer和VolumeShrinker只对Volume的属性子集感兴趣。因此,分离这些类并仅为它们提供他们感兴趣的属性子集是有意义的。这使得它们可以在其他类具有此子集并希望具有相同行为的其他场景中可重用,但不需要对卷有所了解。 有意义吗?

答案 2 :(得分:0)

我认为没问题。这似乎是Composite pattern的一个例子。您的音量由块组成。

没有理由说您的卷不能进行卷范围操作,例如Transform,这可以通过委派给块级转换操作来实现。