当前位置: 首页 > 知识库问答 >
问题:

如何使用生成器模式创建一个类的多个品种?

仲孙英才
2023-03-14

我的目标是使用生成器模式根据产品类别创建产品详细信息字段。

无论产品类别如何,这都是基本的ProductDetails属性。

int stock;          // required
String ships_from;  // required

String brand;       // optional

电脑类可能有

String model;           // optional
String screen_size;     // optional
String warranty_period; // optional

食物类别可能有

String shelf_life;      // required

String expiration_date; // optional

这是我使用的基本构建器模式

public class ProductDetails {
  // attributes

  private ProductDetails(ProductDetailsBuilder builder) {
    this.attribute1 = builder.attribute1;
    this.attribute2 = builder.attribute2; // and so on.
  }

  // getters

  public static class ProductDetailsBuilder {
    // attributes

    public ProductDetailsBuilder(//required attributes) {
      this.attribute1 = attribute1;
    }

    // setters

    public ProductDetails build() { return new ProductDetails(this); }
  }
}

当我尝试将ProductDetails类扩展到例如ProductDetails\u ComputerProductDetails\u Food类时,就会出现问题。

public class ProductDetails_Computer extends ProductDetails {
  // attributes

  private ProductDetails_Computer(ProductDetails_ComputerBuilder builder) {
    this.attribute1 = builder.attribute2;
  }

  // getters

  public static class ProductDetails_ComputerBuilder {
    // attributes.

    // setters

    public ProductDetails_Computer build() { return new ProductDetails_Computer(this); }
  }
}

我的预期结果是:我可以做公共类ProductDetails\u计算机扩展ProductDetails

我的实际结果是:因为ProductDetails构造函数是私有/受保护的,所以我无法扩展。一些网站禁止使用公共构造函数来避免直接初始化,我同意这种做法。

共有1个答案

郝玄天
2023-03-14

有效的Java建议在这种情况下使用构建器的并行层次结构。

下面是抽象类和具体类的外观:

ProductDetails(基本抽象类):

abstract public class ProductDetails {
    int stock;
    String ships_from;

    String brand;
    
    // Recursive generics
    abstract static class Builder<T extends Builder<T>> {
        int stock;
        String ships_from;

        String brand;

        public Builder(int stock, String ships_from) {
            this.stock = stock;
            this.ships_from = ships_from;
        }

        // returns the reference of implementation (child class)
        T brand(String brand) {
            this.brand = brand;
            return self();
        }
        
        // force implementation to return child class' builder
        protected abstract T self();
         
       // force implementation to return itself while holding "Code to interface" practice
        abstract ProductDetails build();
    }

    protected ProductDetails(Builder<?> builder) {
        this.stock = builder.stock;
        this.ships_from = builder.ships_from;

        this.brand = builder.brand;
    }
    
}

实现可能如下所示:

电脑产品详情

public class ProductDetails_Computer extends ProductDetails {
    String model;
    String screen_size;
    String warranty_period;

    private ProductDetails_Computer(Builder builder) {
        super(builder);
        this.model = builder.model;

        this.screen_size = builder.screen_size;
        this.warranty_period = builder.warranty_period;
    }

    public static class Builder extends ProductDetails.Builder<Builder> {
        String model;
        String screen_size;
        String warranty_period;

        public Builder(int stock, String ships_from) {
            super(stock, ships_from);
        }

        // child class attributes setter
        public Builder model(String model) {
            this.model = model;
            return this;
        }

        public Builder screen_size(String screen_size) {
            this.screen_size = screen_size;
            return this;
        }

        public Builder warranty_period(String warranty_period) {
            this.warranty_period = warranty_period;
            return this;
        }

        @Override
        protected Builder self() {
            return this;
        }

        @Override
        ProductDetails build() {
            return new ProductDetails_Computer(this);
        }

    }

    @Override
    public String toString() {
        return "ProductDetails_Computer [stock= " + stock + ", brand= " + brand + ", model=" + model + ", screen_size="
                + screen_size + ", warranty_period=" + warranty_period + "]";
    }

}

测试类


public class TestBuilder {
    public static void main(String[] args) {
        var computerBuilder = new ProductDetails_Computer.Builder(20, "XYZ");
        computerBuilder.brand("Some_brand")
                       // able to invoke child class methods because of recursive generics
                       .screen_size("200").model("some_model");
        
        System.out.println(computerBuilder.build().toString());
        
    }
}

输出:

ProductDetails_Computer [stock= 20, brand= Some_brand, model=some_model, screen_size=200, warranty_period=null]

您可以在这里阅读递归泛型。

 类似资料:
  • 问题内容: 假设我有一个集合列表,并且我想获得该列表中所有集合的并集。有什么方法可以使用生成器表达式来实现吗?换句话说,我怎么能在列表中创建在所有集合的并集 直接 作为? 问题答案: 只需使用该方法即可。 这适用于任何可迭代的迭代器。

  • 我正在用两个实体构建web应用程序: 漫画-id、标题、发行日期、封面id、流派、作者、卷等 这两个类继承自抽象类书。Book类将为这两个类提供公共变量:id、title、releaseDate、coverID; 我正在使用Pattern Builder创建漫画和体积对象。但当我试图设置描述时,我得到了以下错误: 图书类: 公开摘要类书籍 我的漫画课: 或者有更好的解决方案吗? 谢谢

  • 问题内容: 在Java中,可以轻松地生成无限流。但是,我需要生成一个最终将完成的流。 想象一下,例如,我想要目录中所有文件的流。文件的数量可能很大,因此我无法预先收集所有数据并通过它们(通过)创建流。我需要逐段生成序列。但是流显然会在某个时刻结束,并且像(或)这样的终端运营商需要对其进行处理,因此不适合在这里使用。 是否有任何合理的简便方法可以用Java实现,而无需自己实现整个Stream接口?

  • 问题内容: 我看到了许多生成器函数的示例,但是我想知道如何为类编写生成器。可以说,我想写斐波那契数列作为一个类。 输出: 为什么值没有打印出来?另外,我该如何为发电机编写代码? 问题答案: 您快要写完 Iterator 类了(我在答案末尾显示了Generator),但是每次使用调用对象时都会被调用,并返回一个generator对象。相反,要使您的代码以最少的更改和最少的代码行工作,请使用,这使您的

  • 问题 你想实现一个自定义迭代模式,跟普通的内置函数比如 range() , reversed() 不一样。 解决方案 如果你想实现一种新的迭代模式,使用一个生成器函数来定义它。 下面是一个生产某个范围内浮点数的生成器: def frange(start, stop, increment): x = start while x < stop: yield x

  • 考虑这个例子 我有一个函数,它以作为输入,并返回三个值,我想存储到三个不同的变量。下面的似乎工作正确 然而,当我试图创建相应的变量时,我得到了一个错误 你怎么认为? 我曾经在pandas apply()的返回多列中使用伟大的解决方案,但在当前的pandas中,此解决方案不再有效 谢谢!