简介
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 IProduct30 {31 string Name { get; }32 void ShowName();33 }34 35 ///36 /// 产品类A37 /// 38 class ProductA : IProduct39 {40 public string Name41 {42 get43 {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 /// 产品类B58 /// 59 class ProductB : IProduct60 {61 public string Name62 {63 get64 {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 /// 产品类B1108 /// 109 class ProductB1 : IProduct110 {111 public string Name112 {113 get114 {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 /// 产品类B2129 /// 130 class ProductB2 : IProduct131 {132 public string Name133 {134 get135 {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 }
简单工厂模式:
只有一个工厂类,工厂类可以创建一个抽象产品类的所以具体产品实例
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建同一个抽象产品类的具体产品实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个抽象产品类的具体产品类实例。 区别:工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。