BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 1.1+

Flyweight Design Pattern

The flyweight pattern is a design pattern that is used to minimise resource usage when working with very large numbers of objects. When creating many thousands of identical objects, stateless flyweights can lower the memory used to a manageable level.

What is the Flyweight Pattern?

The flyweight pattern is a Gang of Four design pattern. This is a structural pattern as it defines a manner for creating relationships between classes. The flyweight design pattern is used to reduce the memory and resource usage for complex models containing many hundreds, thousands or even hundreds of thousands of similar objects.

When you need to create a very large number of objects, each requires an amount of memory to store the object's state. Even if the storage requirements for each individual object are small, the number of objects may cause the overall memory usage to be high. Depending upon the scenario and the target environment, the memory usage may be so high that the program cannot execute.

In some cases, the objects being created may include information that is often duplicated. Where this is true, the flyweight pattern can be used. When this pattern is applied, the properties of the objects that are shared and are reasonably unchanging are moved into flyweight objects. For each of the main objects that use the shared data, only a reference to the appropriate flyweight object is required. This can drastically reduce the memory used by each of the main objects.

The flyweight pattern uses the concepts of intrinsic and extrinsic data. The intrinsic data is held in the properties of the flyweight objects that are shared. This information is stateless and generally remains unchanged, as any changes would be effectively replicated amongst all of the objects that reference the flyweight. Extrinsic data can be stateful as it is held outside of a flyweight object. It can be passed to methods of a flyweight when needed but should never be stored within a shared flyweight object.

The flyweight design pattern often uses a variation on the factory method pattern for the generation of the shared objects. The factory receives a request for a flyweight instance. If a matching object is already in use, that particular object is returned. If not, a new flyweight is generated. Usually the full set of available flyweight objects is held within the factory in a collection that can be accessed quickly, such as a Hashtable.

An appropriate use of the flyweight pattern is for a simulation that contains many similar items. For example, a war strategy simulation game may include the ability to monitor every individual unit on the battlefield. For a large battle, this could easily involve tens of thousands of infantry and vehicles. Holding the details of each object individually would use prohibitively large amounts of memory. However, as most units would share a set of stateless information, this could be extracted from the main objects to be held in flyweight objects.

Implementing the Flyweight Pattern

Flyweight Design Pattern UML

The UML class diagram above describes an implementation of the flyweight design pattern. The items in the diagram are described below:

  • FlyweightBase. This abstract class defines the members of the flyweight objects. This can be replaced with a simple interface if no base functionality is to be defined for inheritance by the flyweight classes that subclass it.
  • ConcreteFlyweight. Inheriting from the FlyweightBase class, the ConcreteFlyweight types provide the functionality and stateless information that will be shared amongst other objects.
  • UnsharedFlyweight. Although the flyweight design pattern enables sharing of information, it is possible to create instances of concrete flyweight classes that are not shared. In these cases, the objects may be stateful.
  • FlyweightFactory. This class holds references to each of the flyweight objects that have already been created. When the GetFlyweight method is called from client code, these references are checked to determine if an appropriate flyweight is already present. If one is, it is returned. If not, a new object is generated, added to the collection and returned.

The following shows the basic code of the flyweight design pattern implemented using C#. For compatibility with .NET 1.1, the flyweight collection is held in a simple Hashtable. In later versions of the .NET framework, you could use a generic dictionary for the same purpose.

public abstract class FlyweightBase
{
    public abstract void StatefulOperation(object o);
}


public class FlyweightFactory
{
    private Hashtable _flyweights = new Hashtable();

    public FlyweightBase GetFlyweight(string key)
    {
        if (_flyweights.Contains(key))
        {
            return _flyweights[key] as FlyweightBase;
        }
        else
        {
            ConcreteFlyweight newFlyweight = new ConcreteFlyweight();

            // Set properties of new flyweight here.

            _flyweights.Add(key, newFlyweight);
            return newFlyweight;
        }
    }
}


public class ConcreteFlyweight : FlyweightBase
{
    public override void StatefulOperation(object o)
    {
        Console.WriteLine(o);
    }
}


public class UnsharedFlyweight : FlyweightBase
{
    private object _state;

    public override void StatefulOperation(object o)
    {
        _state = o;
        Console.WriteLine(o);
    }
}
19 November 2008