首页 > 解决方案 > 避免 java 构造函数中的逻辑

问题描述

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

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

标签: javaoopconstructorsoftware-design

解决方案


你不应该在构造函数中做一些可能会失败的事情,在你的情况下,当你阅读文件时有很多事情可能会出错,你应该定义你自己的自定义检查异常来通知你的 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 {
}

推荐阅读