工厂模式(Factory Pattern)
简介
1、工厂模式主要是为对象的创建提供一个统一的方法,工厂模式主要分为三类
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
2、工厂模式的主要应用场景:
- 在编码是不能预见需要创建那种类的实例
- 系统不应依赖于产品类实例如何被创建、组合和表达的细节
简单工厂模式
简单工厂模式又叫静态工厂,简单工厂模式:工厂是根据调用者传入的参数决定创建哪一种产品类的
简单工厂模式的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 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 }
抽象工厂模式
给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件
- 系统中有多个产品族,而系统一次只可能消费其中一族产品
- 同属于同一个产品族的产品一起使用时
产品族:位于不同产品等级结构中,功能相关联的产品组成的家族, 如下示例中:SqlConnection,SqlCommand,SqlParameter 就属于同一个产品族
抽象工厂模式的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 }
简单工厂模式:
只有一个工厂类,工厂类可以创建一个抽象产品类的所以具体产品实例
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建同一个抽象产品类的具体产品实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个抽象产品类的具体产品类实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。