C SC 335 Flyweight Design Pattern

Constructing many objects is a relatively slow operation for a computer to perform. It takes CPU time and memory to store objects; therefore, when possible, in large programs we should try to reduce the number of objects we create while the program is running. But how can we do this?

One way to reduce object construction is to flyweight objects, if possible. Flyweighting means reusing objects and variables, usually ones that are not changeable. If instances of a class that contain the same information can be used interchangeably, the Flyweight pattern allows a program to avoid the expense of multiple instances that contain the same information by sharing one instance.

The Flyweight pattern was used by the designers of Java for better performance. For example, equivalent Strings in Java are flyweighted; if a program creates two String references that refer to the String “hello”, both reference variables will refer to the same string object. This saves time and memory by avoiding creating a second identical “hello” object. It is legal and safe to do this, because Strings are immutable in Java—they cannot be directly modified. So there is no danger by having both variables point to the same String, since they cannot modify it.

How can we implement a flyweighting system? If we have a class whose instances are unchangeable and often equivalent, we can make our class’s constructor private, then create astatic method to get a “new” instance of the class. If this “new” instance is one that we have never created before, then we actually construct a new object. However, if the “new” instance is equivalent/identical to another previously constructed instance, we can just return a reference to the existing instance.

Example from Biology Software Project: Biologists who analyze proteins using computational methods typically have characters and strings to represent them. Proteins are made up of linear structures of 20 different molecules, called amino acids. For convenience and brevity, amino acids are usually represented by characters. For example, the amino acid tryptophan is represented by a 'W' and the amino acid methionine is represented by 'M'. A peptide, a chain of amino acids, can be represented as a string of these characters, "NPVGLRQGID", for example.

An inspired but not very astute young computational biologist decided to write a class representing a single amino symbol. Her class, AminoAcid, can be used to make immutable (can't be modified) AminoAcid objects that can be strung together using lists and other linear data structures to represent a peptide. The problem is that since peptides can be very long, these lists of objects take up an unnecessary amount of memory. Typical lengths used for certain types of analysis can be around 500 to 1000 amino acids long. Rewrite the AminoAcid class so programs that use it can be more memory efficient by guaranteeing that no two objects with the same exact state can be instantiated and therefore stored in memory.

public class AminoAcid {

private String myName;

private char myToken;

public AminoAcid(String name, char token) {

myName = name;

myToken = token;

}

public String getName() {

return myName;

}

public char getToken() {

return myToken;

}

}

Currently the code to construct one protein object and displays its state would like this

AminoAcid aminoAcid0 = new AminoAcid("tryptophan", 'W');

// Output:

System.out.println(aminoAcid0.getName()); // tryptophan

System.out.println(aminoAcid0.getToken()); // W

Question for Thought

How would you modify the class so a static method getAminoAcidInstance returns a reference to the single shared object with the given token ('W' here) even though there may be thousands of requests for 'W'. Hint: There should be no public constructor. Use a static method that will return a reference to the object if the key, which is 'W' here exsits.

AminoAcid aminoAcid = AminoAcid.getAminoAcidInstance('W');

System.out.println(aminoAcid.getName());

System.out.println(aminoAcid.getToken());

You will find a HashMap useful. A HashMap can store a reference to the single instance of AminoAcid if it exists by mapping the AminoAcid value to the Character key.

import java.util.HashMap;

public class AminoAcid implements AminoAcidSymbol {

// Make the constructor private to force use of the public static method

private AminoAcid(String name, char token) {

myName = name;

myToken = token;

}

// Can call this only the first time someone asks for an AminoAcid

private static void makeMapTheFirstTime() {

AminoAcid ala = new AminoAcid("Alanine", 'A');

AminoAcid arg = new AminoAcid("Arginine", 'R');

AminoAcid asn = new AminoAcid("Asparagine", 'N');

// Omitting the other 17 to save space. Only 3 AminoAcids in this answer.

mySymbolTable = new HashMap<Character, AminoAcid>();

mySymbolTable.put('A', ala);

mySymbolTable.put('R', arg);

mySymbolTable.put('N', asn);

}

private static HashMap<Character, AminoAcid> mySymbolTable = null;

Consider using methods of HashMap

In particular put(K, V), V get(K), and containsKey(K)