----

Prototype Pattern Example Cont..

Solution: Initially read user profile information only once into UserProfile object. This object can be used for display purpose. But if you want to update address, then first create a clone of UserProfile object, update the address in this cloned object as well as in the data base and then make the cloned object as the prototype. In case you want to revert or cancel the update you can just discard the cloned object. This way you can prevent expensive database operations by using prototype object

Lets update UserProfile.java to support cloning for prototyping.

public class UserProfile implements Cloneable{
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User id: " + id + ", name: " + this.name + ", address: "+ address;
}


        public Object clone() throws CloneNotSupportedException {
                   return super.clone();
        }
}

Client application can be updated, which now uses prototype object instead of reading updated information from the database each time. 

public class UserProfileApplication {
private  UserProfile prototypeUserProfile;
          public static void main(String args[]) {
                  try {
                        prototypeUserProfile = getUserProfile(12345);
                        display(prototypeUserProfile);

                        UserProfile clonedProfile = (UserProfile) prototypeUserProfile.clone();
                        boolean update = updateAddress(clonedProfile, "YYY Mumbai, India");
                        if(update) {
                               // If the update is successful then replace the prototype with the cloned object.
                               // The prototype now holds updated information and now can be used for
                               // subsequent display or to perform any update operation.
                                 prototypeUserProfile = clonedProfile ;
                       }
                        // If the update fails then discard the cloned object and free the memory
                        clonedProfile = null;
                        display(prototypeUserProfile);
                      } catch (CloneNotSupportedException e) {
                                e.printStackTrace();
                      }
           }
          private static boolean updateAddress(UserProfile userProfile, String address) {
                    int userId = userProfile.getId();
                   // Update the address in the database for the userId update the address in the clone
                    userProfile.setAddress(address);
                    // return success or failure based on transaction status
                    return true;

           }
         // This method will read the user profile information from the database 
private static UserProfile getUserProfile(int userId) {
                 // check if userId exists in the database and if exists
                 // read all the user profile information and set to this object as shown
                    UserProfile userProfile = new UserProfile();
                    userProfile.setId(userId);
                    return userProfile;
           }
           private static void display(UserProfile userProfile) {
                    System.out.println("User details :" + userProfile);
           }
}

Output:

User details :User id: 12345, name: Guest, address: Delhi, India
User details :User id: 12345, name: Guest, address: YYY Mumbai, India

The prototype objects also can be used to maintain cache in the application where caching is used.
There are lots of other situations where prototype pattern can be used.

Let us consider another example where we have to develop a photo application where a user should be able to do the following 
1. Select a compressed image from either local disk or from the network
2. Create copies of the image and apply different effect to each copy
3. View all the images with different effects at the same time

When the user selects an image from either local disk or the network, the application will
1. Load the image into the memory,
2. Decompress it and make the image object ready for display.

Problem:
These two operations are time consuming and can't be repeated if user wants to create copies and apply different effects. 

Solution:
We can use prototype pattern here. First time after the image object is created and made ready for display, subsequent copies then can be created using the already created image object. Different effects can then be applied to the cloned image objects. The content of the cloned object is same as that of the already created image object but differs only the effect.

No comments :

Post a Comment