.NIT

Tuesday, June 07, 2005

Five Great Patterns for Dealing with References

Five Great Patterns for Dealing with References

Descriptor Pattern
The descriptor pattern, mixes best practices from the previous two patterns. Basically, a descriptor is a collection of instances of the class itself. Using this pattern, the CourseLevels class can be implemented as follows.

public class CourseLevels
{
public static CourseLevels Beginner = new CourseLevels();
public static CourseLevels Advanced = new CourseLevels();
public static CourseLevels VeryHigh = new CourseLevels();
public static CourseLevels Expert = new CourseLevels();
}


Because the instances are again static, descriptors are type safe, both in simple checks as in operation signatures, just like enumerations, as the following example shows.

if (MyCourse.Level == CourseLevels.Beginner) { … }

Methods on the Course class can also be specified elegantly.

public bool HasLevel(CourseLevels level)
{
return (Level == level);
}

Also descriptors can be extended, like constant collections. In the simple implementation above however, it is not possible to use display values other than the defined names of the instances. Luckily a straightforward extension to this implementation solves these issues, if necessary.

public class CourseLevels
{
public string DisplayValue;

public CourseLevels(string displayvalue)
{
DisplayValue = display;
}

public static CourseLevels Beginner = new CourseLevels("Beginner");
public static CourseLevels Advanced = new CourseLevels("Advanced");
public static CourseLevels VeryHigh = new CourseLevels("Very high");
public static CourseLevels Expert = new CourseLevels("Expert");
}

Still, descriptors have a fixed number of elements, just like enumerations and constant collections. And again, like the latter, retrieving the set of possible values requires reflection. In C#, in both patterns, an operation like the following takes care of this job.

public static CourseLevels[] GetValues()
{
ArrayList list = new ArrayList();

foreach (FieldInfo pi in type.GetFields())
{
list.Add((CourseLevels) pi.GetValue(type));
}

return (CourseLevels[]) list.ToArray(typeof(CourseLevels));
}