e2rabi
e2rabi

Reputation: 4848

what is the benefit of prototype pattern in this case

I saw some code defines the prototype pattern in this way :

public abstract class Shape implements Cloneable {

   private String id;
   protected String type;

   abstract void draw();

   public String getType(){
      return type;
   }

   public String getId() {
      return id;
   }

   public void setId(String id) {
      this.id = id;
   }

   public Object clone() {
      Object clone = null;

      try {
         clone = super.clone();

      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }

      return clone;
   }
}

Two concrete classes extending the above class :

public class Rectangle extends Shape {

   public Rectangle(){
     type = "Rectangle";
   }

   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}
public class Square extends Shape {

   public Square(){
     type = "Square";
   }

   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

Create a class to get concrete classes from database and store them in a Hashtable :

public class ShapeCache {

   private static Hashtable<String, Shape> shapeMap  = new Hashtable<String, Shape>();

   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }


   public static void loadCache() {

      Square square = new Square();
      square.setId("2");
      shapeMap.put(square.getId(),square);

      Rectangle rectangle = new Rectangle();
      rectangle.setId("3");
      shapeMap.put(rectangle.getId(), rectangle);
   }
}

My question is in the getShape method what is the difference and benefit between these two implementations :

Implementation 1 :

  public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }

And : Implementation 2 :

 public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      // return (Shape) cachedShape.clone();
     return  cachedShape ;
   }

I tried the two implementations and they work well just I want to know the benefit if I use the first Implementation

Upvotes: 3

Views: 147

Answers (2)

GhostCat
GhostCat

Reputation: 140467

I have a heard time understanding how all your input actually relates to the final question you put in your text, but lets try: the fundamental difference is: option 1 creates a copy of the cached object each time.

Whereas option 2 ... gives you the cached object itself.

As you talking about a cache, and a getter method, the actual code to be found with option 1 is surprising to say the least.

In other words: most people would expect that a cache is about providing the same objects to its user (that is the whole point of a cache!).

So, my take here: it seems that cloning is important to your design. If so, then you should re-think your idea of having a cache there. Is that cache more like a "template engine" that contains "patterns" and allows you to duplicate those "patterns"? But in the end, the guiding factor here is not what we think, but what makes most sense in your domain. And that is something we can't help with.

Long story short: the classes and the functionalities you put into them ... do not exist in some vacuum. You create them to implement a "mental model" that exists to resolve a problem. And you are the person who should understand the problem you intend to solve. And that drives your implementation. And as said; we can't help with the exact details of that.

Upvotes: 4

Mark
Mark

Reputation: 1498

Implementation 1 returns a new object. Changing that object will not change the object in your shapeMap.

Implementation 2 return the exact object in your shapeMap. If you change that, the object in your shapeMap will be changed.

So it all depends on what exactly you wish to do with the result of your method.

Upvotes: 3

Related Questions