工厂模式
记得一个好友面试的时候,面试官问他,你怎么获得一个类的对象的好友说,new一个啊,的确没错,对象不是new难道还是create...
当然在使用new对象的时候,这段代码也就意味着难以以后的维护和扩展了,怎么让灵活起来呢,这里就说到了工厂模式的好处了
工厂模式的好处
系统的灵活性、可扩展性、可维护性
抽象工厂
这里着重讲下之前在项目中使用到的工厂模式
DataAccess:对象工厂->创建对象
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Reflection;
using System.Web;
using Jxmstc.Dal;
using Jxmstc.IDal;
namespace Jxmstc.DalFactory
{
/// <summary>
/// UserManagement抽象工厂
/// 作者:
/// 日期:2009-7-22
/// </summary>
public sealed class DataAccess
{
private static readonly string assemblyPath = ConfigurationManager.AppSettings["DAL"];
//当前架构
private static readonly string architecture = ConfigurationManager.AppSettings["Architecture"];
/// <summary>
/// 构造函数
/// </summary>
public DataAccess()
{ }
#region 缓存处理
/// <summary>
/// 创建对象或从缓存获取
/// </summary>
public static object CreateObject(string assemblyPath, string className)
{
if (architecture.Trim().ToUpper() == "C/S")
{
return Assembly.Load(assemblyPath).CreateInstance(className);
}
object objType = GetCache(className);//从缓存读取
if (objType == null)
{
try
{
objType = Assembly.Load(assemblyPath).CreateInstance(className);//反射创建
SetCache(className, objType);// 写入缓存
}
catch
{
throw;
}
}
return objType;
}
/// <summary>
/// 获取当前应用程序指定CacheKey的Cache值
/// </summary>
///
/// <param name="cacheKey">缓存标记</param>
/// <returns>对象</returns>
public static object GetCache(string cacheKey)
{
System.Web.Caching.Cache objCache = HttpRuntime.Cache;
return objCache[cacheKey];
}
/// <summary>
/// 设置当前应用程序指定CacheKey的Cache值
/// </summary>
/// <param name="cacheKey">缓存标记</param>
/// <param name="obj">对象</param>
public static void SetCache(string cacheKey, object obj)
{
System.Web.Caching.Cache objCache = HttpRuntime.Cache;
objCache.Insert(cacheKey, obj);
}
#endregion
#region 生产对象
/// <summary>
/// 创建User数据层接口
/// </summary>
/// <returns></returns>
public static IDal.IUser CreateUser()
{
string className = assemblyPath + ".User";
object objType = CreateObject(assemblyPath, className);
return (IDal.IUser)objType;
}
#endregion
}
}
【注】:在最后面我们可以看到CreateUser()返回的是接口类型,使用到了接口的多态,让我们看看这两个类 User和IUser
User
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jxmstc.Model;
using Jxmstc.IDal;
using Jxmstc.DbUtility;
using System.Data.Common;
using System.Data;
namespace Jxmstc.Dal
{
public class User : IUser
{
protected CustomDbParameterCollection Parameters;
protected OutputValueCollection outParameters;
#region 构造函数
/// <summary>
/// 初始化User的实例。
/// </summary>
public User()
{
Parameters = new CustomDbParameterCollection();
outParameters = new OutputValueCollection();
}
/// <summary>
/// 根据配置文件中给定的连接字串,初始化User的实例。
/// </summary>
/// <param name="connectiongStringKey">配置文件中指定的连接字符串</param>
public User(string connectionStringKey)
{
Parameters = new CustomDbParameterCollection(connectionStringKey);
}
#endregion
#region 自定义方法
protected void FillModel(ref Model.UserInfo model, IDataReader dr)
{
try
{
if (dr.Read())
{
model = new UserInfo();
model.UserId = Convert.ToInt32(dr["UserId"]);
model.Account = dr["Account"].ToString();
model.Password = dr["Password"].ToString();
model.State = Convert.ToBoolean(dr["State"]);
model.Type = Convert.ToInt32(dr["Type"]);
model.Problem1 = dr["Problem1"].ToString();
model.Answer1 = dr["Answer1"].ToString();
model.Problem2 = dr["Problem2"].ToString();
model.Answer2 = dr["Answer2"].ToString();
}
}
catch
{
throw;
}
finally
{
dr.Dispose();
}
}
#endregion
#region IUser 成员
/// <summary>
/// 通过用户名获取Model 对象
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
public UserInfo GetModel(string account)
{
Model.UserInfo model = null;
Parameters.Clear();
Parameters.AddInParameter("@Account", DbType.String, account);
IDataReader dr = DbHelper.ExecuteReader("up_User_GetModelByAccount", Parameters);
FillModel(ref model, dr);
return model;
}
/// <summary>
/// 通过用户ID获取 权限ID、模块名、操作名、状态(T/F)
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns></returns>
public DataSet GetUserPrivilege(int userId)
{
Parameters.Clear();
Parameters.AddInParameter("@UserId", DbType.Int32, userId);
return DbHelper.ExecuteDataSet("up_Privilege_ByUserId", Parameters);
}
#endregion
}
}
IUser:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jxmstc.Model;
using System.Data;
using System.Data.SqlClient;
namespace Jxmstc.IDal
{
/// <summary>
/// 用户表
/// </summary>
public interface IUser
{
/// <summary>
/// 获取对象实体
/// </summary>
/// <param name="account">用户账号</param>
/// <returns>对象实体</returns>
Model.UserInfo GetModel(string account);
/// <summary>
/// 通过用户ID获取改用户在模块上操作的所有权限 既 权限ID、模块名、操作名、状态(T/F)
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns></returns>
DataSet GetUserPrivilege(int userId);
}
}
前面的User如果用三层来讲的话,属于DAL层和数据库打交道 IUser属于一个映射的桥梁,在BLL层的User中就可以看到作用
Bll.User
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jxmstc.Model;
using Jxmstc.IDal;
using Jxmstc.DalFactory;
using System.Data;
using System.Data.SqlClient;
namespace Jxmstc.Bll
{
/// <summary>
/// 业务逻辑类User 的摘要说明。
/// </summary>
public class User
{
private readonly IUser dal = DataAccess.CreateUser();
public User()
{ }
#region 成员方法
/// <summary>
/// 通过对象得到对象实体
/// </summary>
/// <param name="account"></param>
/// <returns></returns>
public Model.UserInfo GetModel(string account)
{
return dal.GetModel(account);
}
public DataSet GetUserPrivilege(int userId)
{
return dal.GetUserPrivilege(userId);
}
#endregion
}
}
[注]:这样接口调用的方法就会到DAL层下的User具体方法下,使用到了多态性
Head-First中有讲到工厂模式和简单工厂模式,主要提倡的是使用abstruct, 这也就是abstract和interface的区别
abstract是相关对象中抽象出来的概念,反映的是事物的内部共性,而接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性。
感觉Head-First对工厂模式讲解的不到位,到时候把小胖的大话模式给蹭过来看,嘿嘿。