创建型模式之间的比较
在GOF的设计模式中没有简单工厂,而是将其作为工厂方法的一个特例加以解释的。可以这样理解,简单工厂是参数化的工厂方法。简单工厂的作用是实例化对象,而不需要客户了解这个对象属于那个具体子类。优点:可以使用户根据参数获得对应的类的实例,避免了用户直接实例化类,降低了耦合性。缺点:可实例化的类型在编译期间已绑定,如果增加新类型,则需要修改工厂。简单工厂需要知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用。
当一个类不知道他所必需创建对象的类或一个类希望有子类指定他所创建的类型时(也就是说一个类中的某个对象需要由子类来创建时),可以使用工厂方法模式。优点:工厂方法使类中的代码不依赖于它必须创建的类,代码只知道要创建类的接口。缺点:新增加一个需要创建的类就需要增加一个相应的子类。工厂方法与工厂对象不同,工厂对象的作用是专门负责其他类的实例化,如抽象工厂的对象或者简单工厂的对象,即实例化对象是工厂对象的唯一职责,而工厂方法所存在的类则不同,只有工厂方法负责实例化相关类型的实例。除此之外,这个类的对象还具有其他职责,也就是说除了工厂方法外,还有其他方法。
工厂方法针对的仅仅是一种“产品”,或者称为“类”,而抽象工厂实际上针对很多平行的产品,因此层次不同。抽象工厂才是名副其实的“工厂”,即不仅仅只生产一种产品,抽象工厂是层次较高的模式,针对应用中需要使用的一系列相关的类给出一个创建接口。抽象工厂分离了具体的类:(1)是产品系列容易交换,只要更换相应的具体工厂即可(经常用工厂方法来实现);(2)有利于产品的一致性,由抽象工厂创建的产品必须符合相同的接口,任何在子类中的特殊功能都不能体现在统一的接口中;(3)难以支持新产品的类型,如果抽象工厂的基类要发生变化,那么针对每个产品系列的具体工厂也都要发生变化,显然这是很麻烦的。
反射工厂方法:如果工厂方法仅仅是为了获得某个产品的实例,那么完全可以使用反射技术来实现工厂方法,这样解决了工厂方法潜在的问题,即当增加产品类时,必须增加相应的子类,然而当工厂方法所在的类不仅是实例化产品时,采用反射技术不一定是好办法,因此可能是问题变得复杂。反射工厂的优点:极大地减少了工厂类的数量,降低了代码的冗余,并且系统更容易扩展,在增加新类型后,不需要修改工厂类。使用反射工厂的代价是工厂与产品之间的依赖关系不明显,由于是动态绑定,因此理论上可以用一个工厂完成很多类型的实例化,从而使得代码不容易理解。
生成器模式(Builder Pattern)把构造对象实例的逻辑移到了类的外部,在这个类的外部定义了这个类的构造逻辑。他把一个复杂对象的构造过程从对象的表示中分离出来。其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。他强调的是产品的构造过程。生成器产生的不一定是一个产品系列的对象,只要对象的创建过程一致即可,而抽象工厂所创建的对象一定是一个产品的系列。
原型模式(Prototype)和简单工厂等一样,同样对客户隐藏了对象创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。
以下是利用抽象工厂模式对数据库访问类的优化:
当一个类不知道他所必需创建对象的类或一个类希望有子类指定他所创建的类型时(也就是说一个类中的某个对象需要由子类来创建时),可以使用工厂方法模式。优点:工厂方法使类中的代码不依赖于它必须创建的类,代码只知道要创建类的接口。缺点:新增加一个需要创建的类就需要增加一个相应的子类。工厂方法与工厂对象不同,工厂对象的作用是专门负责其他类的实例化,如抽象工厂的对象或者简单工厂的对象,即实例化对象是工厂对象的唯一职责,而工厂方法所存在的类则不同,只有工厂方法负责实例化相关类型的实例。除此之外,这个类的对象还具有其他职责,也就是说除了工厂方法外,还有其他方法。
工厂方法针对的仅仅是一种“产品”,或者称为“类”,而抽象工厂实际上针对很多平行的产品,因此层次不同。抽象工厂才是名副其实的“工厂”,即不仅仅只生产一种产品,抽象工厂是层次较高的模式,针对应用中需要使用的一系列相关的类给出一个创建接口。抽象工厂分离了具体的类:(1)是产品系列容易交换,只要更换相应的具体工厂即可(经常用工厂方法来实现);(2)有利于产品的一致性,由抽象工厂创建的产品必须符合相同的接口,任何在子类中的特殊功能都不能体现在统一的接口中;(3)难以支持新产品的类型,如果抽象工厂的基类要发生变化,那么针对每个产品系列的具体工厂也都要发生变化,显然这是很麻烦的。
反射工厂方法:如果工厂方法仅仅是为了获得某个产品的实例,那么完全可以使用反射技术来实现工厂方法,这样解决了工厂方法潜在的问题,即当增加产品类时,必须增加相应的子类,然而当工厂方法所在的类不仅是实例化产品时,采用反射技术不一定是好办法,因此可能是问题变得复杂。反射工厂的优点:极大地减少了工厂类的数量,降低了代码的冗余,并且系统更容易扩展,在增加新类型后,不需要修改工厂类。使用反射工厂的代价是工厂与产品之间的依赖关系不明显,由于是动态绑定,因此理论上可以用一个工厂完成很多类型的实例化,从而使得代码不容易理解。
生成器模式(Builder Pattern)把构造对象实例的逻辑移到了类的外部,在这个类的外部定义了这个类的构造逻辑。他把一个复杂对象的构造过程从对象的表示中分离出来。其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。他强调的是产品的构造过程。生成器产生的不一定是一个产品系列的对象,只要对象的创建过程一致即可,而抽象工厂所创建的对象一定是一个产品的系列。
原型模式(Prototype)和简单工厂等一样,同样对客户隐藏了对象创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。
以下是利用抽象工厂模式对数据库访问类的优化:
1public class DBUse
2{
3 DBFactory dbf = null;
4 public DBUse(string dbType)
5 {
6 switch (dbType.ToLower())
7 {
8 case "sql":
9 dbf = new SQLDBFactory();
10 break;
11 case "oracle":
12 dbf = new OracleDBFactory();
13 break;
14 default:
15 dbf = new OleDBFactory();
16 break;
17 }
18 }
19
20 public DataSet GetDataSet(string sql)
21 {
22 DBOperator dbop = new DBOperator(dbf);
23 dbop.Open("connctionstring");
24 return dbop.ExecSQL(sql);
25 }
26}
2{
3 DBFactory dbf = null;
4 public DBUse(string dbType)
5 {
6 switch (dbType.ToLower())
7 {
8 case "sql":
9 dbf = new SQLDBFactory();
10 break;
11 case "oracle":
12 dbf = new OracleDBFactory();
13 break;
14 default:
15 dbf = new OleDBFactory();
16 break;
17 }
18 }
19
20 public DataSet GetDataSet(string sql)
21 {
22 DBOperator dbop = new DBOperator(dbf);
23 dbop.Open("connctionstring");
24 return dbop.ExecSQL(sql);
25 }
26}
public class DBOperator
{
private DBFactory dbf;
private IDbConnection dbconn;
public DBOperator(DBFactory dbf)
{
this.dbf = dbf;
}
public void Open(string connstring)
{
dbconn = dbf.GetDBConnection();
dbconn.ConnectionString = connstring;
dbconn.Open();
}
public DataSet ExecSQL(string sql)
{
IDbCommand dbc = dbf.GetDBCommand();
dbc.CommandText = sql;
dbc.CommandType = CommandType.Text;
dbc.Connection = dbconn;
IDataAdapter ida = dbf.GetDBDataAdapter(dbc);
DataSet ds = null;
ida.Fill(ds);
return ds;
}
}
{
private DBFactory dbf;
private IDbConnection dbconn;
public DBOperator(DBFactory dbf)
{
this.dbf = dbf;
}
public void Open(string connstring)
{
dbconn = dbf.GetDBConnection();
dbconn.ConnectionString = connstring;
dbconn.Open();
}
public DataSet ExecSQL(string sql)
{
IDbCommand dbc = dbf.GetDBCommand();
dbc.CommandText = sql;
dbc.CommandType = CommandType.Text;
dbc.Connection = dbconn;
IDataAdapter ida = dbf.GetDBDataAdapter(dbc);
DataSet ds = null;
ida.Fill(ds);
return ds;
}
}
public abstract class DBFactory
{
public abstract IDbCommand GetDBCommand();
public abstract IDbConnection GetDBConnection();
public abstract IDataAdapter GetDBDataAdapter(IDbCommand idc);
}
{
public abstract IDbCommand GetDBCommand();
public abstract IDbConnection GetDBConnection();
public abstract IDataAdapter GetDBDataAdapter(IDbCommand idc);
}
public class SQLDBFactory : DBFactory
{
public SQLDBFactory()
{}
public override IDbCommand GetDBCommand()
{
return new SqlCommand();
}
public override IDbConnection GetDBConnection()
{
return new SqlConnection();
}
public override IDataAdapter GetDBDataAdapter(IDbCommand idc)
{
return new SqlDataAdapter((SqlCommand)idc);
}
}
{
public SQLDBFactory()
{}
public override IDbCommand GetDBCommand()
{
return new SqlCommand();
}
public override IDbConnection GetDBConnection()
{
return new SqlConnection();
}
public override IDataAdapter GetDBDataAdapter(IDbCommand idc)
{
return new SqlDataAdapter((SqlCommand)idc);
}
}