Difference between Factory Method and Abstract Factory design patterns using C#.Net
I have moved this blog to http://pragmaticdevs.wordpress.com/
First of all I'll just put both these patterns in context and describe their intent as in the GOF book:
Factory Method:
Define an interface for creating an object, but let subclasses decide which class
to instantiate. Factory Method lets a class defer instantiation to subclasses.
Abstract Factory:
Provide an interface for creating families of related or dependent objects without
specifying their concrete classes.
Points to note:
- Abstract factory pattern adds a layer of abstraction to the factory method pattern. The type of factory is not known to the client at compile time, this information is passed to the client at runtime (How it is passed is again dependent on the system, you may store this information in configuration files and the client can read it on execution).
- While implementing Abstract factory pattern, the factory classes can have multiple factory methods.
- In Abstract factory, a factory is capable of creating more than one type of product (Similar products are grouped together in a factory)
Sample implementation of factory method pattern
Let's see the class diagram first:
ProductFactory.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="ProductFactory.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public abstract class ProductFactory
18 {
19 /// <summary>
20 /// </summary>
21 /// <returns>
22 /// </returns>
23 public abstract Product CreateProductInstance();
24 }
25 }
26
ProductAFactory.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="ProductAFactory.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public class ProductAFactory:ProductFactory
18 {
19 public override Product CreateProductInstance()
20 {
21 return new ProductA();
22 }
23 }
24 }
25
ProductBFactory.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="ProductBFactory.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public class ProductBFactory:ProductFactory
18 {
19 public override Product CreateProductInstance()
20 {
21 return new ProductB();
22
23 }
24 }
25 }
26
Product.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="Product.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public abstract class Product
18 {
19 public abstract string Name { get; set; }
20 }
21 }
22
ProductB.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="ProductB.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public class ProductB:Product
18 {
19 public ProductB()
20 {
21
22 Name = "ProductB";
23 }
24 public override string Name { get; set; }
25 }
26 }
27
ProductA.cs
1 // -----------------------------------------------------------------------
2 // <copyright file="ProductA.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public class ProductA:Product
18 {
19 public ProductA()
20 {
21
22 Name = "ProductA";
23 }
24
25 public override string Name { get; set; }
26 }
27 }
28
Sample implementation of Abstract Factory pattern
Here's the class diagram:
As said earlier, the Abstract factory pattern adds another layer of abstraction to the factory method pattern so the Product/ProductFactory classes that we used earlier in Factory Method pattern implementation would be reused here.
1 // -----------------------------------------------------------------------
2 // <copyright file="ApplicationCaller.cs" company="">
3 // TODO: Update copyright text.
4 // </copyright>
5 // -----------------------------------------------------------------------
6
7 namespace FactoryMethod
8 {
9 using System;
10 using System.Collections.Generic;
11 using System.Linq;
12 using System.Text;
13
14 /// <summary>
15 /// TODO: Update summary.
16 /// </summary>
17 public class ApplicationCaller
18 {
19 public Product PassFactory(ProductFactory pf)
20 {
21
22 Product product = pf.CreateProductInstance();
23 return product;
24 }
25 }
26 }
27
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace FactoryMethod
7 {
8 using System.Configuration;
9 using System.Net.Mime;
10
11 class Program
12 {
13 static ProductFactory CreateSpecificFactory()
14 {
15
16 string facType = System.Configuration.ConfigurationSettings.AppSettings["FactoryName"];
17 if (facType == "ProductAFactory")
18 {
19 return new ProductAFactory();
20 }
21 else
22 {
23 return new ProductBFactory();
24 }
25 }
26
27 static void Main(string[] args)
28 {
29 Console.WriteLine(new ApplicationCaller().PassFactory(CreateSpecificFactory()).Name);
30
31 }
32 }
33 }
34
Add finally the type of factory to be used would be decided at runtime, in this sample we are reading this information from a config file and passing it to the application.
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <appSettings>
4 <add key="FactoryName" value="ProductBFactory"/>
5 </appSettings>
6 </configuration>