AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1751&pId=-1
Exemplifying the Factory Method Pattern inside the .NET Framework
page
by Xianzhong Zhu
Feedback
Average Rating: 
Views (Total / Last 10 Days): 34224/ 43

Introduction

Design patterns were introduced in Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides's seminal work "Design Patterns: Elements of Reusable Object-Oriented Software" (Addison-Wesley). In this book, 23 patterns were specified and described, which form the foundation of any study of the subject. Today, these patterns are still regarded as the essential core patterns. According to this masterpiece, The Factory Method pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. More precisely, Factory Method transfers the responsibility of instantiating a class to the factory class, and defers the instantiation to concrete factory classes.

In this article, I will try to detail into the Factory Method pattern in combination with the typical implementation cases in the .NET Framework.

Using Factory Method Pattern to Better OOP

All OO languages have an idiom for object creation. However, the core of any OOP is the management of the objects. Of course, the first step of the object management is creating the object. In C#, this action is performed using the new operator. In essence, the true important part of managing an object is when to create the object.

As is well known, the types representing abstract definitions, such as interfaces and abstract classes, can not be used to create their respective instances. This means that the objects we want to create is relevant to concrete object types. i.e. the creation of the object is sure to involve the detail of implementation, which result in the close coupling between the creator and the concrete created object. Let us take an example, in the next section, to look more closely at this case.

Figure 1 - The initial idea in creating the objects required in the graphic project

At the first face, the structure in Figure 1 appropriately tallies with the OO idea. In terms of the polymorphism principle, we can substitute interface IShape for the two concrete classes (in this case Square and Circle) in practical programming, so that we defer the concrete object type binding to the running time. However, due to the face that we can not directly create the interface, once the IShape typed object requires to be created, we have to create the concrete class related object, as shown below.

Listing 1

IShape shape=new Square();

Suppose that you are developing a graphic tool, there will be lots of objects, such as Square and Circle, required to be created. Obviously, in each of the modules in this sample project, with so many of the above lines stuffed in it, it is very difficult for you to decouple the module from the Square object. When we require to change the object to create to Circle, all the modules that invoke the new Square() operation will have to be modified, which undoubtedly increases the quantity of modification, as well as results in the inextensibility of the project and the non-reusability of the modules. In this sense, the abstract interface IShape concerning the above graphic objects has now become an unnecessary and failed design.

So, what should we do with the above case? Ideally, we would kill this kind of diversification above in the cradle period. For this, we will have recourse to the principle of "Encapsulate Variety." With this idea, we can introduce the Factory Method pattern to encapsulate the creation of objects--the IShape typed objects are the products the factory needs to create. In the Factory Method pattern, the structure of the factory object should be in parallel with that of the products. Well, since there are two types of products (i.e. the Square and Circle), there also should be two corresponding concrete factory objects, SquareFactory and CircleFactory. And also, should abstract a related interface IShapeFactory for these two factories. Figure 2 indicates the relationships of these factory related objects.

Figure 2 - The factory class structure introduced by the Factory Method pattern

Below is the related code implementations.

Listing 2

public interface IShapeFactory
{
    IShape CreateShape();
}
public class SquareFactory : IShapeFactory
{
    public IShape CreateShape()
    {
        return new Square();
    }
}
public class SquareFactory : IShapeFactory
{
    public IShape CreateShape()
    {
        return new Square();
    }
}

As is indicated above, with the help of the Factory Method pattern, we have achieved the aim of encapsulating the creation of the objects, which shifts all the code creating concrete products to the respective factory objects, which is finally performed inside method CreateShape(). All these structures can be described using the diagram in Figure 3.

Figure 3 - The whole structure of the Factory Method pattern

Herein, the returned type of method CreateShape() is the type of interface IShape, which efficiently avoids the dependency between the factory objects and concrete product objects, decoupling the creator and the created object in the end.

Digging Further

Is that the final result? No! In essence, although we have introduced the Factory Method pattern in solving the above puzzles, we have not broken away from the heavy payload resulted from the creation of concrete objects. By digging further, it is not difficult to find out that although by introducing the Factory Method pattern the task of creating the IShape object is transferred to the factory object, the concrete factory object still exists inside the structure of the factory class. That is to say, we have cut off the dependency between the modules and the concrete graphic objects; however, this brings out the new dependency upon the concrete factory objects. What benefits does this bring to us?

Let us continue to do some research from the point of view of the creating frequency of the object. For a graphic tool, there is no doubt that the IShape object is frequently created, one of the possibilities is that the IShape object needs to be created in each module in the project. This, however, is not the case for the factory object; we can initialize the factory object in a central module and directly invoke the CreateShape method of the instance of the factory object when in need of the IShape object.

For example, suppose that in the graphic tool there are three modules, ModuleA, ModuleB, and ModuleC, all of which require creating the Square object. In the light of the original design solution, each module should contain the following:

Listing 3

IShape shape=new Square();

In this case, the above three modules all have dependency of the concrete Square object, as is shown in Figure 4 below. Well, suppose you want to change the shape object into the Circle type, this small alteration will surely influences upon every corner of the project.

Figure 4 - All the three modules rely heavily upon the graphic objects

Of course, we will have to continue to seek better solutions. Now, by introducing the Factory Method pattern, we can add a new module named ModuleFactory, inside which we create a factory object.

Listing 4

IShapeFactory shapeFactory=new SquareFactory();

With this new solution, ModuleA, ModuleB, and ModuleC should also be altered accordingly.

Listing 5

IShape shape=new shapeFactory.CreateShape();

By now, the three original modules have broken away from the dependency of concrete graphic objects; and also, this dependency has now been transferred to the ModuleFactory module. Figure 5 shows the new relationships after introducing the Factory Method pattern.

Figure 5

Well, when we are again in the face of the similar alteration requirement (requiring modifying the creation of the shape object), it becomes more feasible because the three modules (ModuleA, ModuleB, and ModuleC) are no longer dependent of the concrete graphic objects. What we need to modify is the parts (in this case the ModuleFactory module) that bear dependency of concrete graphic objects. Please check out the following:

Listing 6

IShapeFactory sf=new CircleFactory();

By distinguishing Figure 4 from Figure 5, you can easily find out that with the introduction of the Factory Method pattern the whole design has been drastically improved. Despite that we have introduced three new factory objects and the new ModuleFactory module; they together have decoupled the three modules with concrete graphic objects, so that this dependency is shifted into only one module -- ModuleFactory.

Altogether, introducing the factory object does not only mean to build up the corresponding factory for each product, but to care more about the compartmentalization of the responsibilities of different modules so as to put the creation of the factory at the most proper site. Numerous design facts prove that the best solution is to centralize the responsibility of creating the factory object in a module, but not to create the factory objects just when in need of create concrete products.

Exploring the Design Pattern of class WebRequest inside the .NET Framework

The Factory Method pattern is widely used in the design of .NET framework. As one of the most important classes in processing web requests, WebRequest plays the key role. It is able to create the corresponding web requests according to the passed URI objects. For example, when the prefix of the URI is "https://" or "http://," it can create and return a HttpWebRequest object; in the case that the prefix is "file://," however, it can create and return a FileWebRequest object. Both HttpWebRequest and FileWebRequest are derived classes of class WebRequest. Figure 6 illustrates their relationships.

Figure 6 - The WebRequest class and its two derivatives

There are many means for you to create an instance of class WebRequest. For example, you can directly leverage the static method Create of this class.

Listing 7

WebRequest wr= WebRequest.Create(http://www.aspalliance.com);

After that, you can get the WebResponse object according to the newly-created WebRequest object.

Listing 8

WebResponse myresponse=wr.GetResponse();
//…
myresponse.Close();

It seems that the static Create() method is one of the implementations of the simple Factory pattern, which can judge the type of class WebRequest according to the arguments passed to the method, and then create and return the concrete WebRequest object. If so, the simplest solution is to judge the value of the argument to decide the type of the object to create using a conditional sentence. Obviously, this is not a good means, which directly results in the concrete subclasses of class WebRequest dependent of the static method Create(). In this way, once it requires increasing the subclasses of class WebRequest, we have to modify the Create method everywhere.

As you may have imaged, Microsoft architects of .NET Framework have already grasped the idea of the design pattern. Thus, they introduce the Factory Method pattern to overcome the above deficiency. They built up a special factory interface named IWebRequestCreate responsible to create the WebRequest object, which merely declares one method named Create.

Listing 9

public interface IWebRequestCreate
{
  WebRequest Create(Uri uri);
}

Corresponding to different kinds of web requests, the Factory Method pattern can provide different related factory classes which all implement interface IWebRequestCreate, such as HttpRequestCreator below.

Listing 10

internal class HttpRequestCreator : IWebRequestCreate
{
    public WebRequest Create(Uri Uri)
    {
        return new HttpWebRequest(Uri, null);
    }
}

Another example relates to class FileWebRequestCreator:

internal class FileWebRequestCreator : IWebRequestCreate
{
    internal FileWebRequestCreator()
    { }
    public WebRequest Create(Uri uri)
    {
        return new FileWebRequest(uri);
    }
}

So, as you have seen, .NET Framework has created an excellent factory class architecture that parallels to each product class. Figure 7 indicates the diagram introduced by the Factory Method pattern.

Figure 7 - The class diagram related to class WebRequest

Now, you see, whether for the factory classes or the product classes, there only exist weak dependencies between interface IWebRequestCreate and the abstract class WebRequest. This appropriately reflects the essence of abstract or interface oriented programming in the idea of OOP.

Digging Further

For now, everything seems better. However, we still worry about the creation of the concrete factory objects. For example, when the WebRequest object is to be created, the related factory class object should be created beforehand in the system.

Listing 11

IWebRequestCreate webRequestCreate = new 
 HttpRequestCreator();

Different from common objects, the types of WebRequest might change at any moment, which correspondingly results in the related factory types changing accordingly. In this case, even if we put the code of creating the factory in a special module as described above, it still lacks flexibility. After all, as a summit framework, the design tenet of .NET framework is to facilitate the use of the class libraries for developers as far as possible, as well as to deal with various extensibilities. So, we can not settle for the present design. Well, any other better ideas?

In fact, it is only through digging further into the implementation of all WebRequest related objects that we find out how the Microsoft architects have racked their brains in scheming the design of the WebRequest class. So, have you caught on to the reason that the abstract WebRequest class introduces a static method Create? What on earth hides behind the scene? For this, we have to dig further into the inner implementation of this method.

Listing 12

public static WebRequest Create(Uri requestUri)
 {
   if (requestUri == null) 
  {
     throw new ArgumentNullException(”requestUri”);
   }
    return Create(requestUri, false);
 }

Now, as you have seen, another private static method named Create is called inside this method. OK, let us continue to follow up the scene:

Listing 13

private static WebRequest Create(Uri requestUri, bool useUriBase)
 {
  string LookupUri;
  WebRequestPrefixElement Current = null;
  bool Found = false;
 if (!useUriBase) {
       LookupUri = requestUri.AbsoluteUri;
  }
  else {
      LookupUri = requestUri.Scheme + ‘:’;
  }
 int LookupLength = LookupUri.Length;
  ArrayList prefixList = PrefixList;
 for (int i = 0; i < prefixList.Count; i++)
  {
        Current = (WebRequestPrefixElement)prefixList[i];
       // See if this prefix is short enough.
        if (LookupLength >= Current.Prefix.Length)
   {
            // It is. See if these match.
            if (String.Compare(Current.Prefix,0,LookupUri,0,Current.Prefix.Length,true,
  CultureInfo.InvariantCulture) == 0)
    {
                   Found = true;
                   break;
            }
         }
  }
     if (Found)
  {
         return Current.Creator.Create(requestUri);
    }
   throw new NotSupportedException(SR.GetString(SR.net_unknown_prefix));
 }

In a word, the above method retrieves the WebRequestPrefixElement object meeting the specified condition in an ArrayList structure according to the value of the passed parameter of Uri. If found, then invoke the method Create of property Creator of object WebRequestPrefixElement, and then create and return the proper WebRequest object; or else, throw a related exception.

Now, we have to make clear two questions:

1. What is the definition of class WebRequestPrefixElement? And what is the type of property Creator of class WebRequestPrefixElement?

2. What on earth does the PrefixList object hold?

Well, let us first look at the definition of class WebRequestPrefixElement.

Listing 14

internal class WebRequestPrefixElement
{
  public string Prefix;
  public IWebRequestCreate Creator;
public WebRequestPrefixElement(string P, IWebRequestCreate C)
{
  Prefix = P;
  Creator = C;
}
}

Now, we have known that class WebRequestPrefixElement is responsible for establishing a one-to-one mapping between the prefix Prefix of Uri and the IWebRequestCreate typed object Creator, which is performed through the constructor of class WebRequestPrefixElement.

For now, we have also made clear the function of the sentence "Current.Creator.Create(requestUri)" inside the private static method Create of class WebRequest. In detail, it bears the responsibility of finding the proper IWebRequestCreate typed object in the specified Uri, then invokes its factory method to create the final object-- WebRequest. Well, which factory method has been invoked? (What is the IWebRequestCreate object that property Current represents?)

In fact, as is hinted in the above code, the value of Current is just the IWebRequestCreate object obtained from the structure prefixList, while the value of this prefixList inside method Create is just the PrefixList property defined in class WebRequest.

Next, let us continue to examine the definition of property PrefixList.

Listing 15

private static ArrayList PrefixList
{
  get
  {
    if (s_PrefixList == null)
    {
      lock (typeof(WebRequest))
      {
        if (s_PrefixList == null)
        {
          GlobalLog.Print(
            ”WebRequest::Initialize(): calling ConfigurationSettings.GetConfig()”);
          ArrayList prefixList =
      (ArrayList)ConfigurationSettings.GetConfig(”system.net/webRequestModules”);
 
          if (prefixList == null)
          {
            GlobalLog.Print(”WebRequest::Initialize(): creating default settings”);
            HttpRequestCreator Creator = new HttpRequestCreator();
 
            // longest prefixes must be the first
            prefixList = new ArrayList();                            
            prefixList.Add(new WebRequestPrefixElement(”https”, Creator));
            prefixList.Add(new WebRequestPrefixElement(”http”, Creator));
            prefixList.Add(new WebRequestPrefixElement(”file”, 
              new FileWebRequestCreator())); //
          }
          s_PrefixList = prefixList;
        }
      }
    }
    return s_PrefixList;
  }
  set
  {
    s_PrefixList = value;
  }
}

As you have seen, inside the Get accessor of property PrefixList, a series of judgments and initializations have been performed. The most important work here is adding three elements which are all of type of the WebRequestPrefixElement object, through which a one-to-one mapping is established between Uri and IWebRequestCreate in the prefixList property.

Listing 16

prefixList.Add(new WebRequestPrefixElement(”https”, Creator));
prefixList.Add(new WebRequestPrefixElement(”http”, Creator));
prefixList.Add(new WebRequestPrefixElement(”file”, new FileWebRequestCreator()));

Inside property prefixList, the first two elements related factory types are both of type of HttpWebRequestCreator, while the third element related factory type is FileWebRequestCreator. The two are just the two concrete factory classes that implement interface IWebRequestCreator.

Now, we have further realized that during the course of invoking WebRequest’s static method Create(), the system will, according to the passed Uri object, retrieve from inside prefixList the WebRequestPrefixElement typed object whose prefix matches the uri inside property PrefixList( through the String.Compare() method). If found, then invoke the corresponding factory class to create related WebRequest instance according to the one-to-one mapping.

Now, let us look back to see the related code to create the WebRequest object.

Listing 17

WebRequest myRequest = 
 WebRequest.Create("http://www.aspalliance.com");

According to the analysis above, the interior of the single line of code has implemented the following steps:

1. Pass the string "http://www.aspalliance.com" to the private static method Create() of class WebRequest.

2. Assign the value of the private property PrefixList of class WebRequest to the local variable, i.e. the prefixList object. In this case, the Get accessor of property PrefixList is called which can initialize the PrefixList object, and adds the default Uri and the value of the IWebRequestCreate type into the PrefixList.

3. Resolve the passed Uri, and get the value "http," where the related IWebRequestCreate object is the HttpWebRequestCreator object.

4. Invoke the Create() method of the HttpWebRequestCreator object, creating and returning a HttpWebRequest object.

Next, let us look at the timing diagram of the static method Create of class WebRequest, as shown in Figure 8 below.

Figure 8 - Timing diagram to create object WebRequest

Next, we consider the case of extensibility. If the derived classes of WebRequest are not only limited to the two classes HttpWebRequest and FileWebRequest, there is still a third subclass named FtpWebRequest (with the Uri being "ftp" and the related factory class being "FtpWebRequestCreator"), then how can we create the new subclass?

According to the analyses above, due to the fact that inside the get accessor of property PrefixList no other WebRequestPrefixElement objects are added, method Create cannot find the appropriate IWebRequestCreate factory object if the passed prefix for Uri is "ftp." Do we have to modify the property Prefix related code inside class WebRequest in the case that we need to extend the new subclasses for class WebRequest? If so,you may be astonished, all the above factory classes and related "skills" may seem clumsy and antic!

In fact, it is not the real case. By digging further, you can easily find out some traces which imply some ingenious tips and skills. For example, as you may still remember, during the course of the creation of WebRequest, Microsoft architects vexatiously introduced class WebRequestPrefixElement and an ArrayList typed PrefixList object. Is there some occult hiding behind this?

Well, you know that the ArrayList object permits new elements being added into it. The good thing is that the WebRequest class just contains a public static method named RegisterPrefix which is used to register the WebRequestPrefixElement object.

Listing 18

public static bool RegisterPrefix(string prefix, IWebRequestCreate creator)
{
 bool Error = false;
 int i;
 WebRequestPrefixElement Current;
 
 if (prefix == null)
 {
      throw new ArgumentNullException(”prefix”);
 }
 if (creator == null)
 {
      throw new ArgumentNullException(”creator”);
 }         
 
 lock(typeof(WebRequest))
 {           
      ArrayList prefixList = (ArrayList) PrefixList.Clone();
      i = 0; 
      while (i < prefixList.Count)
  {
           Current = (WebRequestPrefixElement)prefixList[i];
           if (prefix.Length > Current.Prefix.Length)
   {
                 // It is. Break out of the loop here.
                 break;
           }
           if (prefix.Length == Current.Prefix.Length)
   {
        // They’re the same length.
          if (String.Compare(Current.Prefix, prefix, true, 
                CultureInfo.InvariantCulture) == 0)
    {
        // …and the strings are identical. This is an error.
               Error = true;
               break;
                 }
          }
            i++;
      }
      if (!Error)
  {
           prefixList.Insert(i, new WebRequestPrefixElement(prefix, creator));
           PrefixList = prefixList;
      }
 }
 return !Error;
}

Here, if the passed prefix cannot be found in the structure PrefixList, the new prefix and object IWebRequestCreate are inserted into the PrefixList structure. Through this means, new factory classes can be added dynamically. For this, consider the following.

Listing 19

WebRequest.RegisterPrefix(“ftp”,new 
 FtpWebRequestCreator());
WebRequest ftpRequest = 
 WebRequest.Create(“ftp://www.aspalliance.com”);

With this mode, we can finally achieve the target of decoupling the concrete factory class, concrete product class, and the static method Create() of class WebRequest.

In the .NET Framework, it seems rather complex to create a class WebRequest related object, not to mention the concrete implementation of class WebRequest. In essence, however, Microsoft architects utilized the Factory Method pattern to get over the inside knots one after another. Moreover, to make the class library more feasible, universal and extensible, another mapping-like class WebRequestPrefixElement and the ArrayList object are introduced. At the same time, set the concrete factory class as internal, and encapsulate it into the static method of the abstract product base class WebRequest.

Downloads
Conclusion

Design patterns are wonderful tools software masters bring to us, which are based upon the object oriented programming. As one of the mostly used design patterns, the Factory Method pattern is also widely leveraged in designing the numerous .NET Framework classes.

In this article, we first introduced the basic idea of the Factory Method pattern with a simple graphic related example. Then, we started to explore the behind implementation of one of the most important web classes-- WebRequest. By seeking after the detailed code related to class WebRequest we have finally dug out the design routine of class WebRequest and tasted the wonderful utilization of the Factory Method pattern.

One last note: I have omitted all the WebRequest associated code in the source code file, so I highly recommend you to pick up Red Gate's .NET Reflector (originally developed by Lutz Roeder) to find out all the related things.



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-23 10:05:49 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search