- 定义:
1.) 工厂方法模式是用来封装对象的创建,通过让子类来决定创建的对象是什么,来达到将对象创建的过程封装的目的;
2.) 定义了一个创建对象的接口,但由子类决定要实例的泪是哪一个。工厂方法让类把实例化推迟到子类。
- 适用场景:
代码中经常会出现:根据条件创建实现了同一个接口的不用类实例,而这些判定条件可能随时变动,导致我们这个不得不去改动很多代码。
备注:简单工厂在Head First中,被认为不是设计模式的一种,但人们经常使用,大家习惯性的叫,久了也就言传为“工厂方法模式”。
- 简单工厂方法
- 解决了什么问题
例如:
string dbName=string.Empty; dbName="Access"; MemberDaoBase memberDao=null; if(dbName.ToUpper()=="ACCESS"){ memberDao=new Access.MemberDao(); } else if(dbName.ToUpper()=="SQLSERVER") { memberDao=new SqlServer.MemberDao(); } memberDao.Create(new Member()); memberDao.Modify(new Member()); memberDao.Remove(0);
如果代码中不再变动还好,但这种情况很多时候是不存在的,当来了一个新的领导,领导说Sqlite的性能好且免费,那你就不得不去重新去写一个Sqlite.MemberDao,之后再在这里的判断条件中添加上
1 else if(dbName.ToUpper()=="SQLITE") 2 { 3 memberDao=new SqlServer.SqliteDao(); 4 }
当某天另外一个领导说我们不再支持SqlServer了,我们就不得不把else if(dbName.ToUpper()=="SQLSERVER") {...} 这块代码给注释了。我们就痛苦在这种“变动”中。
问题分析:
不稳定部分:
1 string dbName=string.Empty; 2 dbName="Access"; 3 MemberDaoBase memberDao=null; 4 5 if(dbName.ToUpper()=="ACCESS"){ 6 memberDao=new Access.MemberDao(); 7 } 8 else if(dbName.ToUpper()=="SQLSERVER") 9 { 10 memberDao=new SqlServer.MemberDao(); 11 }稳定部分:
1 memberDao.Create(new Member()); 2 3 memberDao.Modify(new Member()); 4 5 memberDao.Remove(0);
如果我们将不稳定的部分给交给两外一个类单独管理,就能把这种耦合变得低一点,当我们需要“变动”时,只用去修改这个管理类;而这管理来是用来new 实例的,我们习惯。
- “new管理类(简单工厂方法核心类)”:
1 /// <summary> 2 /// Description of MemberDaoFactory. 3 /// </summary> 4 public class MemberDaoFactory 5 { 6 public MemberDaoBase Create(string dbName) 7 { 8 if(dbName.ToUpper()=="ACCESS") 9 { 10 Console.WriteLine("new Access.MemberDao()"); 11 return new Access.MemberDao(); 12 } 13 else if(dbName.ToUpper()=="SQLSERVER") 14 { 15 Console.WriteLine("new SqlServer.MemberDao()"); 16 return new SqlServer.MemberDao(); 17 } 18 else 19 { 20 throw new NotSupportedException(string.Format("Not supported {0}",dbName)); 21 } 22 } 23 }
- 按照简单工厂方法的定义调整
代码结构图:
Member.cs
1 /// <summary> 2 /// Description of Member. 3 /// </summary> 4 public class Member 5 { 6 private int id; 7 private string name; 8 9 public Member() 10 { 11 } 12 13 public int Id 14 { 15 get { return id; } 16 set{id=value;} 17 } 18 19 public string Name 20 { 21 get { return name; } 22 set { name = value; } 23 } 24 }