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

有帮助吗?

解决方案

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.

其他提示

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top