在实际项目中如何应用门面模式(Facade)
我选择在项目中采用Nhibernate+Spring.Net+Asp.Net + Jquery 来作为我的主要.Net技术,我的框架的设计借鉴了博客园博主 传说中的弘哥博主的大量的技术思路 http://www.cnblogs.com/legendxian/ 结合了自己在实际项目中的经验,下面介绍我选择这套技术的思路和理由:
1.技术选择Nhibernate理由:
对象关系映射技术(ORM)的最主要目的是为了解决关系数据库与面向对象编程技术不匹配的阻抗问题,通常所说的面向对象的类往往都存在继承和类间关系与数据库的表不是—对应的,ORM 技术可屏蔽掉数据库访问的技术细节,让我们更专注于业务和UI实现,另外不能强制要求客户使用固定的数据库产品,Nhibernate 很大程度上屏蔽了不同数据库产品之间差异,使我们不必对不同数据库产品写具体实现,类库设计的原则:高内聚,低耦合。
(1)系统结构类图
1. 数据访问层:
主要用NHibernate访问数据库,但也有可能去访问其他模块或系统的WebService,也有可能用Linq去访问一些缓存(内存中的)数据。
2. 业务领域层:
所有与数据访问无关的业务逻辑都应该内聚在这里,业务领域对象理论上应该是充血的,内聚自己的业务逻辑。但有一些业务逻辑在设计的时候涉及到了多个业务领域对象 ,我们很难决定放在哪个具体的业务对象里,所以我们有一个Service层来放这种业务逻辑。
3. 门面层:
把数据访问接口,业务领域对象的业务逻辑,Service接口简单的封装一下成为Facade层接口供展示层UI或SOA层调用,这个层可以避免界面和数据库的平凡的交互。
数据访问层
{
T Load(string id);
T Get(string id);
IList<T> GetAll();
void SaveOrUpdate(T entity);
void Update(T entity);
void Delete(string id);
void PhysicsDelete(string id);
}
Repository.cs 数据访问层采用Nhibernate 实现
using System;
using System.Linq;
using System.Text;
using Demo.HIS.FrameWork.DomainBase;
using NHibernate;
using NHibernate.Criterion;
using Demo.HIS.FrameWork.Repository.NHb;
namespace Demo.HIS.FrameWork.Repository.Nhb
{
public class RepositoryNhbImpl<T> : IRepository<T> where T : Entity
{
protected virtual ISession Session
{
get { return SessionBuilder.CreateSession(); }
}
#region IRepository<T> 成员
public virtual T Load(string id)
{
try
{
T reslut = Session.Load<T>(id);
if (reslut == null)
throw new RepositoryException("返回实体为空");
else
return reslut;
}
catch (Exception ex)
{
throw new RepositoryException("获取实体失败", ex);
}
}
public virtual T Get(string id)
{
try
{
T reslut = Session.Get<T>(id);
if (reslut == null)
throw new RepositoryException("返回实体为空");
else
return reslut;
}
catch (Exception ex)
{
throw new RepositoryException("获取实体失败", ex);
}
}
public virtual IList<T> GetAll()
{
return Session.CreateCriteria<T>()
.AddOrder(Order.Asc("CreateTime"))
.List<T>();
}
public virtual void SaveOrUpdate(T entity)
{
try
{
Session.SaveOrUpdate(entity);
Session.Flush();
}
catch (Exception ex)
{
throw new RepositoryException("插入实体失败", ex);
}
}
public virtual void Update(T entity)
{
try
{
Session.Update(entity);
Session.Flush();
}
catch (Exception ex)
{
throw new RepositoryException("更新实体失败", ex);
}
}
public virtual void PhysicsDelete(string id)
{
try
{
var entity = Get(id);
Session.Delete(entity);
Session.Flush();
}
catch (System.Exception ex)
{
throw new RepositoryException("物理删除实体失败", ex);
}
}
public virtual void Delete(string id)
{
try
{
var entity = Get(id);
entity.IsDelete = true;
Update(entity);
}
catch (System.Exception ex)
{
throw new RepositoryException("删除实体失败", ex);
}
}
#endregion
}
}
业务领域层: IMenuRepository 菜单模块业务领域逻辑
using System;
using System.Linq;
using System.Text;
namespace Demo.HIS.Infrastructure.Core.Authority.Repositories
{
public interface IMenuRepository : IRepository<MenuNode>
{
bool IsFieldExist(string fieldName, string fieldValue, string id);
IList<MenuNode> GetListByUserId(string userId);
IList<MenuNode> GetListByRoleId(string roleId);
/// <summary>
/// 获取用户常用菜单列表
/// <remarks>排除用户没权限的菜单</remarks>
/// </summary>
/// <param name="userId">用户Id</param>
/// <returns></returns>
IList<MenuNode> GetUserFavoriteList(string userId);
}
}
门面层接口:IMenuFacade.cs 此处设计一个抽象的外观类可以方便扩张和需求的变化
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demo.HIS.FrameWork;
using Demo.HIS.FrameWork.DomainBase;
using Demo.HIS.Infrastructure.Core.Authority.Repositories;
using Demo.HIS.Infrastructure.Core.Authority;
namespace Demo.HIS.Infrastructure.Facade.Authority
{
public interface IMenuFacade : IDomainFacade
{
IList<MenuNode> GetAlllist();
bool IsFieldExist(string fieldName, string fieldValue, string id);
void SaveOrUpdate(MenuNode entity);
void Delete(string id);
MenuNode Get(string id);
MenuNode Load(string id);
IList<ActionPermission> QueryActionPlist(string query, int start, int limit, out long total);
IList<MenuNode> GetMenuListByRoleId(string roleId);
}
}
MenuFacadeImpl.cs 实现IMenuFacade.cs 对业务逻辑的封装,便于界面的类的调用。
using System;
using System.Linq;
using System.Text;
using Demo.HIS.Infrastructure.Core.Authority.Repositories;
using Demo.HIS.Infrastructure.Core.Authority;
using Demo.HIS.FrameWork.DomainBase;
using Demo.HIS.Infrastructure.Core.Authority.Services;
namespace Demo.HIS.Infrastructure.Facade.Authority.Impl
{
public class MenuFacadeImpl : IMenuFacade
{
private readonly IMenuRepository MenuRepository;
private readonly IActionPermissionService ActionPermissionService;
public MenuFacadeImpl(IMenuRepository MenuRepository, IActionPermissionService ActionPermissionService)
{
this.MenuRepository = MenuRepository;
this.ActionPermissionService = ActionPermissionService;
}
#region IMenuFacade 成员
public IList<MenuNode> GetAlllist()
{
return MenuRepository.GetAll();
}
public bool IsFieldExist(string fieldName, string fieldValue, string id)
{
return MenuRepository.IsFieldExist(fieldName, fieldValue, id);
}
public void SaveOrUpdate(MenuNode entity)
{
MenuRepository.SaveOrUpdate(entity);
}
public void Delete(string id)
{
MenuRepository.Delete(id);
}
public MenuNode Get(string id)
{
return MenuRepository.Get(id);
}
public MenuNode Load(string id)
{
return MenuRepository.Load(id);
}
public IList<ActionPermission> QueryActionPlist(string query, int start, int limit, out long total)
{
return ActionPermissionService.QueryActionPlist(query,start,limit,out total);
}
public IList<MenuNode> GetMenuListByRoleId(string roleId)
{
return MenuRepository.GetListByRoleId(roleId);
}
#endregion
}
}
MenuRepositoryImpl.cs 业务领域逻辑具体实现
using System;
using System.Linq;
using System.Text;
using Demo.HIS.Infrastructure.Core.Authority.Repositories;
using Demo.HIS.Infrastructure.Core.Authority;
using Demo.HIS.FrameWork.Repository;
using Demo.HIS.FrameWork;
using Demo.HIS.FrameWork.DomainBase;
using Demo.HIS.FrameWork.Repository.Nhb;
namespace Demo.HIS.Infrastructure.Repositories.Authority
{
public class MenuRepositoryImpl : RepositoryNhbImpl<MenuNode>, IMenuRepository
{
public override void SaveOrUpdate(MenuNode entity)
{
if (IsFieldExist("TreeCode", entity.TreeCode, entity.Id, null))
throw new ExistException("TreeCode");
base.SaveOrUpdate(entity);
}
public override void Delete(string id)
{
var entity = Get(id);
if (IsChildForNotLeaf(id))
throw new ValidationException("所选项下面存在子项,无法删除!");
base.Delete(id);
}
#region IMenuRepository 成员
public bool IsFieldExist(string fieldName, string fieldValue, string id)
{
return base.IsFieldExist(fieldName, fieldValue, id, null);
}
public IList<MenuNode> GetListByUserId(string userId)
{
var query = Session.CreateQuery(@"select distinct t
from MenuNode as t
left join t.Roles as r
left join r.Persons p
where p.Id = :UserId and r.IsDelete = 0 and p.IsDelete = 0 and p.State = :PersonState and r.State=:RoleState order by t.Index asc")
.SetString("UserId", userId)
.SetEnum("PersonState", PersonState.Normal)
.SetEnum("RoleState", RoleState.Normal);
return query.List<MenuNode>();
}
public IList<MenuNode> GetListByRoleId(string roleId)
{
var query = Session.CreateQuery(@"select distinct t
from MenuNode as t
left join t.Roles as r
where r.Id = :RoleId and r.IsDelete = 0 and r.State = :RoleState")
.SetString("RoleId", roleId)
.SetEnum("RoleState", RoleState.Normal);
return query.List<MenuNode>();
}
public IList<MenuNode> GetUserFavoriteList(string userId)
{
var query = Session.CreateQuery(@"select distinct t
from MenuNode as t
left join t.FavoritedUsers u
left join u.Roles ur
where u.Id = :UserId and u.IsDelete = 0 and ur.IsDelete = 0 and u.State = :PersonState and ur.State = :RoleState
and exists (select m from MenuNode as m
left join m.Roles as mr
where mr.Id = ur.Id and t.Id = m.Id
and mr.IsDelete = 0 and mr.State = :RoleState)")
.SetString("UserId", userId)
.SetEnum("PersonState", PersonState.Normal)
.SetEnum("RoleState", RoleState.Normal);
return query.List<MenuNode>();
}
#endregion
private bool IsChildForNotLeaf(string id)
{
var query = Session.CreateQuery(@"select count(*) from MenuNode as o where o.ParentId=:ParentId")
.SetString("ParentId", id);
return query.UniqueResult<long>() > 0;
}
}
}
初学者在学习设计模式的过程中,很难理解设计模式在具体项目中如何应用,我非常喜欢设计模式,设计模式蕴含着软件设计的很重要的思想,真正的要描述设计模式在实际项目中如何运用其实还是比较难的,主要是代码会很多,建议初学者去看一些比较好的源代码,去研究别人的设计思想,这样会有很大的提高。
门面模式介绍 http://blog.csdn.net/lovelion/article/details/7798064