0

I just learned prototype design Pattern.

I am a Java guy so obviously I learned Java Implementation. but i have some confusion about the Example implementation from the different source.

I think these examples might be wrong

Prototype Using new
Prototype Using new

above examples using new keyword in their clone method implementation.

the following example is good as it is exactly implements stated in Prototype definitions.

Prototype Without new

Now, my questions are,

  • why the above two examples uses new keyword ?
  • IF we use new keyword then do not the benefits of this pattern vanished ?
  • If i am wrong about above 2 examples than please mention the reasons in your answer .
  • and finally , which is the correct implementation ? why ?

Updates 28-06-2013

thanks for all for their answers and comments.though some of them still did not understand what was asked here .

the above all works is a preface to actual problem , what i h =ave been trying to solve is I have a Cache object which contains 30K entries in it in the order of they entered. Now in the UI i have to display this data in ascending or descending order based on the user choice. I can only work on Cache object itself so thought that why not clone given cache object using the prototype pattern and then re arrange the contents of cloned cache object by the user choice and display to them ?

Did i make the correct decision ? I am not the enemy of new operator but do it not be very expensive in this specific case. ?

Note

neither loading of data into cache is not in my hand nor any UI side data manipulation.

what i can do is only manipulate the prefilled cached data .

Thanks Mihir

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
Mihir
  • 2,480
  • 7
  • 38
  • 57
  • 1
    You need to use `new` to create an object , if there aren't any object then what will you `clone()` ! – AllTooSir Jun 26 '13 at 08:20
  • The 1st is fine. They create _the_ prototype with `new` and then they clone it with `doClone`. The 2nd is the same... – Balint Bako Jun 26 '13 at 08:20
  • The third example uses `new` as well - have a look at the sequence diagram – Marco Forberg Jun 26 '13 at 08:22
  • there are no differences, because you cannot find the new keyword in the 3rd. one it doesn't mean it does not use new, in fact the super.clone() method uses new keyword, and it has to do so –  Jun 26 '13 at 08:30
  • @Mihir Serial downvoting can get you in trouble ! – AllTooSir Jun 28 '13 at 06:39

2 Answers2

2

Cloning is not about avoiding the use of new operator but creating a new instance that has the same state (values of its member fields) as that of the object that's being cloned.

So, you may either use clone() (that would internally be using new only) or create a new instance yourself (using a copy constructor or firing the setters explicitly post-construction) to mirror the state of the source object.

In your third example

clonedAnimal = (Animal) super.clone();

is actually invoking Object.clone() which creates the new instance here.

Also, try removing the clonedAnimal.setXXX() methods afterwords and it should still work since by default a shallow copy should have already been created by Object.clone(). They probably left them there for ease of understanding.

EDIT : (in response to OP's comments)
When you clone() you're basically delegating the new obj() call to the original object itself.

Why? So, that it copies the state as well. But, this doesn't guarantee that new wasn't used down the line; just that the object's class exposed a clone() implementation to take the burden of creating copies on itself.

Here's where things get interesting. Object.clone() is a native method. It's been implemented within the JVM that does C++ stuff to allocate heap memory and all other jazz. But, it's practically the same thing that JVM does when you call the new operator yourself (except copying of the object state as well).

But, this isn't the important point. What's important is to understand when return super.clone() would truly return an independent cloned object. The answer is mostly NO even for moderately complex objects because it does a shallow copy.

So, if your cache object is heavy on resources you would have to provide your own implementation for cloning of cache objects. To just give you an example: let's assume your cache had a LinkedHashMap of recently accessed objects. If you rely on super.clone() alone; your cloned cache object (by virtue of a shallow copy) would only have a copy of the reference to your Map which means if you purge one of your caches the other would also get purged.

Hence, when I say new is employed via delegation to clone(); I'm referring to classes providing their own deep-copy implementations (almost always the case) for cloning. And, since they are doing it within the boundaries of Java their first step (barring Reflection API) is to instantiate a new object using the new operator.

Ravi K Thapliyal
  • 51,095
  • 9
  • 76
  • 89
  • my question is not about new operator. i have to clone a cache object which is very heavy and will take so much resource if we use new to clone it . another thing who says that super.clone uses new operator internally ? – Mihir Jun 28 '13 at 04:36
  • @Mihir, I've added my response as an edit to my answer itself. Please, have a look at it. – Ravi K Thapliyal Jun 28 '13 at 14:01
1

In Java you can create objects in two ways: by using new or by using the cloneable interface and calling super.clone(). You might want to take a look at this question, which discusses Java's cloneable interface. Cloneable is essentially Java's own implementation of the prototype pattern. As it states the cloneable interface has several flaws. To avoid these you must use new somewhere in your code.

An alternative to cloneable is to provide a copy constructer, i.e., public MyClass(MyClass other) {.... One disadvantage of doing this, is that you must declare the exact class of the created type, which the prototype pattern tries to prevent. Example 1 has a solution to this however.

As a comment for your examples

  1. This uses the copy constructor approach. It also provides a nice wrapper method doClone, which makes the client unaware of the actual class instantiated. It thereby doesn't have the disadvantage of the copy constructor mentioned above. You can say it kind of "encapsulates" or hides the new keyword.
  2. This example is broken. Do not do this! It only creates a new object, but do not copy its state. This is a violation of the prototype pattern as well as the clonable interface!
  3. This is a proper implementation of the cloneable interface. Calling super.clone() should be used whenever implementing the cloneable interface. It does however also caries the problems with the cloneable interface.

My personal opinion is that the first seems as the preferable solution, though I have however never used the prototype pattern or cloneable interface thoroughly.

Community
  • 1
  • 1
Tobber
  • 7,211
  • 8
  • 33
  • 56