Closed Lab #8: The Flyweight Pattern 1 Overview

CpSc 215: Software Development Foundations
Fall 2014
Closed Lab #8:
The Flyweight Pattern
There are four objectives to this closed lab. First, you will gain additional experience developing
classes that define static methods, fields, and initializers. Second, you will gain additional experience
working with the Java IO library. Third, you will be introduced to the Flyweight pattern, a cousin
of the Singleton pattern discussed in class. Finally, you will gain some insight into the memory
footprint associated with Java objects.
Flyweight Pattern
In designing object-oriented systems, it is convenient to represent all data elements within a program
as objects. This enables developers to adopt a uniform programming approach that is independent
of the differences between scalar types and reference types. In some cases, however, the number of
data elements that need to be managed is large, making it prohibitively expensive to use a single
object per data element. Consider, for example, a word processing application in which each character is represented as an object. This could get very expensive1 !
The Flyweight pattern is a cousin of the Singleton pattern. Its intent is to enable object-based
representations of fine-grained data elements through an efficient object sharing strategy. As you
will see, the approach is very similar to that prescribed by the Singleton pattern.
You are required to develop the following classes. In doing so, it is up to you to decide on the most
appropriate accessibility modifiers (e.g., public, private) to use when declaring your fields, methods,
and constructors. Your TA will check to see that you have made the right choices.
• CharacterA. This class will be used to represent a single character. More precisely, the class
will serve as a basic wrapper for an element of type char. The class should provide a constructor
that accepts a single argument — namely, the char value to be wrapped by the constructed
object. The class should also provide a suitable implementation of toString().
• CharacterB. This class will begin as an exact copy of CharacterA. You will then apply the
following changes: First, you should prevent instances of CharacterB from being constructed
by clients. Next, you should define a static method, createCharacter(), to enable clients to
retrieve a reference to a CharacterB object. The particular object returned should depend on
the char argument passed to the method. So, for example, a call to createCharacter() with ‘a’
passed as argument should yield the CharacterB object that wraps ‘a’.
should create each of the required Character wrappers at load-time, without an
explicit call placed by the programmer. When createCharacter() is invoked, it should simply
return a reference to the appropriate CharacterB object.
This example comes from the Gang of Four’s famous text, Design Patterns: Elements of Reusable Object-Oriented
Software. The Singleton and Flyweight patterns were originally described by these authors.
CpSc 215: Software Development Foundations
Fall 2014
• MainDriverA. This class will implement a simple “echo” application, similar to the application
you developed in a previous closed lab. It will begin by reading the contents of the text file
passed as argument and storing each character that is read within an array of CharacterA
objects. Next, it will iterate through the array and print out each object; the result should
exactly match the contents of the input text file. Finally, the application will report the
approximate amount of memory consumed by the objects within the CharacterA array.
Note that MainDriverA should allocate an array (of CharacterA) that is exactly the right size
to hold the contents of the text file – no larger, no smaller. (Hint: You can determine the
number of bytes in a file using one of the methods provided by the class.)
• MainDriverB. This class will implement the same logic as MainDriverA. The only difference is
that the implementation will use CharacterB instead of CharacterA.
Memory Usage
To retrieve the amount of heap space available within the Java virtual machine, you should use the
following code fragment:
long freeMemory = Runtime.getRuntime().freeMemory();
Recall that Java is a garbage collected language. If you invoke this method at various points
in your program, you might see surprising results if the garbage collector is invoked unexpectedly.
To receive full credit for this lab, you must demonstrate that you have satisfied the above requirements. When you think you are ready, ask one of the TAs to check your solution. When they have
checked your name off of their list, you are free to leave. If you are unable to complete the lab
before the end of the period, but have made a reasonable attempt, you will receive 1/2 credit for
the day. If the TA feels that you have not made a reasonable attempt, you will not receive any
credit for your participation.
You may work independently or with one partner. You must not discuss the problem or the solution
with classmates outside of your group. Keep this in mind before you choose to work independently.