这也是一种抽象工厂
抽象工厂模式
The abstract factory is a GOF (Gang of Four) creational pattern where the intent is to "...provide an interface for creating families of related or dependent objects without specifying their concrete classes". ("Design Patterns" -- Gamma, Help, Johnson, Vlissides)
抽象工厂模式是一种创建型模式,意图是“提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类”。(《Design Patterns》GOF)
There are four main parts to any abstract factory:
Abstract Factory: defines generic interface for creation of objects.
Concrete Factory: implementation of the abstract factory.
Abstract Product: the generic interface that defines the object to be created.
Concrete Product: the implementation of the abstract product. In other words, the actual objects.
任何抽象工厂都包含以下四大部分:
抽象工厂:为创建对象提供一般接口。
具体工厂:抽象工厂的实现。
抽象产品:定义了被创建对象的一般接口。
具体产品:抽象产品的实现,即实际对象。
抽象工厂模式在Pet Shop中的应用
可能有多处应用,我们先从DataAccess这一处最明显的地方讲起。对于Pet Shop中那么多DLL的关系以及讲解可以查阅微软相关资料,我不做过多讲解。
这里首先要明白Pet Shop可以连接多个数据库,这就符合GOF的抽象工厂模式的意图:提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。
在PetShop.BLL命名空间中类说起。
至于那些类中的代理模式之类以后再进行说明。现在引用一些代码如下:
在这里我们主要要看的是PetShop.DALFactory.DataAccess.CreateProduct();
查看定义DataAccess.cs
这里的代码起到框架做用,通过配置文件来自动生成找到工厂类。
开始以为是抽象工厂方法,但是查看了一下,不是,是通过反射直接创建类。也可以理解为一种更简单的抽象工厂。
IDAL 中定义接口,如
IOrder.cs
其中不同的数据库有不同的实现类,在SQLServerDAL中的实现:
Order.cs
在Orcle中的实现:OracleDAL
Order.cs
总结:
虽然没有完全按照GOF的抽象工厂模式去定义,但是其实现思想是一样的。
算是一种变种。
DataAcess代码可以进行变种,如将这些方法都抽象出来
public PetShop.IDAL.ICategory CreateCategory()
IDataAccess接口,然后,实现DataAccessSql,DataAccessOracle,再过去配置文件创建出来。如果这样,那就过于为了模式而模式。比较僵。
2011-6-23 15:50 danny
抽象工厂模式
The abstract factory is a GOF (Gang of Four) creational pattern where the intent is to "...provide an interface for creating families of related or dependent objects without specifying their concrete classes". ("Design Patterns" -- Gamma, Help, Johnson, Vlissides)
抽象工厂模式是一种创建型模式,意图是“提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类”。(《Design Patterns》GOF)
There are four main parts to any abstract factory:
Abstract Factory: defines generic interface for creation of objects.
Concrete Factory: implementation of the abstract factory.
Abstract Product: the generic interface that defines the object to be created.
Concrete Product: the implementation of the abstract product. In other words, the actual objects.
任何抽象工厂都包含以下四大部分:
抽象工厂:为创建对象提供一般接口。
具体工厂:抽象工厂的实现。
抽象产品:定义了被创建对象的一般接口。
具体产品:抽象产品的实现,即实际对象。
抽象工厂模式在Pet Shop中的应用
可能有多处应用,我们先从DataAccess这一处最明显的地方讲起。对于Pet Shop中那么多DLL的关系以及讲解可以查阅微软相关资料,我不做过多讲解。
这里首先要明白Pet Shop可以连接多个数据库,这就符合GOF的抽象工厂模式的意图:提供一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。
在PetShop.BLL命名空间中类说起。
至于那些类中的代理模式之类以后再进行说明。现在引用一些代码如下:
public class Product { private static readonly IProduct dal = PetShop.DALFactory.DataAccess.CreateProduct();
在这里我们主要要看的是PetShop.DALFactory.DataAccess.CreateProduct();
查看定义DataAccess.cs
using System.Reflection; using System.Configuration; namespace PetShop.DALFactory { /// <summary> /// This class is implemented following the Abstract Factory pattern to create the DAL implementation /// specified from the configuration file /// </summary> public sealed class DataAccess { // Look up the DAL implementation we should be using private static readonly string path = ConfigurationManager.AppSettings["WebDAL"]; private static readonly string orderPath = ConfigurationManager.AppSettings["OrdersDAL"]; private DataAccess() { } public static PetShop.IDAL.ICategory CreateCategory() { string className = path + ".Category"; return (PetShop.IDAL.ICategory)Assembly.Load(path).CreateInstance(className); } public static PetShop.IDAL.IInventory CreateInventory() { string className = path + ".Inventory"; return (PetShop.IDAL.IInventory)Assembly.Load(path).CreateInstance(className); } public static PetShop.IDAL.IItem CreateItem() { string className = path + ".Item"; return (PetShop.IDAL.IItem)Assembly.Load(path).CreateInstance(className); } public static PetShop.IDAL.IOrder CreateOrder() { string className = orderPath + ".Order"; return (PetShop.IDAL.IOrder)Assembly.Load(orderPath).CreateInstance(className); } public static PetShop.IDAL.IProduct CreateProduct() { string className = path + ".Product"; return (PetShop.IDAL.IProduct)Assembly.Load(path).CreateInstance(className); } } }
这里的代码起到框架做用,通过配置文件来自动生成找到工厂类。
开始以为是抽象工厂方法,但是查看了一下,不是,是通过反射直接创建类。也可以理解为一种更简单的抽象工厂。
IDAL 中定义接口,如
IOrder.cs
using System; //References to PetShop specific libraries //PetShop busines entity library using PetShop.Model; namespace PetShop.IDAL{ /// <summary> /// Interface for the Order DAL /// </summary> public interface IOrder { /// <summary> /// Method to insert an order header /// </summary> /// <param name="order">Business entity representing the order</param> /// <returns>OrderId</returns> void Insert(OrderInfo order); /// <summary> /// Reads the order information for a given orderId /// </summary> /// <param name="orderId">Unique identifier for an order</param> /// <returns>Business entity representing the order</returns> OrderInfo GetOrder(int orderId); } }
其中不同的数据库有不同的实现类,在SQLServerDAL中的实现:
Order.cs
using System; using System.Data.SqlClient; using System.Data; using System.Collections.Generic; using System.Text; using PetShop.Model; using PetShop.IDAL; using PetShop.DBUtility; namespace PetShop.SQLServerDAL { public class Order : IOrder { //Static constants private const string SQL_INSERT_ORDER = "Declare @ID int; Declare @ERR int; INSERT INTO Orders VALUES(@UserId, @Date, @ShipAddress1, @ShipAddress2, @ShipCity, @ShipState, @ShipZip, @ShipCountry, @BillAddress1, @BillAddress2, @BillCity, @BillState, @BillZip, @BillCountry, 'UPS', @Total, @BillFirstName, @BillLastName, @ShipFirstName, @ShipLastName, @AuthorizationNumber, 'US_en'); SELECT @ID=@@IDENTITY; INSERT INTO OrderStatus VALUES(@ID, @ID, GetDate(), 'P'); SELECT @ERR=@@ERROR;"; private const string SQL_INSERT_ITEM = "INSERT INTO LineItem VALUES( "; private const string SQL_SELECT_ORDER = "SELECT o.OrderDate, o.UserId, o.CardType, o.CreditCard, o.ExprDate, o.BillToFirstName, o.BillToLastName, o.BillAddr1, o.BillAddr2, o.BillCity, o.BillState, BillZip, o.BillCountry, o.ShipToFirstName, o.ShipToLastName, o.ShipAddr1, o.ShipAddr2, o.ShipCity, o.ShipState, o.ShipZip, o.ShipCountry, o.TotalPrice, l.ItemId, l.LineNum, l.Quantity, l.UnitPrice FROM Orders as o, lineitem as l WHERE o.OrderId = @OrderId AND o.orderid = l.orderid"; private const string PARM_USER_ID = "@UserId"; private const string PARM_DATE = "@Date"; private const string PARM_SHIP_ADDRESS1 = "@ShipAddress1"; private const string PARM_SHIP_ADDRESS2 = "@ShipAddress2"; private const string PARM_SHIP_CITY = "@ShipCity"; private const string PARM_SHIP_STATE = "@ShipState"; private const string PARM_SHIP_ZIP = "@ShipZip"; private const string PARM_SHIP_COUNTRY = "@ShipCountry"; private const string PARM_BILL_ADDRESS1 = "@BillAddress1"; private const string PARM_BILL_ADDRESS2 = "@BillAddress2"; private const string PARM_BILL_CITY = "@BillCity"; private const string PARM_BILL_STATE = "@BillState"; private const string PARM_BILL_ZIP = "@BillZip"; private const string PARM_BILL_COUNTRY = "@BillCountry"; private const string PARM_TOTAL = "@Total"; private const string PARM_BILL_FIRST_NAME = "@BillFirstName"; private const string PARM_BILL_LAST_NAME = "@BillLastName"; private const string PARM_SHIP_FIRST_NAME = "@ShipFirstName"; private const string PARM_SHIP_LAST_NAME = "@ShipLastName"; private const string PARM_AUTHORIZATION_NUMBER = "@AuthorizationNumber"; private const string PARM_ORDER_ID = "@OrderId"; private const string PARM_LINE_NUMBER = "@LineNumber"; private const string PARM_ITEM_ID = "@ItemId"; private const string PARM_QUANTITY = "@Quantity"; private const string PARM_PRICE = "@Price"; public void Insert(OrderInfo order) { StringBuilder strSQL = new StringBuilder(); // Get each commands parameter arrays SqlParameter[] orderParms = GetOrderParameters(); SqlCommand cmd = new SqlCommand(); // Set up the parameters orderParms[0].Value = order.UserId; orderParms[1].Value = order.Date; orderParms[2].Value = order.ShippingAddress.Address1; orderParms[3].Value = order.ShippingAddress.Address2; orderParms[4].Value = order.ShippingAddress.City; orderParms[5].Value = order.ShippingAddress.State; orderParms[6].Value = order.ShippingAddress.Zip; orderParms[7].Value = order.ShippingAddress.Country; orderParms[8].Value = order.BillingAddress.Address1; orderParms[9].Value = order.BillingAddress.Address2; orderParms[10].Value = order.BillingAddress.City; orderParms[11].Value = order.BillingAddress.State; orderParms[12].Value = order.BillingAddress.Zip; orderParms[13].Value = order.BillingAddress.Country; orderParms[14].Value = order.OrderTotal; orderParms[15].Value = order.BillingAddress.FirstName; orderParms[16].Value = order.BillingAddress.LastName; orderParms[17].Value = order.ShippingAddress.FirstName; orderParms[18].Value = order.ShippingAddress.LastName; orderParms[19].Value = order.AuthorizationNumber.Value; foreach (SqlParameter parm in orderParms) cmd.Parameters.Add(parm); // Create the connection to the database using (SqlConnection conn = new SqlConnection(SqlHelper.ConnectionStringOrderDistributedTransaction)) { // Insert the order status strSQL.Append(SQL_INSERT_ORDER); SqlParameter[] itemParms; // For each line item, insert an orderline record int i = 0; foreach (LineItemInfo item in order.LineItems) { strSQL.Append(SQL_INSERT_ITEM).Append(" @ID").Append(", @LineNumber").Append(i).Append(", @ItemId").Append(i).Append(", @Quantity").Append(i).Append(", @Price").Append(i).Append("); SELECT @ERR=@ERR+@@ERROR;"); //Get the cached parameters itemParms = GetItemParameters(i); itemParms[0].Value = item.Line; itemParms[1].Value = item.ItemId; itemParms[2].Value = item.Quantity; itemParms[3].Value = item.Price; //Bind each parameter foreach (SqlParameter parm in itemParms) cmd.Parameters.Add(parm); i++; } conn.Open(); cmd.Connection = conn; cmd.CommandType = CommandType.Text; cmd.CommandText = strSQL.Append("SELECT @ID, @ERR").ToString(); // Read the output of the query, should return error count using (SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { // Read the returned @ERR rdr.Read(); // If the error count is not zero throw an exception if (rdr.GetInt32(1) != 0) throw new ApplicationException("DATA INTEGRITY ERROR ON ORDER INSERT - ROLLBACK ISSUED"); } //Clear the parameters cmd.Parameters.Clear(); } } /// <summary> /// Read an order from the database /// </summary> /// <param name="orderId">Order Id</param> /// <returns>All information about the order</returns> public OrderInfo GetOrder(int orderId) { OrderInfo order = new OrderInfo(); //Create a parameter SqlParameter parm = new SqlParameter(PARM_ORDER_ID, SqlDbType.Int); parm.Value = orderId; //Execute a query to read the order using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringOrderDistributedTransaction, CommandType.Text, SQL_SELECT_ORDER, parm)) { if (rdr.Read()) { //Generate an order header from the first row AddressInfo billingAddress = new AddressInfo(rdr.GetString(5), rdr.GetString(6), rdr.GetString(7), rdr.GetString(8), rdr.GetString(9), rdr.GetString(10), rdr.GetString(11), rdr.GetString(12), null, "email"); AddressInfo shippingAddress = new AddressInfo(rdr.GetString(13), rdr.GetString(14), rdr.GetString(15), rdr.GetString(16), rdr.GetString(17), rdr.GetString(18), rdr.GetString(19), rdr.GetString(20), null, "email"); order = new OrderInfo(orderId, rdr.GetDateTime(0), rdr.GetString(1), null, billingAddress, shippingAddress, rdr.GetDecimal(21), null, null); IList<LineItemInfo> lineItems = new List<LineItemInfo>(); LineItemInfo item = null; //Create the lineitems from the first row and subsequent rows do { item = new LineItemInfo(rdr.GetString(22), string.Empty, rdr.GetInt32(23), rdr.GetInt32(24), rdr.GetDecimal(25)); lineItems.Add(item); } while (rdr.Read()); order.LineItems = new LineItemInfo[lineItems.Count]; lineItems.CopyTo(order.LineItems, 0); } } return order; } /// <summary> /// Internal function to get cached parameters /// </summary> /// <returns></returns> private static SqlParameter[] GetOrderParameters() { SqlParameter[] parms = SqlHelper.GetCachedParameters(SQL_INSERT_ORDER); if (parms == null) { parms = new SqlParameter[] { new SqlParameter(PARM_USER_ID, SqlDbType.VarChar, 80), new SqlParameter(PARM_DATE, SqlDbType.DateTime, 12), new SqlParameter(PARM_SHIP_ADDRESS1, SqlDbType.VarChar, 80), new SqlParameter(PARM_SHIP_ADDRESS2, SqlDbType.VarChar, 80), new SqlParameter(PARM_SHIP_CITY, SqlDbType.VarChar, 80), new SqlParameter(PARM_SHIP_STATE, SqlDbType.VarChar, 80), new SqlParameter(PARM_SHIP_ZIP, SqlDbType.VarChar, 50), new SqlParameter(PARM_SHIP_COUNTRY, SqlDbType.VarChar, 50), new SqlParameter(PARM_BILL_ADDRESS1, SqlDbType.VarChar, 80), new SqlParameter(PARM_BILL_ADDRESS2, SqlDbType.VarChar, 80), new SqlParameter(PARM_BILL_CITY, SqlDbType.VarChar, 80), new SqlParameter(PARM_BILL_STATE, SqlDbType.VarChar, 80), new SqlParameter(PARM_BILL_ZIP, SqlDbType.VarChar, 50), new SqlParameter(PARM_BILL_COUNTRY, SqlDbType.VarChar, 50), new SqlParameter(PARM_TOTAL, SqlDbType.Decimal, 8), new SqlParameter(PARM_BILL_FIRST_NAME, SqlDbType.VarChar, 80), new SqlParameter(PARM_BILL_LAST_NAME, SqlDbType.VarChar, 80), new SqlParameter(PARM_SHIP_FIRST_NAME, SqlDbType.VarChar, 80), new SqlParameter(PARM_SHIP_LAST_NAME, SqlDbType.VarChar, 80), new SqlParameter(PARM_AUTHORIZATION_NUMBER, SqlDbType.Int)}; SqlHelper.CacheParameters(SQL_INSERT_ORDER, parms); } return parms; } private static SqlParameter[] GetItemParameters(int i) { SqlParameter[] parms = SqlHelper.GetCachedParameters(SQL_INSERT_ITEM + i); if (parms == null) { parms = new SqlParameter[] { new SqlParameter(PARM_LINE_NUMBER + i, SqlDbType.Int, 4), new SqlParameter(PARM_ITEM_ID+i, SqlDbType.VarChar, 10), new SqlParameter(PARM_QUANTITY+i, SqlDbType.Int, 4), new SqlParameter(PARM_PRICE+i, SqlDbType.Decimal, 8)}; SqlHelper.CacheParameters(SQL_INSERT_ITEM + i, parms); } return parms; } } }
在Orcle中的实现:OracleDAL
Order.cs
using System; using System.Collections.Generic; using System.Data; using System.Data.OracleClient; using System.Text; using PetShop.Model; using PetShop.IDAL; using PetShop.DBUtility; namespace PetShop.OracleDAL { public class Order : IOrder { // Static strings private const string SQL_GET_ORDERNUM = "SELECT ORDERNUM.NEXTVAL FROM DUAL"; private const string SQL_INSERT_ORDER = "INSERT INTO Orders VALUES(:OrderId, :UserId, :OrderDate, :ShipAddress1, :ShipAddress2, :ShipCity, :ShipState, :ShipZip, :ShipCountry, :BillAddress1, :BillAddress2, :BillCity, :BillState, :BillZip, :BillCountry, 'UPS', :Total, :BillFirstName, :BillLastName, :ShipFirstName, :ShipLastName, :AuthorizationNumber, 'US_en')"; private const string SQL_INSERT_STATUS = "INSERT INTO OrderStatus VALUES(:OrderId, 0, sysdate, 'P')"; private const string SQL_INSERT_ITEM = "INSERT INTO LineItem VALUES(:OrderId{0}, :LineNumber{0}, :ItemId{0}, :Quantity{0}, :Price{0})"; private const string SQL_SELECT_ORDER = "SELECT o.OrderDate, o.UserId, o.CardType, o.CreditCard, o.ExprDate, o.BillToFirstName, o.BillToLastName, o.BillAddr1, o.BillAddr2, o.BillCity, o.BillState, o.BillZip, o.BillCountry, o.ShipToFirstName, o.ShipToLastName, o.ShipAddr1, o.ShipAddr2, o.ShipCity, o.ShipState, o.ShipZip, o.ShipCountry, o.TotalPrice, l.ItemId, l.LineNum, l.Quantity, l.UnitPrice FROM Orders o, lineitem l WHERE o.OrderId = :OrderId AND o.orderid = l.orderid"; private const string PARM_USER_ID = ":UserId"; private const string PARM_DATE = ":OrderDate"; private const string PARM_SHIP_ADDRESS1 = ":ShipAddress1"; private const string PARM_SHIP_ADDRESS2 = ":ShipAddress2"; private const string PARM_SHIP_CITY = ":ShipCity"; private const string PARM_SHIP_STATE = ":ShipState"; private const string PARM_SHIP_ZIP = ":ShipZip"; private const string PARM_SHIP_COUNTRY = ":ShipCountry"; private const string PARM_BILL_ADDRESS1 = ":BillAddress1"; private const string PARM_BILL_ADDRESS2 = ":BillAddress2"; private const string PARM_BILL_CITY = ":BillCity"; private const string PARM_BILL_STATE = ":BillState"; private const string PARM_BILL_ZIP = ":BillZip"; private const string PARM_BILL_COUNTRY = ":BillCountry"; private const string PARM_TOTAL = ":Total"; private const string PARM_BILL_FIRST_NAME = ":BillFirstName"; private const string PARM_BILL_LAST_NAME = ":BillLastName"; private const string PARM_SHIP_FIRST_NAME = ":ShipFirstName"; private const string PARM_SHIP_LAST_NAME = ":ShipLastName"; private const string PARM_AUTHORIZATION_NUMBER = ":AuthorizationNumber"; private const string PARM_ORDER_ID = ":OrderId"; private const string PARM_LINE_NUMBER = ":LineNumber"; private const string PARM_ITEM_ID = ":ItemId"; private const string PARM_QUANTITY = ":Quantity"; private const string PARM_PRICE = ":Price"; /// <summary> /// With Oracle we can send a PL/SQL block to the database and /// maintain ACID properties for the batch of statements /// The benefits with this is that ou increase performance by /// reducing roundtrips to the database /// gurantee that you only use one database connection and hence same construction costs /// However there are limits to statement size which is based on the /// maximum size of VARCHAR2 parameters (approx 40,000 characters) /// </summary> /// <param name="order">Order details</param> /// <returns>OrderId</returns> public void Insert(OrderInfo order) { int orderId = 0; // Get the parameters OracleParameter[] completeOrderParms = null; OracleParameter[] orderParms = GetOrderParameters(); OracleParameter statusParm = new OracleParameter(PARM_ORDER_ID, OracleType.Number); // Bind the parameters orderParms[1].Value = order.UserId; orderParms[2].Value = order.Date; orderParms[3].Value = order.ShippingAddress.Address1; orderParms[4].Value = order.ShippingAddress.Address2; orderParms[5].Value = order.ShippingAddress.City; orderParms[6].Value = order.ShippingAddress.State; orderParms[7].Value = order.ShippingAddress.Zip; orderParms[8].Value = order.ShippingAddress.Country; orderParms[9].Value = order.BillingAddress.Address1; orderParms[10].Value = order.BillingAddress.Address2; orderParms[11].Value = order.BillingAddress.City; orderParms[12].Value = order.BillingAddress.State; orderParms[13].Value = order.BillingAddress.Zip; orderParms[14].Value = order.BillingAddress.Country; orderParms[15].Value = order.OrderTotal; orderParms[16].Value = order.BillingAddress.FirstName; orderParms[17].Value = order.BillingAddress.LastName; orderParms[18].Value = order.ShippingAddress.FirstName; orderParms[19].Value = order.ShippingAddress.LastName; orderParms[20].Value = order.AuthorizationNumber.Value; // Create the connection to the database using (OracleConnection conn = new OracleConnection(OracleHelper.ConnectionStringOrderDistributedTransaction)) { // Open the database connection conn.Open(); // Get the order id for the order sequence orderId = Convert.ToInt32(OracleHelper.ExecuteScalar(conn, CommandType.Text, SQL_GET_ORDERNUM)); orderParms[0].Value = orderId; statusParm.Value = orderId; // Total number of parameters = order parameters count + 1 + (5 * number of lines) int numberOfParameters = orderParms.Length + 1 + (5 * order.LineItems.Length); //Create a set of parameters completeOrderParms = new OracleParameter[numberOfParameters]; //Copy the parameters to the execution parameters orderParms.CopyTo(completeOrderParms, 0); completeOrderParms[orderParms.Length] = statusParm; //Create a batch statement StringBuilder finalSQLQuery = new StringBuilder("BEGIN "); // Append the order header statements finalSQLQuery.Append(SQL_INSERT_ORDER); finalSQLQuery.Append("; "); finalSQLQuery.Append(SQL_INSERT_STATUS); finalSQLQuery.Append("; "); int index = orderParms.Length + 1; int i = 1; // Append each line item to the batch statement foreach (LineItemInfo item in order.LineItems) { //Add the appropriate parameters completeOrderParms[index] = new OracleParameter(PARM_ORDER_ID + i, OracleType.Number); completeOrderParms[index++].Value = orderId; completeOrderParms[index] = new OracleParameter(PARM_LINE_NUMBER + i, OracleType.Number); completeOrderParms[index++].Value = item.Line; completeOrderParms[index] = new OracleParameter(PARM_ITEM_ID + i, OracleType.Char, 10); completeOrderParms[index++].Value = item.ItemId; completeOrderParms[index] = new OracleParameter(PARM_QUANTITY + i, OracleType.Number); completeOrderParms[index++].Value = item.Quantity; completeOrderParms[index] = new OracleParameter(PARM_PRICE + i, OracleType.Number); completeOrderParms[index++].Value = item.Price; // Append the statement to the batch finalSQLQuery.Append(string.Format(SQL_INSERT_ITEM, i)); finalSQLQuery.Append("; "); i++; } //Close the PL/SQL block finalSQLQuery.Append("END;"); // Finally execute the query OracleHelper.ExecuteNonQuery(conn, CommandType.Text, finalSQLQuery.ToString(), completeOrderParms); } } /// <summary> /// Read an order from the database /// </summary> /// <param name="orderId">Order Id</param> /// <returns>Details of the Order</returns> public OrderInfo GetOrder(int orderId) { //Create a parameter OracleParameter parm = new OracleParameter(PARM_ORDER_ID, OracleType.Number); parm.Value = orderId; //Execute a query to read the order using (OracleDataReader rdr = OracleHelper.ExecuteReader(OracleHelper.ConnectionStringOrderDistributedTransaction, CommandType.Text, SQL_SELECT_ORDER, parm)) { if (rdr.Read()) { //Generate an order header from the first row AddressInfo billingAddress = new AddressInfo(rdr.GetString(5), rdr.GetString(6), rdr.GetString(7), rdr.GetString(8), rdr.GetString(9), rdr.GetString(10), rdr.GetString(11), rdr.GetString(12), null, "email"); AddressInfo shippingAddress = new AddressInfo(rdr.GetString(13), rdr.GetString(14), rdr.GetString(15), rdr.GetString(16), rdr.GetString(17), rdr.GetString(18), rdr.GetString(19), rdr.GetString(20), null, "email"); OrderInfo order = new OrderInfo(orderId, rdr.GetDateTime(0), rdr.GetString(1), null, billingAddress, shippingAddress, rdr.GetDecimal(21), null, null); IList<LineItemInfo> lineItems = new List<LineItemInfo>(); LineItemInfo item = null; //Create the lineitems from the first row and subsequent rows do { item = new LineItemInfo(rdr.GetString(22), string.Empty, rdr.GetInt32(23), rdr.GetInt32(24), rdr.GetDecimal(25)); lineItems.Add(item); } while (rdr.Read()); order.LineItems = new LineItemInfo[lineItems.Count]; lineItems.CopyTo(order.LineItems, 0); return order; } } return null; } /// <summary> /// Internal function to get cached parameters /// </summary> /// <returns></returns> private static OracleParameter[] GetOrderParameters() { OracleParameter[] parms = OracleHelper.GetCachedParameters(SQL_INSERT_ORDER); if (parms == null) { parms = new OracleParameter[] { new OracleParameter(PARM_ORDER_ID, OracleType.Number, 10), new OracleParameter(PARM_USER_ID, OracleType.VarChar, 80), new OracleParameter(PARM_DATE, OracleType.DateTime), new OracleParameter(PARM_SHIP_ADDRESS1, OracleType.VarChar, 80), new OracleParameter(PARM_SHIP_ADDRESS2, OracleType.VarChar, 80), new OracleParameter(PARM_SHIP_CITY, OracleType.VarChar, 80), new OracleParameter(PARM_SHIP_STATE, OracleType.VarChar, 80), new OracleParameter(PARM_SHIP_ZIP, OracleType.VarChar, 50), new OracleParameter(PARM_SHIP_COUNTRY, OracleType.VarChar, 50), new OracleParameter(PARM_BILL_ADDRESS1, OracleType.VarChar, 80), new OracleParameter(PARM_BILL_ADDRESS2, OracleType.VarChar, 80), new OracleParameter(PARM_BILL_CITY, OracleType.VarChar, 80), new OracleParameter(PARM_BILL_STATE, OracleType.VarChar, 80), new OracleParameter(PARM_BILL_ZIP, OracleType.VarChar, 50), new OracleParameter(PARM_BILL_COUNTRY, OracleType.VarChar, 50), new OracleParameter(PARM_TOTAL, OracleType.Number), new OracleParameter(PARM_BILL_FIRST_NAME, OracleType.VarChar, 80), new OracleParameter(PARM_BILL_LAST_NAME, OracleType.VarChar, 80), new OracleParameter(PARM_SHIP_FIRST_NAME, OracleType.VarChar, 80), new OracleParameter(PARM_SHIP_LAST_NAME, OracleType.VarChar, 80), new OracleParameter(PARM_AUTHORIZATION_NUMBER, OracleType.Int32)}; OracleHelper.CacheParameters(SQL_INSERT_ORDER, parms); } return parms; } } }
总结:
虽然没有完全按照GOF的抽象工厂模式去定义,但是其实现思想是一样的。
算是一种变种。
DataAcess代码可以进行变种,如将这些方法都抽象出来
public PetShop.IDAL.ICategory CreateCategory()
IDataAccess接口,然后,实现DataAccessSql,DataAccessOracle,再过去配置文件创建出来。如果这样,那就过于为了模式而模式。比较僵。
2011-6-23 15:50 danny
相关推荐
抽象工厂模式是设计模式中的一种,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。在软件工程中,当系统需要在运行时选择不同的产品族时,或者想要隔离具体产品的实现细节时,抽象工厂...
这个模式的关键在于“族”这个词,也就是说,抽象工厂可以创建一系列相关的产品对象,这些对象通常属于同一类别。抽象工厂模式通过定义多个工厂接口,每个接口对应一类产品,然后由具体的工厂类实现这些接口,以创建...
这是一种创建型设计模式,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。在Winform应用中,可能有多个不同的报表类型,每个报表类型需要不同的UI组件来展示数据。抽象工厂模式允许我们...
抽象工厂模式是设计模式中的一种,尤其适用于创建一组相关或相互依赖的对象。这个实例Demo将向我们展示如何在iOS环境中应用抽象工厂模式。 抽象工厂模式的核心思想是提供一个接口,用于创建一系列相关或相互依赖的...
抽象工厂模式是一种设计模式,属于创建型模式,它提供了一种创建对象集合的接口,而无需指定具体的类。这种模式的主要目的是为了隔离产品对象的创建和使用,使得客户端代码可以独立于具体的产品实现。在软件工程中,...
抽象工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象集合的接口,而无需指定具体的类。这种模式允许系统独立于如何创建、组合和表示产品对象的细节进行设计,为产品族(一组相关或相互依赖的对象)提供...
简单工厂模式是一种静态工厂方法,它提供一个公共的工厂类来创建对象。这个工厂类根据传入的参数或者条件来决定创建哪种类型的实例。在简单工厂模式中,通常有一个中心工厂类,它负责知道如何创建各种产品。这种模式...
抽象工厂模式是设计模式中的一种,属于创建型模式,它提供了一种创建对象族的接口,而无需指定其具体的类。这种模式的关键在于"抽象工厂",它是一个接口或者抽象类,定义了创建一系列相关或相互依赖对象的接口,而...
抽象工厂模式是软件设计模式中的一种,属于创建型模式,它的主要目的是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。在实际应用中,当我们需要创建一组具有共同特性的对象,而这些对象分别...
抽象工厂模式是设计模式中的一种,它属于创建型模式,主要解决的是当系统有多个产品族,而每个产品族又有多个具体产品时,如何组织代码的问题。在Java中,抽象工厂模式提供了一种创建对象组的方式,使得这些对象属于...
抽象工厂模式可以保证在任何环境下都能正确地创建对象,提高了代码的可移植性,但其缺点是增加新平台时,需要增加新的抽象工厂和一系列具体工厂,这可能会导致系统结构变得复杂。 对比这三种工厂模式: 1. **简单...
抽象工厂模式是一种创建型设计模式,它提供了一种方式来创建一组相关或相互依赖的对象,而不需要指定具体的类。该模式允许客户端使用抽象的接口来创建一组相关的产品,而不需要关系实际产出的具体产品是什么。 在...
抽象工厂(Abstract Factory)模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化哪一个类。这种模式是基于对象的抽象,而不是具体的类,因此,它允许创建一系列相关的对象,而无需指定...
抽象工厂模式是设计模式中的一种,属于创建型模式,它提供了一个创建对象的接口,但允许子类决定实例化哪些类。这个模式的关键在于为一组相关或相互依赖的对象提供一个统一的接口,而无需指定他们的具体实现。 抽象...
抽象工厂模式是设计模式中的一种,属于创建型模式,它提供了一种创建对象集合的接口,而无需指定具体的类。这种模式的关键在于“抽象”,它允许我们创建一系列相关的对象,而不必关心它们的具体实现。在Java或其他...
抽象工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象族的接口,而无需指定具体的类。在C#编程中,这种模式经常被用于实现跨平台或跨框架的代码,使得代码与具体实现解耦,提高系统的灵活性和可扩展性。...
抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建相关或依赖对象的家族,而无需明确指定具体类。这种模式允许客户端使用一个通用接口来创建一组相关或相互依赖的对象,而无需知道它们的具体实现。 在...
工厂模式是一种常用的软件设计模式,它是创建型设计模式的一种,主要解决对象的创建问题,将对象的创建过程封装起来,使得创建过程独立于使用过程。这样可以提高代码的可复用性和灵活性,同时降低了系统的耦合度。...
抽象工厂模式是设计模式中的一种创建型模式,它提供了一种创建对象族的接口,而无需指定其具体的类。这种模式的关键在于“族”,即一系列相关的对象。在抽象工厂模式中,我们创建一个抽象工厂接口,然后为每一种具体...
在实际应用中,如果需要创建的对象具有共同的接口或基类,但具体类型是由运行时决定的,工厂方法模式就是一种理想的选择。 例如,假设有一个`ClothesFactory`接口,它有一个方法`createClothing()`,这个方法返回一...