java - 从输入流读取并从数据创建特定实例

标签 java oop io stream

我有一个 BaseProduct 接口(interface)和两个实现类,GroceryProduct 和 TechProduct。我创建了一种从字节输入流中读取产品的方法。考虑到这两种产品都有相似的领域,我一直在寻找一种用这种方法创建某种类型产品的方法。

我想到的唯一解决方案是创建一个辅助方法,获取产品类的构造函数并相应地创建一个实例。

这是该问题的最佳解决方案吗?是否有另一种方法可以从输入流读取产品并创建特定产品类型的实例?

public static BaseProduct input(Class<? extends BaseProduct> productClass, InputStream in) throws IOException {
    DataInputStream dataInputStream = new DataInputStream(in);
    String brand = dataInputStream.readUTF();
    String productName = dataInputStream.readUTF();
    BigDecimal price = new BigDecimal(dataInputStream.readUTF());
    int totalQuantity = dataInputStream.readInt();
    int defectiveQuantity = dataInputStream.readInt();
    List<Review> reviews = new ArrayList<>();
    for (Review review : reviews) {
        String userName = dataInputStream.readUTF();
        int rating = dataInputStream.readInt();
    }
    return createProductInstance(brand, productName, price, totalQuantity, defectiveQuantity, reviews, productClass);
}

private static BaseProduct createProductInstance(String brand, String productName, BigDecimal price, int totalQuantity, int defectiveQuantity, List<Review> reviews, Class<? extends BaseProduct> productClass) {
    try {
        Constructor<? extends BaseProduct> productConstructor = productClass.getConstructor(String.class, String.class, BigDecimal.class, int.class, int.class, List.class);
        return productConstructor.newInstance(brand, productName, price, totalQuantity, defectiveQuantity, reviews);
    } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
        throw new IllegalArgumentException("Could not create product instance: " + e);
    }
}

最佳答案

不,不是。不要使用反射。只需使用多态性即可:

@FunctionalInterface
interface ProductFactory<T extends BaseProduct> {
    T create(String brand, 
             String productName, 
             BigDecimal price, 
             int totalQuantity, 
             int defectiveQuantity, 
             List<Review> reviews);
}

然后传递这样一个接口(interface)的实例,它可以写成 lamdbda:

public static <T> T input(ProductFactory<T> factory, InputStream in) throws IOException {
    DataInputStream dataInputStream = new DataInputStream(in);
    String brand = dataInputStream.readUTF();
    String productName = dataInputStream.readUTF();
    BigDecimal price = new BigDecimal(dataInputStream.readUTF());
    int totalQuantity = dataInputStream.readInt();
    int defectiveQuantity = dataInputStream.readInt();
    List<Review> reviews = new ArrayList<>();
    for (Review review : reviews) {
        String userName = dataInputStream.readUTF();
        int rating = dataInputStream.readInt();
    }
    return factory.create(brand, productName, price, totalQuantity, defectiveQuantity, review);
}

并这样调用它,例如:

ProductFactory<GroceryProduct> factory = 
    (String brand, String productName, BigDecimal price, int totalQuantity, int defectiveQuantity, List<Review> reviews) -> 
        new GroceryProduct(brand, 
                           productName, 
                           price, 
                           totalQuantity, 
                           defectiveQuantity, 
                           reviews);
input(factory, inputStream);

请注意,如果您定义一个类(假设 ProductInformation )来保存所有这些参数,并且将该类的实例作为参数传递给产品构造函数,那么它会更清晰。然后,您可以将 ProductFactory 接口(interface)替换为 Function<ProductInformation, T> 。但请注意,如果您这样做,您甚至不再需要该功能。你可以这样做

ProductInformation info = input(inputStream);
GroceryProduct product = new GroceryProduct(info);

关于java - 从输入流读取并从数据创建特定实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47372215/

相关文章:

c - 像在原始 shell 中一样处理 Ctrl + C

java - 如何返回列表 “s” 中 2 个第一批学生的列表?

java - 用java字符串中的th替换所有td的标签

java - 如何在 Java 中读取 "join"哈希表?

c++ - 如何在 C++ 中与另一个类共享变量

c++ - 在 C++ 中设计多个使用的类时,我应该使用 API/ABC 吗?

java - 寻找正确的克隆方法

class - 类的所有私有(private)变量的 getter 和 setter?

python - 如何拆分大小大于可用内存的文件?

performance - 有效地将大文件读入 map