多态对象层次结构的构建器模式:可能用Java? [英] Builder pattern for polymorphic object hierarchy: possible with Java?

查看:131
本文介绍了多态对象层次结构的构建器模式:可能用Java?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个接口层次结构, Child 实现 Parent 。我想使用不可变对象,所以我想设计一个方便地构建这些对象的 Builder 类。但是,我有很多 Child 接口,我不想重复每个代码来构建 Parent

I have a hierarchy of interfaces, with Child implementing Parent. I would like to work with immutable objects, so I would like to design Builder classes that construct these objects conveniently. However, I have many Child interfaces, and I don't want to repeat the code for building Parents in each type of child builder.

所以,假设以下定义:

public interface Parent {
    public Long getParentProperty();
}

public interface Child1 extends Parent {
    public Integer getChild1Property(); 
}

public interface Child2 extends Parent {
    public String getChild2PropertyA();
    public Object getChild2PropertyB();
}

如何有效地实施构建器 Child1Builder Child2Builder ?他们应该支持如下操作:

How can I efficiently implement builders Child1Builder and Child2Builder? They should support operation like:

Child1 child1 = Child1Builder.newChild1().withChild1Property(5).withParentProperty(10L);

Child2 child2 = Child2Builder.newChild2().withChild2PropertyA("Hello").withParentProperty(10L).withChild2PropertyB(new Object());

我不想使用ParentProperty c $ c>为每个小孩建造者。

I don't want to implement a special case of withParentProperty for each child builder.

编辑添加第二个属性到 Child2 ,以澄清这不可能用简单的泛型完成我不是在寻找一种方法来组合 Child1 Child2 - 我正在寻找一种实现 Builder 系统不重复为每个子类构建父类的工作。

Edited to add second property to Child2 to clarify that this cannot be done with simple generics. I am not looking for a way to combine Child1 and Child2 - I am looking for a way to implement a Builder system that does not duplicate the work of building the parent class for every child class.

感谢任何帮助! / p>

Thanks for any help!

推荐答案

我想象的解决方案就像 好奇地循环模板模式 CRTP 。您可以定义一个基类来处理与父相关的初始化,但是您仍然可以找到两个样板 getParent() getThis()方法在每个派生的与孩子相关的构建器类中重复太多。

The solution I imagine is like the Curiously Recurring Template Pattern, or CRTP. You can define a base class to handle the parent-related initialization, but you still may find the two boilerplate getParent() and getThis() methods to be too much repetition in each derived child-related builder class.

查看:

abstract class ParentBase implements Parent
{
  @Override
  public final Long getParentProperty()
  {
      return parentProperty_;
  }


  protected void setParentProperty(Long value)
  {
      parentProperty_ = value;
  }


  private Long parentProperty_;
}


abstract class ParentBuilder<T extends ParentBuilder<T>>
{
  T withParentProperty(Long value)
  {
      getParent().setParentProperty(value);
      return getThis();
  }


  protected abstract ParentBase getParent();


  protected abstract T getThis();
}


final class ConcreteChild1 extends ParentBase implements Child1
{
  @Override
  public Integer getChild1Property()
  {
      return childProperty_;
  }


  public void setChild1Property(Integer value)
  {
      childProperty_ = value;
  }


  private Integer childProperty_;
}


final class Child1Builder extends ParentBuilder<Child1Builder>
{
  public Child1Builder()
  {
     pending_ = new ConcreteChild1();
  }


  public Child1Builder withChild1Property(Integer value)
  {
      pending_.setChild1Property(value);
      return this;
  }


  @Override
  protected ParentBase getParent()
  {
      return pending_;
  }


  @Override
  protected Child1Builder getThis()
  {
      return this;
  }


  private final ConcreteChild1 pending_;
}

如您所见, ParentBuilder type期望与派生类型协作,以允许它返回一个正确类型的实例。自己的这个引用将不会到期,因为 c ParentBuilder 当然是 ParentBuilder ,而不是说, Child1Builder 旨在维护流利的通话链接。

As you can see, the ParentBuilder type expects to be cooperating with a derived type to allow it to return a properly-typed instance. Its own this reference won't due, because the type of this within ParentBuilder is, of course, ParentBuilder, and not, say, Child1Builder as intended to maintain the "fluent" call chaining.

我欠 getThis()技巧到安格丽卡兰格的教程条目

这篇关于多态对象层次结构的构建器模式:可能用Java?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆