|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThe Essence Pattern provides a way to enforce users of an object to enter valid properties for that object. A full description of the pattern can be found in the original paper here (PDF). In this article, I shall provide a C# implementation of this pattern. BackgroundIf you are providing an external interface to your code either as an API or because your code forms a tier in an n-tier system, then the Essence Pattern can be used to force other programmers to put valid, required fields into an object before they start using that object. One common situation where this is required is for key fields to be saved to a database. The user of the object must not attempt to save that object to the database without the key properties, or the database will complain. Of course, you could simply provide just one constructor that forces the programmer to enter all the required properties. In the simple case this is perfectly acceptable. However, if you are exposing an external interface, you may also want it to be COM wrappable. In this case, you can only have one, parameterless constructor which disallows that particular strategy. Also, what if there are a lot of required parameters, some of which need to be calculated or read from a data source? Are you going to make the user of your object store all these in local variables before they can construct your object? The Example CodeThe code sample with this article shows a very simple implementation of the Essence Pattern for a small class representing a contact. The The first thing we do is create the One of the two important methods of the // Validates the essence fields.
private bool Validate()
{
// Check we have a firstname
if (mFirstName.Length == 0)
return false;
// ... and a last name
if (mLastName.Length == 0)
return false;
// Check email exists and if it does, then check it's valid.
if (mEmail.Length == 0)
return false;
else
{
// Use a regular expression to match an email address.
System.Text.RegularExpressions.Regex emailReg =
new System.Text.RegularExpressions.Regex(
@"^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$",
System.Text.RegularExpressions.RegexOptions.CultureInvariant);
System.Text.RegularExpressions.MatchCollection results =
emailReg.Matches(mEmail, 0);
// If we didn't get a mtach, fail the validation
if (results.Count == 0)
return false;
}
// Getting this far means validation is good
return true;
}
The next stage is the creation of the real /// <summary>
/// Creates a <c>Contact</c> instance based on this essence.
/// </summary>
/// <returns>A new <c>Contact</c>
/// if this <c>ContactEssence</c> is valid,
/// otherwise a <c>null</c> reference.</returns>
public Contact CreateContact()
{
if (this.Validate() == true)
return new Contact(this);
return null;
}
As you can see, if the The final part of the puzzle is the // Private constructor can only be accessed by internal classes.
private Contact(ContactEssence xEssence)
{
// Copy required, immutable properties from essence
mEmail = xEssence.Email;
mFirstName = xEssence.FirstName;
mLastName = xEssence.LastName;
}
// We make the default constructor private and mark it as obsolete.
[System.Obsolete(
"Default constructor not valid -- use " +
"ContactEssence to create the Contace object", true)]
private Contact()
{
}
Both constructors are private. When the Finally, in the So how do we use the The example code shows the role of the // Cannot create contact directly this line
// of code will create an error
//Essence.Contact c = new Contact(new Contact.ContactEssence());
// Create the essence
Contact.ContactEssence essence = new Contact.ContactEssence();
// Add the first required field
essence.Email = "me@mydomain.com";
// Cannot create Contact yet ...
Contact invalidContact = essence.CreateContact();
if (invalidContact == null)
Console.WriteLine("Created NULL contact!");
// Fill in the rest of the required fields
essence.FirstName = "Dermot";
essence.LastName = "Gubbins";
// Try creating contact again
Contact validContact = essence.CreateContact();
if(validContact == null)
Console.WriteLine("Oops! This should be valid!");
else
{
// Add a phone number (optional)
// but not an address.
validContact.PhoneNumber = "(+44) 444 444";
// Display the valid contact.
Console.WriteLine("\nContact Created ...\n");
Console.WriteLine(validContact.ToString());
}
Points of InterestAs explained in the original paper the Essence Pattern can be used in object creational patterns to create multiple valid classes by changing one or more of the required fields and then creating a new instance of the main class. Additionally, the Essence can also act as a builder class.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||