【问题标题】:Most efficient way to remove duplicated code from multiple strategies从多个策略中删除重复代码的最有效方法
【发布时间】:2016-11-14 17:31:49
【问题描述】:

我们的项目中有 3 种类型的属性:CategoryAttributeProductAttributeProductTypeAttribute。这些不在我们的控制范围内,因为它们来自自动生成的类,并且可能包含不同类型的属性值,例如文字数字图片。现在,每个属性都有自己的策略来检索属性值。为简单起见,我们假设它们都具有 TextStrategyNumberStrategyImageStrategy

示例策略:

@Component
public class CategoryImageAttributeStrategy implements CategoryAttributeStrategy {

  @Override
  public boolean isApplicable(CategoryAttribute attribute) {
      return attribute.getImage() != null;
  }

  @Override
  public Object getAttributeValue(CategoryAttribute attribute) {
      //return attribute value here 
      //may be different or may be the same 
      //for ProductImageAttributeStrategy and ProductTypeImageAttributeStrategy
  }

}

虽然获取图像值可能对所有人都不同,但获取文本值是相同的,我们最终得到 3 类几乎相同的代码,我真的真的很不喜欢重复代码。

我考虑为每种策略类型创建一个抽象类/默认接口,例如DefaultTextStrategy ,所有 3 个文本策略都将从继承并使用提供更高的默认代码或用自己的实现覆盖它,但是我对这种方法并不满意,因为它需要为此类创建更多类一个简单的任务。

也许甚至可以将相同类型(例如图像)的策略组合成一个?

我真的很想听听更有经验的人在这件事上怎么说,因为我想学习和改进。

提前感谢您的宝贵时间。

【问题讨论】:

    标签: java spring oop design-patterns strategy-pattern


    【解决方案1】:

    应该只有 3 种策略。扩展基本策略的 TextStrategy、NumberStrategy 和 ImageStrategy。混合属性和策略会让人感到困惑,因为两者实际上是独立的,并且彼此之间存在多对多的关系。

    让 3 个属性扩展一个 Attribute 类:CategoryAttribute、ProductAttribute 和 ProductTypeAttribute。

    让策略根据传递给它的 Attribute 类对象来决定需要做什么。对于文本策略,将有单一的实现。对于图像策略,您可能需要对一个类进行特殊处理。

    【讨论】:

    • 问题是(正如我在原帖中提到的)CategoryAttribute、ProductAttribute 等是基于 xsd 模式的自动生成的类,我无法控制它们,所以我不能让它们扩展一些东西别的。我只喜欢 3 种策略的想法,但是在策略类中,我必须使用 Object 参数并检查它的 instanceof。(找出它是什么属性类型)这看起来有点脏。至少我认为带有 3 个 instanceof 的 isApplicable 方法有点意思。
    【解决方案2】:

    这就是我所做的:

    首先,我为所有类型的策略创建了一个名为“AttributeValueStrategy”的接口。然后添加 3 个回调(特定类型,例如 NumberValueCallback 等)。现在,每个策略都实现了其类型的回调接口和 AttributeValueStrategy 接口。然后是 DefaultStrategyMethods 类,其中包含每种类型的默认“getAtrribute”,实际策略调用 defaultStrategyMethods(如下所示)或只是实现自己的代码。

    @Override
    public Object getAttributeValue(Object attribute) {
        return defaultStrategyMethods.getNumberValue(attribute, this);
    }
    

    创建回调是因为只有实际的策略知道它应该转换到哪个类(并且有一个方法可以做到这一点),而 DefaultStrategyMethods 需要使用它,所以这就是我将“this”作为第二个参数传递的原因(这是回调本身)。

    不再重复,一切都清晰干净。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-31
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 2021-05-19
      相关资源
      最近更新 更多