How to implement Prototype pattern in Java?

Lets say you run a modelling agency.

You are creating an application to manage your models.

They are of different types – actors, male and female , can do anchoring , can play the role of video jockey , can act in cinema etc.

To design classes for the above use case , you could create a parent class named Artist and then a subclass for each role type. Whenever you need to create a new model you could create an instance of the subclass . Given the combination of attributes for the models that could lead to creating a lot of subclasses.

Or you can create a single class and have different types of attributes. Even in the case you have to instantiate all the attributes every time you create an object.

For example if you need a male anchor with no experience.

You create an Artist class with the fields name ,gender , experience , field etc.

And you can intialize the values like below:

artist.setGender("male");
artist.setExperience(0);
artist.setField("anchoring");
artist.setName("John");

Now if you need another model with the same attributes as above and with one more criteria of an age of 30 years , you have to create a new object repeating the above code :

artist.setGender("male");
artist.setExperience(0);
artist.setField("anchoring");
artist.setAge(30);
artist.setName("Tom");

This is not efficient.

Instead we can adopt the Prototype pattern.

The Prototype pattern lets you to create custom objects and then just create a copy of them and return to client. The client can use this copy to further customize them as per their requirement.

Let’s dive into the code.

In the below client code I am fetching custom artist objects from a registry and then modifying it according to my needs:

package creational.prototype.pattern;

public class Client {

	public static void main(String a[]) {

		// Get a male artist who is an anchor
		ArtistRegistry registry = new ArtistRegistry();
		Artist artist = registry.getPrototype("maleAnchor");

		// Set his name
		artist.setName("Batista");

		// display the custom artist made , client just had to set the name!
		System.out.println(artist);

		// Another example
		// Let's create a new prototype from existing prototype and add it to registry

		Artist femaleArtist = registry.getPrototype("femaleModelNoExperience");
		femaleArtist.setField("cinema");

		// we have created a new prototype model who is female, has no experience and
		// tagged to cinema field
		// Now lets add this prototype to registry
		
		registry.addPrototype(femaleArtist, "femaleCinemaFresh");
		
		
		//Now lets get the prototype again and assign a name and age 
		
		Artist femaleCineArtist = registry.getPrototype("femaleCinemaFresh");
		
		femaleCineArtist.setAge(22);
		femaleCineArtist.setName("Rithika");
		
		System.out.println(femaleCineArtist);
		

	}
}

ArtistRegistry is a registry containing different types of models.

Custom artist objects are fetched from the registry and new objects are created as per modelling requirements.

Here is the code of ArtistRegistry:

package creational.prototype.pattern;

import java.util.HashMap;
import java.util.Map;

public class ArtistRegistry {

	
	Map<String,Artist> artistRegistry = new HashMap<String,Artist>();
	
	
	
	ArtistRegistry(){
		
		loadInitialRegistry();
	}

	
	Artist getPrototype(String type) {
		
		Artist cloneArtist = null;
		
		try {
			cloneArtist = (Artist)artistRegistry.get(type).clone();
		}catch(CloneNotSupportedException e) {
			
			e.printStackTrace();
		}
		
		return cloneArtist;
		
	}

	
	public void addPrototype(Artist artist, String type) {
		
		artistRegistry.put(type, artist);
	}

	private void loadInitialRegistry() {
		
		
		Artist maleanchor = new Artist();
		maleanchor.setGender("Male");
		maleanchor.setField("anchoring");
		
		artistRegistry.put("maleAnchor", maleanchor);
		
		Artist femaleModel = new Artist();
		femaleModel.setGender("Female");
		femaleModel.setExperience(0);
		
		artistRegistry.put("femaleModelNoExperience", femaleModel);
		
		
	}
}

There is an initial set up with custom artist objects ‘Male Anchor’ and ‘Female Model with no experience’. They can be fetched from the registry (by cloning them so that a new instance is returned) and returned to the client.

The method getPrototype() does the cloning.

Below is the Artist model class:

package creational.prototype.pattern;

public class Artist implements Cloneable {

	public String name;

	public int age;

	public String gender;

	public String field;

	public int experience;

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

	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getField() {
		return field;
	}

	public void setField(String field) {
		this.field = field;
	}

	public int getExperience() {
		return experience;
	}

	public void setExperience(int experience) {
		this.experience = experience;
	}

	@Override
	public String toString() {
		return "Artist [name=" + name + ", age=" + age + ", gender=" + gender + ", field=" + field + ", experience="
				+ experience + "]";
	}

}

It implements Cloneable interface which allows for cloning objects from existing ones.

Our cloning machines are ready.

Below is the output on running the application :

Artist [name=Batista, age=0, gender=Male, field=anchoring, experience=0]
Artist [name=Rithika, age=22, gender=Female, field=cinema, experience=0]

New objects made from custom predefined objects!

The Gang of Four define Prototype pattern as

Specify the kinds of objects to create using a prototypical instance and create new objects by copying this prototype.

We have done exactly that.

Here is the entire code :

https://github.com/vijaysrj/designPatternsGoF/tree/master/src/creational/prototype

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s