The perfect copy

The Prototype pattern allows to initialize a new instance with the state of an other.
It’s easy to implement this pattern when the fields of the instance are are of primitive types (int, …).
However, when the fields are references, It can be more complex to clone all the members recursively.

The JVM can help us do that more easily with serialization.

Thanks to ByteArrayStream you can write an object, and read the copy of the object.

You want to make the both classes cloneable :

class B {}
class A implements Cloneable {
    public B b = new B();

    @Override
    protected A clone() {
        try {
            return (A) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

We write two unit tests to check if the cloning is ok :

class CloneTest extends TestCase {
    private A a = new A();

   @Test
   public void testInstanceClone() {
       assertTrue(a != a.clone());
   }

   @Test
   public void testInstanceMembreClone() {
       assertTrue(a.b != a.clone().b);
   }
}

testInstanceClone passes but testInstanceMembreClone fails.

The clone seems good but the cloned references are the sames.

To create a perfect clone you can use the JVM and serializable objects as in this snippet :

class Cloner {
     static <T> T clone(T t) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(t);
            oos.flush();
            return (T) new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

You can now use it in the clone method :

    @Override
    protected A clone() {
        return Cloner.clone(this);
    }

Now the two tests pass :).

This tip is not the most performant way to clone an instance but it’s the most reliable.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s