当父类始终是子类时,如何将整个层次结构设计为具有*不可变*父字段? [英] How to design entire hierarchy to have an *immutable* parent-field, when the parent-type is always a sub-class?

查看:297
本文介绍了当父类始终是子类时,如何将整个层次结构设计为具有*不可变*父字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Heirachy:

LineEntityType
   SingleLineEntity
   BlockEntity

块可以包含其他块或单行实体。所有实体都可以有一个父项,它始终是 BlockEntity

Blocks can contain other blocks or single line entities. All entities can have a parent, which is always a BlockEntity

我想要做这样的事情:

I want to do something like this:

BlockEntity rootBlock = new BlockEntity(...);
block.assignChildren(new LineEntityType[]  {
   new SingleLineEntity(...)
   new BlockEntity(...)
   new BlockEntity(...)});

所以父块对象( rootBlock )重复每个孩子(防御副本),并同时添加自己作为父母:

so the parent block object (rootBlock) duplicates each child (defensive copies) and at the same time adds itself as the parent:

BlockEntity(LineEntityType[] children)  {
   for(LineEntityType[] children)  {

      //Duplicate the array
      childEntitiesWithParentAssigned = Arrays.copyOf(children, children.length);

      //Duplicate each child, adding "this" as the parent
      for(int i = 0; i < children.length; i++)  {
         child = childEntitiesWithParentAssigned[i];
         childEntitiesWithParentAssigned[i] = child.getCopyWithParentAssigned(this);
      }
   }
}

但是这是不可接受的,因为父类 LineEntityType 有多个对子类型的引用, BlockEntity (循环依赖) 。

This is what I have so far, but it's unacceptable because the parent class, LineEntityType has multiple references to the child type, BlockEntity (circular dependency).

public abstract class LineEntityType  {

   private final BlockEntity parent;

   public LineEntityType(...)  {
      this(..., null);            //Root entity
   }
   public LineEntityType(..., BlockEntity parent)  {
      this.parent = parent;
   }

   ...

   public abstract LineEntityType getCopyWithParentAssigned(BlockEntity parent);
}

我想出的唯一其他事情是明确分配父在分配子项之前:

The only other thing I've come up with is to explicitely assign the parent before assigning its children:

//null: No parent
BlockEntity rootBlock = new BlockEntity(..., null);

LineEntityType children = new LineEntityType[]  {
   new SingleLineEntity(..., rootBlock)
   new BlockEntity(..., rootBlock)
   new BlockEntity(..., rootBlock)});

rootBlock.setChildren(children);

但这需要孩子字段是可变的。

But this requires the children field to be mutable.

有关如何重新思考这个问题的任何想法,所以父域可以由父级分配,但是不可变,避免循环依赖?

Any ideas on how to rethink this, so the parent-field can be assigned by the parent, yet be immutable and avoid circular dependencies?

谢谢。 / p>

Thanks.

推荐答案

听起来你基本上说我想要Foo指向酒吧,酒吧指向Foo,但也希望两者都是不变的。这些是相互矛盾的要求,一般来说(一个对象必须先创建,那时候太晚了)。

It sounds like you're basically saying "I want Foo to point to Bar, and Bar to point to Foo, but also want both to be immutable". Those are mutually contradictory requirements, in general (one object must be created first, at which point it's too late).

这是在其他的构造函数期间创建一个。您可以使用构建器模式的一些变体来保持这一点:

The only way around this is to create one during the constructor of the other. You could use some variant of the builder pattern to keep this sane:

// Immutable
class Foo {
    private final Bar bar;
    public Foo(BarBuilder builder) { this.bar = builder.create(this); }
}

// Immutable
class Bar {
    private final Foo foo;
    public Bar(Foo foo) { this.foo = foo; }
}

class BarBuilder {
    public Bar create(Foo foo) { return new Bar(foo); }
}

Foo foo = new Foo(new BarBuilder());
Bar bar = foo.bar;

将此应用于您的特定设计留作读者的练习...

Applying this to your particular design is left as an exercise for the reader...

这篇关于当父类始终是子类时,如何将整个层次结构设计为具有*不可变*父字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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