Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中重构实用程序类(静态类)的最佳方法是什么_Java_Oop_Design Patterns_Immutability - Fatal编程技术网

在java中重构实用程序类(静态类)的最佳方法是什么

在java中重构实用程序类(静态类)的最佳方法是什么,java,oop,design-patterns,immutability,Java,Oop,Design Patterns,Immutability,我正在考虑重构一些实用程序类(静态类)。 静态类很难测试,主要问题是它的生成 我们的代码紧密耦合,有很多依赖性。 用于重构的最佳设计模式是什么? 我考虑过使用构建器的不可变对象,但我不确定 将此代码视为我要重构的1 public class UtilTest { public static boolean isEligibleItem(Item item){ if(isCondition1(item)){ return isConditio

我正在考虑重构一些实用程序类(静态类)。 静态类很难测试,主要问题是它的生成 我们的代码紧密耦合,有很多依赖性。 用于重构的最佳设计模式是什么? 我考虑过使用构建器的不可变对象,但我不确定

将此代码视为我要重构的1

public class UtilTest {

    public static boolean  isEligibleItem(Item item){
         if(isCondition1(item)){
             return isCondition2(item);
         }

         return false;
    }

    public static  boolean  isCondition1(Item item){
        //go to service that go to the data base  
        return false;
    }

    public static boolean  isCondition2(Item item){
        //go to service that go to the data base  
        return false;
    }
}
如果我想测试我的isEligibleItem()方法,我需要模拟去db的2个方法。
我做不到,因为它们是静态的。我希望避免使用Powermock

将其简单转换为更易于测试的设置:

public class UtilTest {

    private final MyDatabaseService service;

    public UtilTest(MyDatabaseService service) {
       this.service = service;
    }

    public boolean  isEligibleItem(Item item){
         if(isCondition1(item)){
             return isCondition2(item);
         }
         return false;
    }

    public boolean isCondition1(Item item){
        this.service.goToDataBase();
        return false;
    }

    public boolean isCondition2(Item item){
        this.service.goToDataBase2();
        return false;
    }
}
这并不能消除所有问题,但这只是一个开始,您可以使用模拟数据库服务测试您的类

如果您想进一步推进,可以声明一个接口,其中包含您想要公开的所有方法(您可能还想重命名该类…),并使
UtilTest
实现它。所有使用
UtilTest
的代码都应该重写为使用接口,然后您可以完全直接地模拟
UtilTest
。这是否值得,在很大程度上取决于实际的
UtilTest
有多复杂。如果它执行的任务相对简单,你可能会认为它比它的价值更麻烦。但是,如果其中有一些繁重的处理,您肯定希望使其易于模仿。

实用程序类反模式 人们说静态方法很难测试的原因更多的是它如何将不相关的类紧密地结合在一起,它降低了内聚性,并引入了不可见的副作用。这三件事比一些单元测试挥手抱怨要重要得多

测试交互作用 它更多的是测试与其他代码的交互,而不是测试
静态方法本身。这就是Java真正需要
函数作为第一类对象的地方

在大多数情况下,只有
静态
方法的类肯定是一种代码味道。也有例外,但这种反模式往往被非面向对象语言的初学者和老手滥用

规则的例外-不可变 异常主要是标记为
final
的类中可能被认为缺少的东西,比如
String
不可变的

拥有一个具有通用的
静态
方法的
Strings
类并不坏,因为
String
是不可变的(没有副作用),并且您不能向
String
类添加任何内容,因此您没有太多的选择。同样适用于
Integer
等,
Guava
具有这种命名约定,它适用于这些不可变对象

副作用
静态
方法往往会引入很多副作用。以某种不透明的方式获取对象并操纵该对象的事情是不好的,更糟糕的是,当他们根据传入的实例查找其他对象并操纵它们时,它们会混淆正在发生的事情,并且是紧密耦合和低内聚性的

高内聚 紧密内聚不像耦合那样被谈论得那么多,但它同样重要。它们是同一枚硬币的两面,忽视其中一方会导致另一方因此而受苦

这些
静态
方法应该在它们作为参数的类上,它们与这些类紧密耦合。在这种情况下,为什么它们不在
类中

一旦您添加另一个采用
SomeOtherItem
static
方法,您就间接地将不相关的类耦合在一起了

纠正这种情况的最简单方法是将事物移到更靠近它们所属的位置(在本例中为
类)

工厂/提供者模式 如果您有真正属于
常规
的内容,或者由于
最终
或其他原因而无法添加到类中的内容,那么使用接口和
提供程序
模式是使用
工厂
生成
提供程序
实例的最佳方法

然后,您可以使用
Guice
之类的工具来注入您需要的任何实现,具体取决于它是否是测试


甚至还有一种混合的
实用程序
模式,可以从
提供者
中注入实现,这将为您提供
静态
方法的便利,以及不使用它的灵活性和可维护性。

也许一个示例会有用。你能展示给我们看吗?有时候你想模仿他们,这样做可能会很麻烦。你能展示一些代码吗?如果不知道代码在做什么,就很难做出回应。如果没有具体的代码来讨论,这个问题就不清楚或太广泛。如果您确实有具体的代码要讨论,那么您最好继续提问。与流行的观点相反,静态方法很容易测试。另一方面,调用静态方法的方法…不是。是的,这是一个良好的开端(依赖注入)。但是我们的utils类依赖于其他服务,我不希望我的构造函数太大。这就是为什么我会想到immutable和builder,因为我可以构建我想要的,然后运行它并进行测试it@MosheTsabari看起来这些实用程序类根本不是实用程序类。实用程序类处理非业务逻辑类型代码。如果您是协同服务,那么它很可能不是一个实用程序类,应该被烘焙到处理这些服务的对象中。@JoseMartinez或它们应该被转换为更高级别的服务。这就是我正在处理的问题。一些开发人员希望创建方法并使用它们,而无需创建