在Java类中创建对象列表 - 更好的方法

时间:2015-08-31 06:54:09

标签: java list arraylist

有一个与在Java类中创建对象列表有关的问题。 谁能告诉我哪种解决方案更好?它的优点和缺点是什么?

1)我的第一个版本:

public class ProductRepositoryImpl implements ProductRepository {

    private List<Product> listOfProducts = new ArrayList<Product>();

    public ProductRepositoryImpl() {

        addProducts(1, "Silnik", "Ferrari", 1000, listOfProducts);
        addProducts(2, "Sprzęgło", "Opel", 500, listOfProducts);
        addProducts(3, "Kierownica", "Fiat", 100, listOfProducts);
        addProducts(4, "Panewka", "Maluch", 250.00, listOfProducts);
        addProducts(5, "Akumulator", "Autosan", 1700.00, listOfProducts);
        addProducts(6, "Zakrętka", "Maseratii", 100.00, listOfProducts);
    }

    private void addProducts(int idProduct, String name, String brand, double price, List list) {
        Product product = new Product();
        product.setId(idProduct);
        product.setName(name);
        product.setBrand(brand);
        product.setPrice(price);
        list.add(product);
    }

    @Override
    public List<Product> getListOfProducts() {    
        return listOfProducts;
    }

 }

2)第二个:

public class ProductRepositoryImpl implements ProductRepository {

    private List<Product> listOfProducts = new ArrayList<Product>();

    public ProductRepositoryImpl() {

        Product p1 = new Product();
        p1.setId(1);
        p1.setName("Silnik");
        p1.setBrand("Ferrari");
        p1.setPrice(1000);

        Product p2 = new Product();
        p2.setId(2);
        p2.setName("Hamulec");
        p2.setBrand("Opel");
        p2.setPrice(500);

        Product p3 = new Product();
        p3.setId(3);
        p3.setName("Kierownica");
        p3.setBrand("Fiat");
        p3.setPrice(100);

        Product p4 = new Product();
        p4.setId(4);
        p4.setName("Akumulator");
        p4.setBrand("Autosan");
        p4.setPrice(1700);

        Product p5 = new Product();
        p5.setId(5);
        p5.setName("Zakrętka");
        p5.setBrand("Maseratii");
        p5.setPrice(100);

        listOfProducts.add(p1);
        listOfProducts.add(p2);
        listOfProducts.add(p3);
        listOfProducts.add(p4);
        listOfProducts.add(p5);
    }

    @Override
    public List<Product> getListOfProducts() {
        return listOfProducts;
    }
}

我将感激每一个解释。

3 个答案:

答案 0 :(得分:4)

有一些设计指南可以帮助您改进代码:

  • 责任分离。 ProductRepositoryImpl应负责处理产品存储库。它不是它的责任,也不应该有构建产品的代码。产品的构造应由产品负责
  • 代码重用。版本1优于版本2,因为构建产品的代码在addProducts()内编写一次,而不是在版本2中编写多次。
  • 封装即可。类的接口是应该公开的唯一部分。应该隐藏它的实现。这意味着产品的id字段不应该直接从外部接收,而应该通过接口方法加入。优点是,如果您以后需要更改内部工作方式,则可以轻松完成,因为所有ID都来自Product类中的一些方法。如果id字段是公共的,那么可能有数百个地方访问它并处理这样的改变将是一场噩梦。

另一个问题是可变性。您的Product类是可变的,如setName方法所暗示的那样。如果这是您的申请的绝对要求,请继续。但是,如果产品一旦定义就不会改变,那么您应该使产品不可变。 Inmutability有几个优点,其中之一是它是线程安全的而不需要同步。所以我让Product inmutable。

考虑到这些指导原则,这是我将采取的方法:

class Product
{
    private final int idProduct;
    private final String name;
    private final String brand;
    private final double price;

    public Product(int idProduct, String name, String brand, double price)
    {
        this.idProduct = idProduct;
        this.name = name;
        this.brand = brand;
        this.price = price;
    }
}

public class ProductRepositoryImpl implements ProductRepository
{
    private List<Product> listOfProducts = new ArrayList<Product>();

    public ProductRepositoryImpl()
    {
        addProduct(new Product(1, "Silnik", "Ferrari", 1000));
        addProduct(new Product(2, "Sprzęgło", "Opel", 500));
        addProduct(new Product(3, "Kierownica", "Fiat", 100));
        addProduct(new Product(4, "Panewka", "Maluch", 250.00));
        addProduct(new Product(5, "Akumulator", "Autosan", 1700.00));
        addProduct(new Product(6, "Zakrętka", "Maseratii", 100.00));
    }

    private void addProduct(Product product)
    {
        listOfProducts.add(product);
    }

    @Override
    public List<Product> getListOfProducts()
    {
        return listOfProducts;
    }
}

答案 1 :(得分:0)

第一个选项表示Factory通常推荐。

推荐它的原因是因为对象初始化被本地化到一个中心位置,因此如果您需要在初始化之前执行任何额外的检查,这样的设计将确保您只需要对代码的一部分进行更改。

作为旁注,在您发布的示例中,由于对象的结构发生变化,您实际上会发挥很大的作用,您只需要添加额外的setter而不是传递额外的参数

但是,在其他情况下,对象创建将取决于其他对象。因此,该模式将允许您进行最少量的更改,从而减少在代码中引入新错误的机会,因为您忘记更新代码中某处埋藏的那一行。

同样正如评论中指出的那样,addProducts应该真正成为addProduct,因为它只添加了一个项目。

答案 2 :(得分:0)

一般来说,第一种设计更好。它减少了代码重复。另一方面,你可以进一步改进它。

  • 您的对象似乎只存储硬编码值。您应该考虑将此代码移动到.property文件
  • 返回列表的不可变版本。它可能会阻止一些令人不快的意外
  • 如果您想将此对象视为真正的存储库,您应该提供一种方法,该方法将通过规范/过滤器获取一些提取方法。目前它不提供封装。