簡單工廠模式雖然實現了使對象的創建與使用進行分離,但一次只能創建一個對象。它不能實現一次創建一系列相互依賴對象的需求,為此我們需要學習抽象工廠模式。
抽象工廠:主要功能是生產抽象產品;如:生產學員、管理員等抽象產品。
抽象產品:主要功能是提供實體產品訪問接口;如:提供學員、管理員等實體產品數據訪問的接口。
實體工廠:主要功能是生產實體產品;如:SQL Server和Access形式的學員、管理員等數據訪問對象。
實體產品:主要功能是實現自己的功能;如:分別實現不同的數據庫訪問。
對 MySchoolPro(項目)的數據訪問層用抽象工廠設計模式進行改造,如下圖所示:
抽象工廠(Abstract Factory)設計模式的使用思路概括如下:
提供一系列相互依賴對象的創建;
封裝對象的常規創建方法(new);
提供統一調用數據訪問方法的方式;
避免調用數據訪問方法和具體對象創建工作的緊偶合。
抽象工廠(Abstract Factory)設計模式的概念:
提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
抽象工廠(Abstract Factory)設計模式的使用場合:
一個系統要獨立於它產品的創建、組合和表示時。
一個系統要由多個產品系列中的一個來配置時。
MySchoolPro(項目)應用示例
用抽象工廠設計模式實現的數據訪問層
抽象工廠設計模式與項目中使用的類、接口的對應關系
項目間的依賴關系
項目MySchoolIDAL:提供信息數據訪問接口
IStudentService
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using MySchoolModels; //引用實體類
/**//* ******************************
* 接口名:IStudentService
* 功能描敘:提供學員信息數據訪問接口
* *****************************/
namespace MySchoolIDAL
{
public interface IStudentService
{
Student GetStudentByLoginID(string loginId);
}
}
IAdminService
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using MySchoolModels; //引用實體類
/**//* ******************************
* 接口名:IAdminService
* 功能描敘:提供管理員信息數據訪問接口
* *****************************/
namespace MySchoolIDAL
{
public interface IAdminService
{
Admin GetAdminByLoginID(string loginId);
}
}
項目MySchoolDAL:提供信息數據訪問
StudentService
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using MySchoolModels; //引用實體類
using MySchoolIDAL; //引用抽象訪問接口
/**//* ******************************
* 接口名:StudentService
* 功能描敘:提供學員信息數據訪問
* *****************************/
namespace MySchoolDAL.SqlServer
{
public class StudentService: IStudentService
{
Private Members#region Private Members
// 從配置文件中讀取數據庫連接字符串
private readonly string connString =
ConfigurationSettings.AppSettings["MySchoolConnectionString"].ToString();
private readonly string dboOwner =
ConfigurationSettings.AppSettings["DataBaseOwner"].ToString();
#endregion
Public Methods#region Public Methods
/**//// <summary>
/// 根據登錄ID 得到學員實體
/// </summary>
/// <param name="loginID">登錄ID</param>
/// <returns>學員信息實體</returns>
public Student GetStudentByLoginID(string loginID)
{
Student student = new Student();
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand objCommand = new SqlCommand(dboOwner + ".usp_SelectStudentInfoByLoginID",conn);
objCommand.Parameters.Add("@LoginID", SqlDbType.NVarChar, 50).Value = loginID;
conn.Open();
using (SqlDataReader objReader = objCommand.ExecuteReader(CommandBehavior.CloseConnection))
{
if (objReader.Read())
{
student.LoginId = Convert.ToString(objReader["LoginId"]);
student.StudentNO = Convert.ToString(objReader["StudentNO"]);
student.StudentName = Convert.ToString(objReader["StudentName"]);
student.Phone = Convert.ToString(objReader["Phone"]);
}
}
conn.Close();
conn.Dispose();
}
return student;
}
#endregion
}
}
StudentService
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.OleDb;
using MySchoolModels; //引用實體類
using MySchoolIDAL; //引用抽象訪問接口
/**//* ******************************
* 接口名:StudentService
* 功能描敘:提供學員信息數據訪問
* *****************************/
namespace MySchoolDAL.Access
{
public class StudentService : IStudentService
{
Private Members#region Private Members
// 從配置文件中讀取數據庫連接字符串
string sql = string.Empty;
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=MySchool.mdb";
#endregion
Public Methods#region Public Methods
/**//// <summary>
/// 根據登錄ID 得到學員實體
/// </summary>
/// <param name="loginID">登錄ID</param>
/// <returns>學員信息實體</returns>
public Student GetStudentByLoginID(string loginID)
{
Student student = new Student();
sql = "select * from Student where LoginId='" + loginID + "'";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
OleDbCommand objCommand = new OleDbCommand(sql,conn);
objCommand.CommandType = CommandType.Text;
conn.Open();
using (OleDbDataReader objReader = objCommand.ExecuteReader(CommandBehavior.CloseConnection))
{
if (objReader.Read())
{
student.LoginId = Convert.ToString(objReader["LoginId"]);
student.StudentNO = Convert.ToString(objReader["StudentNO"]);
student.StudentName = Convert.ToString(objReader["StudentName"]);
student.Phone = Convert.ToString(objReader["Phone"]);
}
}
conn.Close();
conn.Dispose();
}
return student;
}
#endregion
}
}
實現數據訪問對象創建功能
在抽象工廠(MySchoolDALFactory)項目中的3個類:
1> 抽象工廠類 AbstractDALFactory:用於提供數據訪問
對象創建功能;
AbstractDALFactory
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using MySchoolIDAL; //引用數據訪問接口
/**//* ******************************
* 接口名:AbstractDALFactory
* 功能描敘:提供數據抽象工廠
* *****************************/
namespace MySchoolDALFactory
{
public abstract class AbstractDALFactory
{
// 創建工廠的選擇應該用反射實現
// 這裡為了方便理解,使用開關語句實現
public static AbstractDALFactory ChooseFactory()
{
string dbType = ConfigurationSettings.AppSettings["DBType"].ToString();
AbstractDALFactory factory = null;
switch(dbType)
{
case "Sql":
factory = new SqlDAlFactory();
break;
case "Access":
factory = new AccessDALFactory();
break;
}
return factory;
}
// 提供數據訪問對象創建功能(抽象工廠提供抽象產品)
public abstract IStudentService CreateStudentService();
public abstract IAdminService CreateAdminService();
}
}
2> SQL Server 實體工廠類 SqlDAlFactory:用於封裝SQL Server數據庫訪問對象的創建;
SqlDAlFactory
using System;
using System.Collections.Generic;
using System.Text;
using MySchoolIDAL; //引用數據訪問接口
using MySchoolDAL.SqlServer; //引用數據訪問 SqlServer
/**//* ******************************
* 接口名:MySchoolDALFactory
* 功能描敘:提供 Sql Server 工廠對象
* *****************************/
namespace MySchoolDALFactory
{
public class SqlDAlFactory: AbstractDALFactory
{
Public Methods#region Public Methods
public override IStudentService CreateStudentService()
{
return new StudentService();
}
public override IAdminService CreateAdminService()
{
return new AdminService();
}
#endregion
}
}
3> Access實體工廠類 AccessDALFactory:用於封裝Access數據庫訪問對象的創建;
AccessDALFactory
using System;
using System.Collections.Generic;
using System.Text;
using MySchoolIDAL; //引用數據訪問接口
using MySchoolDAL.Access; //引用數據訪問 Access
/**//* ******************************
* 接口名:AccessDALFactory
* 功能描敘:提供 Access 工廠對象
* *****************************/
namespace MySchoolDALFactory
{
public class AccessDALFactory : AbstractDALFactory
{
Public Methods#region Public Methods
public override IStudentService CreateStudentService()
{
return new StudentService();
}
public override IAdminService CreateAdminService()
{
return new AdminService();
}
#endregion
}
}
業務邏輯層調用數據訪問層方法
這裡用靜態類實現業務邏輯層,當業務邏輯層使用靜態類實現後,
表示層可以直接調用業務邏輯層的方法,無需實例化對象。
示例用戶登錄業務邏輯代碼
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using MySchoolModels;
using MySchoolIDAL;
using MySchoolDALFactory;
/**//******************************************
* 功能:LoginManager
* 功能描述:提供用戶登錄
******************************************/
namespace MySchoolBLL
{
public static class LoginManager
{
private Members#region private Members
//調用數據訪問層統一數據訪問方式
private static AbstractDALFactory factory =
AbstractDALFactory.ChooseFactory();
private static IStudentService studentService =
factory.CreateStudentService();
private static IAdminService adminService =
factory.CreateAdminService();
#endregion
public Methods#region public Methods
/**//// <summary>
/// 登錄
/// <summary>
/// <param name="loginID">登錄 ID</param>
/// <param name="password">密碼</param>
/// <param name="type">用戶類型</param>
/// <returns></returns>
public static bool Login(string loginID,string password,string type)
{
bool condition = false;
switch(type)
{
case "管理員":
condition = AdminLogin(loginID, password);
break;
case "學員":
condition = StudentLogin(loginID, password);
break;
}
return condition;
}
#endregion
private Methods#region private Methods
/**//// <summary>
/// 管理員登錄
/// <summary>
/// <param name="loginID">登錄 ID</param>
/// <param name="password">密碼</param>
/// <returns></returns>
private static bool AdminLogin(string loginID, string password)
{
bool condition = false;
string pwd = adminService.GetAdminByLoginID(loginID).LoginPwd.ToString();
if(pwd == password)
condition = true;
return condition;
}
/**//// <summary>
/// 學員登錄
/// <summary>
/// <param name="loginID">登錄 ID</param>
/// <param name="password">密碼</param>
/// <returns></returns>
private static bool StudentLogin(string loginID, string password)
{
bool condition = false;
Student student = new Student();
student = studentService.GetStudentByLoginID(loginID);
if(student.UserStateId != 0)
{
if(student.LoginPwd == password)
condition = true;
}
return condition;
}
#endregion
}
}
實現數據訪問接口
操作步驟:
1.搭建數據訪問層基本架構:
新增抽象工廠項目(MySchoolDALFactory);
新增抽象產品項目(MySchoolIDAL);
實現項目之間的依賴;
2.實現數據訪問接口。
3.實現數據訪問對象創建功能。
4.業務邏輯層調用數據訪問層方法。