如何在保持一致引用的同时复制对象?

flo*_*oon 10 java oop copy

我想为我正在进行的游戏实现一个检查点系统,为此我需要复制一个级别内的所有可变对象,以便创建一个级别的独立副本.在一个简化的例子中,我的类看起来像这样:

public class GameObject
{
    ...
    private Level level;
    ...
}

public class Level
{
    ...
    private List<GameObject> gameObjects;
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是有一个问题:当我想要复制一个级别及其对象时,引用变得不一致.例如,我可以深度复制我的Level-instance并深度复制所有gameObjects.但是当我这样做时,GameObject中的Level-reference不再指向"正确"(新)级别.在这种情况下,我可以为每个对象调用一个方法并重置其级别.但随着越来越多类型的对象被包含,这将变得越来越复杂,因为对象可能或可能没有自己创建的对象集,然后这些引用也必须更新等等.

是否存在类似于这种情况的设计模式,或任何特定于Java的问题,使这个问题变得更容易?

编辑

我刚才有一个想法:如何为每个GameObject创建一些包装类,如下所示:

public class GameObjectWrapper
{
    ...
    private long gameObjectID;
    private Level level;
    ...
}
Run Code Online (Sandbox Code Playgroud)

这将作为对需要引用的所有对象的引用.每个GameObject都会获得一个唯一的id,而level将有一个地图将每个id链接到一个真实的GameObject(类似的东西GameObject Level.getObject(long id)).虽然这可能会奏效,但我仍然觉得必须有更好的解决方案.

编辑:进一步澄清

似乎我没有让我的问题足够清楚,所以我将简化并概括一点:

我有两个示例对象(objectAobjectB):objectA包含对它的引用objectBobjectB包含对它的引用objectA.

像这样的东西:

public class MyObject
{
   private MyObject partner;

   ...

   public MyObject shallowCopy()
   {
        return new MyObject(partner);
   }
}
Run Code Online (Sandbox Code Playgroud)

我想复制两者.使用浅拷贝,我得到两个新对象:newObjectAnewObjectB.然而,newObjectA存储的引用(应该指向newObjectB)仍然指向原始引用,objectB反之亦然.

MyObject objectA = new MyObject(), objectB = new MyObject();

objectA.setPartner(objectB);
objectB.setPartner(objectA);

MyObject newObjectA = objectA.copy(); //newObjectA's partner now is objectB (instead of newObjectB)
MyObject newObjectB = objectB.copy(); //newObjectB's partner now is objectA (instead of newObjectA)
Run Code Online (Sandbox Code Playgroud)

现在,我可以 "只是"遍历所有对象并将旧对象映射到新对象,但这对我来说似乎很慢而且太复杂了.解决此问题的最简单,最有效的方法是什么?

注意:我考虑将此发布到gamedev.stackexchange.com,但我发现这更像是一个编程和设计特定问题,而不是游戏开发特定问题.

Bub*_*tan 3

如果您只是复制Level对象并希望其列表中的引用指向新副本,那么您不能在复制方法中循环遍历它们吗?

像这样的东西:

class Level {

    List<GameObject> gameObjects;

    Level copy() {
        Level level = new Level();
        level.gameObjects = new ArrayList<>(gameObjects.size());
        for (GameObject gameObject : gameObjects) {
            level.gameObjects.add(gameObject.copyWithReference(level));
        }
        return level;
    }
}

class GameObject {

    Level level;

    GameObject copyWithReference(Level level) {
        GameObject gameObject = new GameObject();
        gameObject.level = level;
        return gameObject;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

您可以有一个容器用于gameObjects

class GameObjectSet {

    Level level;
    List<GameObject> gameObjects;

    GameObjectSet copy(Level newLevel) {
        GameObjectSet gameObjectSet = new GameObjectSet();
        gameObjectSet.level = newLevel;
        // copy all gameObjects and make them point to new gameObjectSet
        return gameObjectSet;
    }
}
Run Code Online (Sandbox Code Playgroud)

GameObjectSet现在您将在课堂上Level和课堂上都有对 a 的引用GameObject