这也是一种抽象工厂

[b]这也是一种抽象工厂[/b]

抽象工厂模式
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命名空间中类说起。
至于那些类中的代理模式之类以后再进行说明。现在引用一些代码如下:
[code]
public class Product {

private static readonly IProduct dal = PetShop.DALFactory.DataAccess.CreateProduct();

[/code]
在这里我们主要要看的是PetShop.DALFactory.DataAccess.CreateProduct();
查看定义DataAccess.cs
[code]
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);
}

}
}

[/code]
这里的代码起到框架做用,通过配置文件来自动生成找到工厂类。
开始以为是抽象工厂方法,但是查看了一下,不是,是通过反射直接创建类。也可以理解为一种更简单的抽象工厂。
IDAL 中定义接口,如
IOrder.cs
[code]
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);
}
}
[/code]
其中不同的数据库有不同的实现类,在SQLServerDAL中的实现:
Order.cs
[code]
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;
}
}
}
[/code]

在Orcle中的实现:OracleDAL
Order.cs
[code]
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;
}
}
}
[/code]

总结:
虽然没有完全按照GOF的抽象工厂模式去定义,但是其实现思想是一样的。
算是一种变种。
DataAcess代码可以进行变种,如将这些方法都抽象出来
public  PetShop.IDAL.ICategory CreateCategory()
IDataAccess接口,然后,实现DataAccessSql,DataAccessOracle,再过去配置文件创建出来。如果这样,那就过于为了模式而模式。比较僵。


2011-6-23 15:50 danny
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值