【问题标题】:Avoiding logic in java constructors避免 java 构造函数中的逻辑
【发布时间】:2021-02-09 08:21:47
【问题描述】:

我有一个需要构建的类,它从文件中获取信息并对其执行某些计算。它将被传递一个 File 对象,并且需要填写几个实例变量(例如,哈希)。怎样才能不把所有工作都放在构造函数中呢?

我的一个想法是简单地将单个实例变量传递给构造函数,一个 File 对象,然后在必要时计算所需的值。但问题是我需要一个容器来存放这些值,稍后我将把它传递给一个单独的类。如果我实现了这个策略,我需要一个只包含实例变量的单独类。

【问题讨论】:

  • 不是一个真正的“问题”——我说继续做吧。
  • 如果这个逻辑真的是构建对象所涉及的,那就去做吧。我想说的一个例外是不要传递File,而是传递InputStreamReader
  • 为什么你不想在构造函数中做这个工作?构造函数的工作是构造对象,所以只要对象是安全构造的,就可以为所欲为。
  • @PrashantPandey 我总是被教导构造函数应该只分配变量,而不是计算它们,或者做一般的逻辑。
  • @Astrum 不是真的。如果实例创建依赖于构造函数,那么在构造函数内部进行是有意义的,只要我们确保逻辑不会导致异常并且正在构造的对象的实例在构造函数之前不会逃脱构造函数构造得当。它还取决于您的应用程序的性质。对于响应速度快的应用程序,将长时间运行的操作放在构造函数中可能是个坏主意。对于后台作业,没那么多。

标签: java oop constructor software-design


【解决方案1】:

你不应该在构造函数中做一些可能失败的事情,在你的情况下,当你读取文件时有很多事情可能会出错,你应该定义你自己的自定义检查异常来通知你的 API 用户它们很可能在您构建对象时发生。我认为有两种方法可以解决您的问题,其中一种是使用构建器模式并定义在那里构建对象的逻辑,您可以这样做:

public class Sample {
    private final String name;
    private final String family;

    private Sample(String name, String family) {
        this.name = name;
        this.family = family;
    }

    private static class Builder {
        private String filePath;
        Builder(String filePath) {
            this.filePath = filePath;
        }
        
        public Sample build(File file) throws FileNotFoundException, RequiredInfoNotPresentInFile {
            try(Scanner sc = new Scanner(file)) {
                String name;
                String family;
                if (sc.hasNextLine())
                    name = sc.nextLine();
                else
                    throw new RequiredInfoNotPresentInFile();
                if (sc.hasNextLine())
                    family = sc.nextLine();
                else
                    throw new RequiredInfoNotPresentInFile();
                return new Sample(name, family);
            }
        }
    }
}

public class RequiredInfoNotPresentInFile extends Exception {
}

另一种方法是使用静态工厂方法,但你应该抛出你的自定义异常来通知用户在创建你的对象期间也发生了一些不好的事情:

public class Sample {
    private final String name;
    private final String family;

    private Sample(String name, String family) {
        this.name = name;
        this.family = family;
    }

    public Sample fromFile(File file) throws FileNotFoundException, RequiredInfoNotPresentInFile {
        try(Scanner sc = new Scanner(file)) {
            String name;
            String family;
            if (sc.hasNextLine())
                name = sc.nextLine();
            else
                throw new RequiredInfoNotPresentInFile();
            if (sc.hasNextLine())
                family = sc.nextLine();
            else
                throw new RequiredInfoNotPresentInFile();
            sc.close();
            return new Sample(name, family);
        }
    }
}

public class RequiredInfoNotPresentInFile extends Exception {
}

【讨论】:

    【解决方案2】:

    如果我正确理解您的问题,我认为您应该使用静态工厂方法来初始化实例变量或实现逻辑,然后获取类对象。这里将尝试使用静态工厂方法来实现您的问题。

    class SomeClass {
      String hash;
      long size;
      public SomeClass(String hash, long size) {
            this.hash = hash;
            this.size = size;
       }
    
      public static SomeClass initFromFile(File file) {
         // Implement logics here
         String hashValue = DigestUtils.md5Hex(FileUtils.readFileToByteArray(file)); // Apache commons
         long fileSize = file.getSize();
         
          return new SomeClass(hashValue, fileSize);
       }
    }
    
    
    
    Class Main {
        public static void main() {
         File file = getFile();
         SomeClass someClass = SomeCLass.initFromFile(file);
        }
    }
    

    这是一个粗略的想法,如何将逻辑与构造函数分离。有关静态工厂方法的更多信息,请点击下面的链接。

    Static Factory Methods

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-05
      • 2013-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多