子类化构建器模式与Java中的扭曲

时间:2017-06-13 16:31:56

标签: java design-patterns

我想为抽象类创建一个抽象的构建器(虽然它不需要是抽象的),抽象类的每个子类都可以有自己的子类Builder。我还希望每个字段/属性都填写AKA强制。所以我使用Builder Pattern with Twist(https://blog.jayway.com/2012/02/07/builder-pattern-with-a-twist/)。

我遇到了一个问题,这个问题在我之前问过的这个问题中得到了解决:Generic parent object cannot be returned as child without cast 但是现在我无法创建多个具体/子类构建器。

最后,我想实例化像这样的对象:

ConcreteBuilderA.getBuilder().setValue(Object value).setConcreteValue(int num).build()

其中setValue()属于AbstractBuilder,其他属于concreteBuilder。

我最好的镜头是(大大简化和抽象化):

/**
* @param<B> the type of builded object it should return.
* @param<S> the type of the builder subclass.
* @param<L> the type of the linking interface.
*/
public abstract class AbstractBuilder<B extends AbstractClass, S extends AbstractBuilder, L> implements ValueSetter<L>
{
    protected B buildable;
    @Override
    public L setValue(Object value)
    {
         //set the value
         return this;//<-- returns Object, blocking the use of the ConcreteBuilder methods
    }
    public abstract B build();
}

|

public class ConcreteBuilder extends AbstractBuilder<ConcreteProduct, ConcreteBuilder, ConcreteValueSetter> implements ConcreteValueSetter
{
    @Override
    public ConcreteBuilder setConcreteValue(int num)
    {
        //set value
        return this;
    }
    @Override
    public ConcreteProduct build();
    {
        return buildable;
    }
}

|

public interface ValueSetter<L>
{
     public L setValue(Object value);
}

|

public interface ConcreteValueSetter
{
    public ConcreteBuilder setConcreteValue(int num);
}

如标记所示,当切换&#39;到子类构建方法。 我已经为此做了一些变种,我无法让它发挥作用。

所以我真的很想知道这是否可行。如果是,我想看看如何。如果不是我想知道一些符合我要求的技术。

提前致谢!

2 个答案:

答案 0 :(得分:1)

我在Federico Peralta Schaffner的帮助下找到了答案。 我很可能在我的真实项目中使构建器变得复杂。 所以这里是Builder-with-a-twist + inheritance的代码:

/**
 *
 * @param <P> the type of the product.
 * @param <L> the linking interface.
 */
public class AbstractBuilder<P extends AbstractClass, L> implements ValueSetterOne<L>, ValueSetterTwo<L>{

    protected P toBeBuild;
    @Override
    public L setValueTwo(int value) {
        //set value
        return (L) this;
    }
    @Override
    public ValueSetterTwo<L> setValueOne(int value){
        //set value
        return this;
}

|

public class ConcreteBuilder extends AbstractBuilder<ConcreteClass, NameSetter> implements NameSetter, Optional{
    public static ValueSetter<NameSetter> getBuilder()
    {
        AbstractBuilder<ConcreteClass, NameSetter> builder = new ConcreteBuilder();
        builder.toBeBuild = new ConcreteClass();
        return builder;
    }

    @Override
    public Optional buildName(String name) {
        this.toBeBuild.setCharacterName(name);
        return this;
    }

    @Override
    public ConcreteClass build() {
        return this.toBeBuild;
    }

    @Override
    public Optional addExtraObject(Object extra) {
        System.out.println("test");
        return this;
    }
}

|

public interface ValueSetterOne<L> {
    public ValueSetterTwo<L> setValueOne(int value);
}

|

public interface ValueSetterTwo<L> {
    public L setValue(int value);
}

|

public interface NameSetter {
    public Optional buildName(String name);
}

|

public interface Optional {
    public ConcreteClass build();
    public Optional addExtraObject(Object extra);
}

然后测试它: ConcreteBuilder.getBuilder().setValueOne(0).setValueTwo(1).buildName("tricky").addExtraObject(args).build();

答案 1 :(得分:1)

您的问题是懒惰编程技术的症状。 试试这个;假装你是一名专业软件开发人员:

class MyComponent extends Component {
    state = {
        toggle: false
    }

   _fn1 = () => {
       this.setState(previousState => ({
           toggle: !previousState.toggle
       });
   }

   render() {
      const { toggle } = this.state;

      return (
          <button onClick={this.clickHandler}>
              Turn me {toggle ? 'on' : 'off'}
          </button>
      );
   }
}