博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个分层架构设计的例子(2)
阅读量:6296 次
发布时间:2019-06-22

本文共 3136 字,大约阅读时间需要 10 分钟。

接着上一篇关于分层架构的讨论,

上篇介绍了实体类(Entity)、数据库访问类(DAL)、数据访问接口(IDAL)的相关设计,本篇主要讨论下面几个部分内容:业务逻辑层、缓存机制、界面层等方面。

业务逻辑层,主要是业务逻辑基类的设计,由于数据库访问类(DAL)的基类封装了大量的操作实现,因此,业务逻辑层的主要工作是进一步封装对底层访问接口的实现,如下所示。
None.gif
    
public
 
class
 BaseBLL
<
T
>
 
where
 T : BaseEntity, 
new
()
ExpandedBlockStart.gif    
{
ContractedSubBlock.gif        
构造函数
InBlock.gif
ContractedSubBlock.gif        
对象添加、修改、删除等接口
InBlock.gif
ContractedSubBlock.gif        
返回集合的接口
ExpandedBlockEnd.gif    }
业务层基类封装了大量的调用,那么对于业务层的具体操作类,它的工作就很简单了,基本上只需要继承一下基类就可以了,这就是有一个优秀父亲的好处,呵呵
None.gif
    
public
 
class
 Equipment : BaseBLL
<
EquipmentInfo
>
ExpandedBlockStart.gif    
{
InBlock.gif        
public Equipment() : base()
ExpandedSubBlockStart.gif        
{
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }
基本上,业务层的设计到此应该收尾了,可是我们注意到,很多开发都使用了缓存的机制来进一步提高程序的性能,下面对这方面进行讨论。缓存的机制,一般是把创建过的对象资源放到一个集合中,需要的时候,调出来,如下业务层的工厂类所示。
None.gif
    
public
 
class
 BLLFactory
<
T
>
 
where
 T : 
class
ExpandedBlockStart.gif    
{
InBlock.gif        
private static Hashtable objCache = new Hashtable();
InBlock.gif        
public static T Instance
ExpandedSubBlockStart.gif        
{
InBlock.gif            
get
ExpandedSubBlockStart.gif            
{
InBlock.gif                
string CacheKey = typeof(T).FullName;
InBlock.gif                T bll 
= (T)objCache[CacheKey];  //从缓存读取  
InBlock.gif
                if (bll == null)
ExpandedSubBlockStart.gif                
{
InBlock.gif                    bll 
= Reflect<T>.Create(typeof(T).Name, "HuaweiSoftware.IPSPBD.BLL"); //反射创建,并缓存
ExpandedSubBlockEnd.gif
                }
InBlock.gif                
return bll;
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }
  
这是一个业务逻辑类工厂创建类,我们在界面层只需要如下调用即可构造一个(利用了缓存)具体的业务类出来

None.gif
CustomerInfo info 
=
 BLLFactory
<
Customer
>
.Instance.FindByID(ID);
在上面的BaseBLL和BLLFactory类中,有一个Reflect的操作类,这是反射缓存的具体实现所在,我们探讨一下它的实现。
None.gif
    
public
 
class
 Reflect
<
T
>
 
where
 T : 
class
 
ExpandedBlockStart.gif    
{
InBlock.gif        
private static Hashtable m_objCache = null;
InBlock.gif        
public static Hashtable ObjCache
ExpandedSubBlockStart.gif        
{
InBlock.gif            
get
ExpandedSubBlockStart.gif            
{
InBlock.gif                
if (m_objCache == null)
ExpandedSubBlockStart.gif                
{
InBlock.gif                    m_objCache 
= new Hashtable();
ExpandedSubBlockEnd.gif                }
InBlock.gif                
return m_objCache;
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif        
public static T Create(string sName, string sFilePath)
ExpandedSubBlockStart.gif        
{
InBlock.gif            
return Create(sName, sFilePath, true);
ExpandedSubBlockEnd.gif        }
InBlock.gif        
public static T Create(string sName, string sFilePath, bool bCache)
ExpandedSubBlockStart.gif        
{
InBlock.gif            
string CacheKey = sFilePath + "." + sName;
InBlock.gif            T objType 
= null;
InBlock.gif            
if (bCache)
ExpandedSubBlockStart.gif            
{
InBlock.gif                objType 
= (T)ObjCache[CacheKey];    //从缓存读取 
InBlock.gif
                if (!ObjCache.ContainsKey(CacheKey))
ExpandedSubBlockStart.gif                
{
InBlock.gif                    Assembly assObj 
= CreateAssembly(sFilePath);
InBlock.gif                    
object obj = assObj.CreateInstance(CacheKey);
InBlock.gif                    objType 
= (T)obj;
InBlock.gif
InBlock.gif                    ObjCache.Add(CacheKey, objType);
// 写入缓存 将DAL内某个对象装入缓存
ExpandedSubBlockEnd.gif
                }
ExpandedSubBlockEnd.gif            }
InBlock.gif            
else
ExpandedSubBlockStart.gif            
{
InBlock.gif                objType 
= (T)CreateAssembly(sFilePath).CreateInstance(CacheKey); //反射创建 
ExpandedSubBlockEnd.gif
            }
InBlock.gif
InBlock.gif            
return objType;
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif        
public static Assembly CreateAssembly(string sFilePath)
ExpandedSubBlockStart.gif        
{
InBlock.gif            Assembly assObj 
= (Assembly)ObjCache[sFilePath];
InBlock.gif            
if (assObj == null)
ExpandedSubBlockStart.gif            
{
InBlock.gif                assObj 
= Assembly.Load(sFilePath);
InBlock.gif                ObjCache.Add(sFilePath, assObj);
//将整个DLL装入缓存
ExpandedSubBlockEnd.gif
            }
InBlock.gif            
return assObj;
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }
另外,如果你在业务层需要实现更加复杂的功能,而数据库访问基类BaseDAL提供的函数不能满足你的需要,可以扩展数据访问层的接口和实现,如下所示。
None.gif
    
public
 
interface
 ICustomer : IBaseDAL
<
CustomerInfo
>
ExpandedBlockStart.gif    
{
InBlock.gif        List
<string> GetAllCustomerNumber();
InBlock.gif
InBlock.gif        CustomerInfo GetByCustomerNumber(
string number);
ExpandedBlockEnd.gif    }
None.gif
None.gif
None.gif    
public
 
class
 Customer : BaseDAL
<
CustomerInfo
>
, ICustomer
ExpandedBlockStart.gif    
{
ContractedSubBlock.gif        
对象实例及构造函数
InBlock.gif
InBlock.gif        dot.gifdot.gifdot.gifdot.gifdot.gifdot.gif
InBlock.gif
ContractedSubBlock.gif        
ICustomer 成员
ExpandedBlockEnd.gif    }
那么在业务层的类修改如下
None.gif
    
public
 
class
 Customer : BaseBLL
<
CustomerInfo
>
ExpandedBlockStart.gif    
{
InBlock.gif        
public Customer() : base()
ExpandedSubBlockStart.gif        
{
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif        
public List<string> GetAllCustomerNumber()
ExpandedSubBlockStart.gif        
{
InBlock.gif            ICustomer customerDAL 
= baseDal as ICustomer;
InBlock.gif            
return customerDAL.GetAllCustomerNumber();
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif        
public CustomerInfo GetByCustomerNumber(string number)
ExpandedSubBlockStart.gif        
{
InBlock.gif            ICustomer customerDAL 
= baseDal as ICustomer;
InBlock.gif            
return customerDAL.GetByCustomerNumber(number);
ExpandedSubBlockEnd.gif        }
ExpandedBlockEnd.gif    }
最后,界面方面的设计是见仁见智,但根本一条是利用一些控件,可以统一风格,减少劳动,给出几个界面的设计截图供大家参考

WinForm方面的(颜色标明的是使用了特定的界面控件,其中红色部分为和整个架构整合起来的分页控件,集成了一些基本的右键菜单操作,包括打印功能、数据导出功能等):

WinForm_UI1.jpg

Winform分页控件设计视图

GridViewPager.jpg

可以选择列进行打印

GridViewPager_PrintOption.jpg

在实际运用过程中的界面效果

GridViewPager_Product.jpg

WebForm方面的(可以使用之前文章介绍的查询控件、分页控件、内容编辑控件):

下图是查询控件和分页控件的一起运用:


WebForm_UI1.jpg

修改内容时候的编辑控件

WebForm_UI2.jpg

查看内容时候的编辑控件

WebForm_UI3.jpg

以上所引用的代码是通过代码生成工具Database2Sharp自动生成(),选择EnterpriseLibrary架构即可。

Database2Sharp_Enterprise.jpg

本文转自博客园伍华聪的博客,原文链接:,如需转载请自行联系原博主。

你可能感兴趣的文章
入门到进阶React
查看>>
SVN 命令笔记
查看>>
检验手机号码
查看>>
重叠(Overlapped)IO模型
查看>>
Git使用教程
查看>>
使用shell脚本自动监控后台进程,并能自动重启
查看>>
Flex&Bison手册
查看>>
solrCloud+tomcat+zookeeper集群配置
查看>>
/etc/fstab,/etc/mtab,和 /proc/mounts
查看>>
Apache kafka 简介
查看>>
socket通信Demo
查看>>
技术人员的焦虑
查看>>
js 判断整数
查看>>
mongodb $exists
查看>>
js实现页面跳转的几种方式
查看>>
sbt笔记一 hello-sbt
查看>>
常用链接
查看>>
pitfall override private method
查看>>
!important 和 * ----hack
查看>>
聊天界面图文混排
查看>>