工厂模式(Factory Pattern)


简介

1、工厂模式主要是为对象的创建提供一个统一的方法,工厂模式主要分为三类

  1. 简单工厂模式(Simple Factory) 
  2. 工厂方法模式(Factory Method) 
  3. 抽象工厂模式(Abstract Factory)

2、工厂模式的主要应用场景:

  1. 在编码是不能预见需要创建那种类的实例
  2. 系统不应依赖于产品类实例如何被创建、组合和表达的细节

简单工厂模式

  简单工厂模式又叫静态工厂,简单工厂模式:工厂是根据调用者传入的参数决定创建哪一种产品类的

简单工厂模式的4个角色

  1. 抽象产品:所有的产品必须实现这个共同的接口,这样一来,使用这些产品的类即可以引用这个抽象产品。而不是具体类(可以使用接口/和抽象类)
  2. 具体产品:基础或实现了抽象产品的类(调用者实际需要的对象)
  3. 工厂:负责生产具体产品,并以其父类的方式返回
  4. 调用者

 简单工厂模式实例:

 1   /// 
 2     /// 简单工厂
 3     /// 
 4     class SimpleFactory
 5     {
 6         /// 
 7         /// 通过参数获取 IProduct 接口 的实例
 8         /// 
 9         /// 类型参数
10         /// 
11         public static IProduct GetProductInstance(string paramType)
12         {
13             IProduct instance;
14             switch (paramType)
15             {
16                 case "a": instance = new ProductA();
17                     break;
18                 case "b": instance = new ProductB();
19                     break;
20                 default: throw new ArgumentOutOfRangeException("paramType", "ProductFactory中未定义" + paramType);
21             }
22             return instance;
23         }
24     }
25 
26     /// 
27     /// 抽象产品基类
28     /// 
29     interface IProduct
30     {
31         string Name { get; }
32         void ShowName();
33     }
34 
35     /// 
36     /// 产品类A
37     /// 
38     class ProductA : IProduct
39     {
40         public string Name
41         {
42             get
43             {
44                 return "a";
45             }
46         }
47 
48         public void ShowName()
49         {
50             {
51                 Console.Write("My name is " + Name);
52             }
53         }
54     }
55 
56     /// 
57     /// 产品类B
58     /// 
59     class ProductB : IProduct
60     {
61         public string Name
62         {
63             get
64             {
65                 return "b";
66             }
67         }
68 
69         public void ShowName()
70         {
71             {
72                 Console.Write("My name is " + Name);
73             }
74         }
75     }

 工厂方法模式

  工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式让实例化推迟到子类。

工厂方法模式有5个角色

  1. 抽象产品:所有的产品必须实现这个共同的接口,这样一来,使用这些产品的类即可以引用这个抽象产品。而不是具体类(可以使用接口/和抽象类)
  2. 具体产品:基础或实现了抽象产品的类(调用者实际需要的对象)
  3. 抽象工厂:制造产品的实际工厂。它负责创建一个或者多个具体产品,只有具体工厂知道如何创建这些具体产品。
  4. 具体工厂:负责生产具体产品,并以其父类的方式返回
  5. 调用者

工厂方法模式实例

  1     /// 
  2     /// 抽象工厂类
  3     /// 
  4     interface IFactory
  5     {
  6         /// 
  7         /// 通过参数获取 IProduct 接口 的实例
  8         /// 
  9         /// 类型参数
 10         /// 
 11         IProduct GetProductInstance(string paramType);
 12     }
 13 
 14     /// 
 15     /// 具体工厂A
 16     /// 
 17     class FactoryA : IFactory
 18     {
 19         public IProduct GetProductInstance(string paramType)
 20         {
 21             IProduct instance;
 22             switch (paramType)
 23             {
 24                 case "a1": instance = new ProductA1();
 25                     break;
 26                 case "a2": instance = new ProductA2();
 27                     break;
 28                 default: throw new ArgumentOutOfRangeException("paramType", "FactoryB中未定义" + paramType);
 29             }
 30             return instance;
 31         }
 32     }
 33 
 34     /// 
 35     /// 具体工厂B
 36     /// 
 37     class FactoryB : IFactory
 38     {
 39         public IProduct GetProductInstance(string paramType)
 40         {
 41             IProduct instance;
 42             switch (paramType)
 43             {
 44                 case "b1": instance = new ProductB1();
 45                     break;
 46                 case "b2": instance = new ProductB2();
 47                     break;
 48                 default: throw new ArgumentOutOfRangeException("paramType", "FactoryB中未定义" + paramType);
 49             }
 50             return instance;
 51         }
 52     }
 53 
 54 
 55 
 56     /// 
 57     /// 抽象产品基类
 58     /// 
 59     interface IProduct
 60     {
 61         string Name { get; }
 62         void ShowName();
 63     }
 64 
 65     /// 
 66     /// 产品类A1
 67     /// 
 68     class ProductA1 : IProduct
 69     {
 70         public string Name
 71         {
 72             get
 73             {
 74                 return "a1";
 75             }
 76         }
 77 
 78         public void ShowName()
 79         {
 80             {
 81                 Console.Write("My name is " + Name);
 82             }
 83         }
 84     }
 85     /// 
 86     /// 产品类A2
 87     /// 
 88     class ProductA2 : IProduct
 89     {
 90         public string Name
 91         {
 92             get
 93             {
 94                 return "a2";
 95             }
 96         }
 97 
 98         public void ShowName()
 99         {
100             {
101                 Console.Write("My name is " + Name);
102             }
103         }
104     }
105 
106     /// 
107     /// 产品类B1
108     /// 
109     class ProductB1 : IProduct
110     {
111         public string Name
112         {
113             get
114             {
115                 return "b1";
116             }
117         }
118 
119         public void ShowName()
120         {
121             {
122                 Console.Write("My name is " + Name);
123             }
124         }
125     }
126 
127     /// 
128     /// 产品类B2
129     /// 
130     class ProductB2 : IProduct
131     {
132         public string Name
133         {
134             get
135             {
136                 return "b2";
137             }
138         }
139 
140         public void ShowName()
141         {
142             {
143                 Console.Write("My name is " + Name);
144             }
145         }
146     }

抽象工厂模式

给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件

  1. 系统中有多个产品族,而系统一次只可能消费其中一族产品
  2. 同属于同一个产品族的产品一起使用时

产品族:位于不同产品等级结构中,功能相关联的产品组成的家族, 如下示例中:SqlConnection,SqlCommand,SqlParameter 就属于同一个产品族

抽象工厂模式的5角色(与工厂方法的角色差不多):

  1. 抽象产品:所有的产品必须实现这个共同的接口,这样一来,使用这些产品的类即可以引用这个抽象产品。而不是具体类(可以使用接口/和抽象类)
  2. 具体产品:基础或实现了抽象产品的类(调用者实际需要的对象)
  3. 抽象工厂:制造产品的实际工厂。它负责创建一个或者多个具体产品,只有具体工厂知道如何创建这些具体产品。
  4. 具体工厂:负责生产产品族中成员的具体产品,并以其父类的方式返回
  5. 调用者

抽象工厂模式实例:使用的是System.Data.Common.DbProviderFactory 微软提供的跨数据库查询抽象工厂

  1 //抽象工厂, 这个是ado.net 的源码
  2 namespace System.Data.Common
  3 {
  4     public abstract class DbProviderFactory
  5     {
  6         public virtual bool CanCreateDataSourceEnumerator
  7         {
  8             get
  9             {
 10             }
 11         }
 12 
 13         public virtual DbCommand CreateCommand()
 14         {
 15         }
 16 
 17         public virtual DbCommandBuilder CreateCommandBuilder()
 18         {
 19         }
 20 
 21         public virtual DbConnection CreateConnection()
 22         {
 23         }
 24 
 25         public virtual DbConnectionStringBuilder CreateConnectionStringBuilder()
 26         {
 27         }
 28 
 29         public virtual DbDataAdapter CreateDataAdapter()
 30         {
 31         }
 32 
 33         public virtual DbParameter CreateParameter()
 34         {
 35         }
 36 
 37         public virtual CodeAccessPermission CreatePermission(PermissionState state)
 38         {
 39         }
 40 
 41         public virtual DbDataSourceEnumerator CreateDataSourceEnumerator()
 42         {
 43         }
 44     }
 45 }
 46 
 47  
 48 /// 
 49     /// MSSQL 的 具体工厂
 50     /// 
 51     public class MSSQLDbProviderFactory : System.Data.Common.DbProviderFactory
 52     {
 53         static readonly string sqlConn = "数据库连接字符串";
 54 
 55         public override DbConnection CreateConnection()
 56         {
 57             return new SqlConnection(sqlConn);
 58         }
 59 
 60         public override DbCommand CreateCommand()
 61         {
 62             return new SqlCommand();
 63         }
 64 
 65         public override DbParameter CreateParameter()
 66         {
 67             return new SqlParameter();
 68         }
 69     }
 70 
 71 //Globol 中 初始化
 72     public class MvcApplication : System.Web.HttpApplication
 73     {
 74         public static System.Data.Common.DbProviderFactory ProviderFactory;
 75         protected void Application_Start()
 76         {
 77             // 实例化 ProviderFactory 为MSSQL 数据库的
 78             // 如果未来我们是用MYSQL数据库 那么就可以只要修改一下 这个变量的初始化为MYSQLDbProviderFactory 那么这个系统就切换到了MYSQL了(不考虑SQL兼用性的情况下--)
 79             ProviderFactory = new Models.MSSQLDbProviderFactory();
 80 
 81             AreaRegistration.RegisterAllAreas();
 82             RouteConfig.RegisterRoutes(RouteTable.Routes);
 83         }
 84     }
 85 
 86 // 使用
 87 
 88             // 传统方式访问数据库
 89             using (var conn = new SqlConnection(""))
 90             {
 91                 var cmd = new SqlCommand();
 92                 cmd.CommandText = "SELETE * FROM Table";
 93                 cmd.Connection = conn;
 94                 var read = cmd.ExecuteReader();
 95                 while (read.Read())
 96                 {
 97                     Console.Write(read.GetString(1));
 98                 }
 99             }
100 
101             // 在查询中使用到的SQL对象全部依赖抽象工厂来创建
102             using (var conn = MvcApplication.ProviderFactory.CreateConnection())
103             {
104                 var cmd =  MvcApplication.ProviderFactory.CreateCommand();
105                 cmd.CommandText = "SELETE * FROM Table";
106                 cmd.Connection = conn;
107                 var read = cmd.ExecuteReader();
108                 while (read.Read())
109                 {
110                     Console.Write(read.GetString(1));
111                 }
112             }

简单工厂模式:

只有一个工厂类,工厂类可以创建一个抽象产品类的所以具体产品实例

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建同一个抽象产品类的具体产品实例。

抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个抽象产品类的具体产品类实例。

区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。