【问题标题】:Should I create static method or abstract superclass我应该创建静态方法还是抽象超类
【发布时间】:2011-12-16 05:23:24
【问题描述】:

我正在尝试重构一个项目,其中有相同的方法分布在不同的类中。为了减少代码重复,我应该将公共代码移动到抽象超类还是应该将其放在实用程序类的静态方法中?

编辑 其中一些方法适用于我认为可以设为静态的通用内容。虽然还有其他引用类的属性,但在这种情况下,我认为将其作为抽象超类更有意义。

【问题讨论】:

  • 没有上下文就无法回答;很大程度上取决于现有类的相关程度、类和方法的使用方式等。
  • 你必须告诉我们更多关于这些方法的信息——如果它们具有相同的行为并且可以独立于任何类运行,那么使用具有静态方法的实用程序类将是有意义的。如果您正在考虑使用抽象类/基类/接口,则必须考虑该类层次结构是否有意义,以及这些函数是否真的是这些类固有的行为,或者如前所述,这些方法无关紧要关于他们所在的班级。
  • 您能解释一下该方法的作用以及所有这些类是否相关吗?
  • 提供更多有关您实际尝试做什么的信息。
  • 我问了几乎同样的问题:stackoverflow.com/questions/5312193/base-class-vs-utility-class。看看有没有帮助。

标签: java abstract-class static-methods


【解决方案1】:

好吧,我遵循一个规则:不要使用基类来删除代码重复,使用实用程序类。

对于继承,问自己一个问题:Is-A 关系是否存在?

另一条在大多数情况下是正确的规则是:优先组合而不是继承

使用静态实用程序类不是真正的组合,但可以称为它的派生。

将这些规则应用于您的 secenrios,并在做出决定时牢记维护性和可扩展性。但是,如果您可以在问题中添加更多详细信息,那就太好了。

【讨论】:

  • 更多细节会减少猜测,但我喜欢你提到的经验法则。
【解决方案2】:

这取决于您的代码在做什么。它们是实用方法吗?它们是特定/专业的类方法吗?这是一个繁重的多线程应用程序吗?

请记住,如果您将它们设为静态并且您的应用程序是多线程的,则必须使用锁来保护它们。这反过来又降低了并发性。在这种情况下,根据有多少线程调用同一段代码,您可能会考虑将其(代码)移动到超类。

【讨论】:

  • 你只需要锁静态方法,如果它们是有状态的
  • @user949300 我同意。我在做假设。
【解决方案3】:

要考虑的另一点可能是这些函数所做的工作类型。如果那是分散的,你应该创建一个带有静态方法的外观/助手/实用程序类。

【讨论】:

    【解决方案4】:

    正如其他人所提到的,这个问题的答案取决于问题的上下文和重复的代码。

    需要考虑的一些事情

    • 重复的代码是否会改变对象的实例。在这种情况下,公共抽象类中的受保护方法
    • 虽然测试框架在这方面做得越来越好,但静态方法对于纯单元测试来说可能是个问题,而不是静态实用程序类。
    • 要正确继承可能很棘手,考虑一下来自不同类的这些对象是否真的相关并且需要一些 OO 重构?或者它们是不相交的领域逻辑,碰巧需要类似的代码。

    【讨论】:

      【解决方案5】:

      如果它不使用任何类成员,您可能会使用静态!

      但你应该在抽象类或母类中这样做

      【讨论】:

      • 这里是一大早 :X 不要期望太多 :D
      【解决方案6】:

      如果方法使用类的许多字段或方法,它们不应该是静态的。 如果它们是子类可能想要修改的东西,它们不应该是静态的。 如果方法应该是接口的一部分,则它们不能是静态的。

      否则,这是您的决定,您稍后可能会改变主意。 :-)

      【讨论】:

        【解决方案7】:

        乍一看,我会说将公共代码作为公共类中的公共静态方法会更好。这将使该方法对任何类都有用,只需使用

            UtilityClassName.methodName();
        

        这比将其作为抽象超类中的具体方法要好,因为这样您将始终需要在要使用该单一方法的所有类中扩展该超类。

        但是现在,正如您所说,该方法的行为取决于一些变量。现在,如果它依赖于不同类的实例变量,那么最好在一个接口中添加这个方法,让你所有的类都实现这个接口,并有自己的实现。

        但是,如果这些变量是常量值,那么在接口中具有这些常量值。在您的实用程序类中实现这些接口。再次使它成为该实用程序类中的静态方法,它将直接使用这些常量。

        例如考虑跟随。返回圆面积的常用代码。

            public interface TwoDimensional{
                double PI = 3.14;
            }
        
            public class MyUtility implements TwoDimensional{
                public static double getCircleArea(double radius){
                    return PI*radius*radius;
                } 
            }
        

        在这里,您可以看到 getCircleArea() 方法取决于不同类的半径,但我仍然可以将此值传递给 myUtility 类的静态方法。

        【讨论】:

          猜你喜欢
          • 2012-06-17
          • 2014-05-24
          • 1970-01-01
          • 2015-11-25
          • 1970-01-01
          • 2016-08-13
          • 2019-04-15
          • 1970-01-01
          相关资源
          最近更新 更多