4.1. Object Creation

 < Day Day Up > 

The subject of creating objects typically receives less attention than that of designing classes; but it is important enough that a formal body of techniques known as creational patterns has been developed to provide object creation models. A popular approach used throughout the Framework Class Library (FCL) is to implement the factory creational pattern. As the name implies, the factory is an object whose sole purpose is to create other objects much like a real-world factory. Its advantage is that it handles all the details of object creation; a client instructs the factory which object to create and is generally unaffected by any implementation changes that may occur.

There are a number of ways to implement the factory pattern. This section presents two logical approaches illustrated in Figures 4-1 and 4-2.

Figure 4-1. Factory with one factory class

Figure 4-2. Factory with multiple factory classes

Figure 4-1 represents the case where one factory is used to produce all of the related products (objects). In Figure 4-2, each product has its own factory, and the client sends the request to the factory that produces the desired object. We'll look at examples of both, beginning with code for the single factory implementation (see Listing 4-1).

Listing 4-1. Using a Class Factory to Create Objects Single Factory
 public interface IApparel    // Interface representing product {    string ShowMe();    bool Knit        // Property to indicate if Knit    { get; } } public class SportsShirt : IApparel {    public string ShowMe()    {       return("Sports Shirt");    }    public bool Knit    { get {return true;} } } public class DressShirt : IApparel {    public string ShowMe()    {       return("Dress Shirt");    }    public bool Knit    { get {return false;} } } // Factory to return instances of apparel classes public class ApparelFactory {    public IApparel CreateApparel( string apptype)    {       switch (apptype)       {          case "MDRSHIRT":             return new DressShirt();          case "MSPSHIRT":             return new SportsShirt();       }       return null;    } } 

In this example, the class factory implements a method named CreateApparel that returns objects. The most important thing to note is that this method is declared with IApparel as its return type, which enables it to return an instance of any class that implements that interface.

 public IApparel CreateApparel( string apptype) 

The same effect could be achieved by replacing the interface with an abstract class. This could yield better code reuse in situations where objects share common behavior, but should be weighed against other factors that were discussed in Chapter 3, "Class Design in C#."

With the factory and product classes defined, all the hard work has been done. It's a simple matter for clients to create objects:

 ApparelFactory factory= new ApparelFactory(); IApparel ob1 = factory.CreateApparel("MDRSHIRT"); IApparel ob2 = factory.CreateApparel("MSPSHIRT"); string shirtType = ob1.ShowMe(); // Returns "Dress Shirt" 

If the application needs to add any more products, the factory is supplied with the new code, but no changes are required on the client side. It only needs to be aware of how to request all available products.

Example: Creating Objects with Multiple Factories

This solution adds an abstract class (we could use an interface) for the factory and two concrete subclasses that implement it to produce specific apparel objects:

 // abstract public abstract class AppFactory {    public  abstract IApparel CreateApparel(); } // Concrete factory classes public class DressShirtFactory:AppFactory {    public override IApparel CreateApparel( )    { return new DressShirt(); } } public class SportShirtFactory : AppFactory {    public override IApparel CreateApparel( )    { return new SportsShirt(); } } 

We have created the abstract class so that its subclasses can be passed to a new ApparelCollector class that serves as an intermediary between the clients and the factories. Specifically, the client passes the factory to this class, and it is responsible for calling the appropriate factory.

 public class ApparelCollector {    public void CollectApparel(AppFactory factory)    {       IApparel apparel = factory.CreateApparel();    } } 

The code to use the new class is analogous to that in the first example:

 AppFactory factory = new DressShirtFactory(); IApparel obj2 = new ApparelCollector().CollectApparel(factory); 

For a simple example like this, the first approach using one factory is easier to implement. However, there are cases where it's preferable to have multiple factories. The objects may be grouped into families of products (a shirt factory and a dress factory, for example), or you may have a distributed application where it makes sense for different developers to provide their own factory classes.

     < Day Day Up > 

    Core C# and  .NET
    Core C# and .NET
    ISBN: 131472275
    EAN: N/A
    Year: 2005
    Pages: 219

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net