zoukankan      html  css  js  c++  java
  • 一个分层架构设计的例子(2)

    接着上一篇关于分层架构的讨论,一个分层架构设计的例子(1)
    上篇介绍了实体类(Entity)、数据库访问类(DAL)、数据访问接口(IDAL)的相关设计,本篇主要讨论下面几个部分内容:业务逻辑层、缓存机制、界面层等方面。
    业务逻辑层,主要是业务逻辑基类的设计,由于数据库访问类(DAL)的基类封装了大量的操作实现,因此,业务逻辑层的主要工作是进一步封装对底层访问接口的实现,如下所示。
        public class BaseBLL<T> where T : BaseEntity, new()
        
    {
            
    构造函数

            
    对象添加、修改、删除等接口

            
    返回集合的接口
        }

    业务层基类封装了大量的调用,那么对于业务层的具体操作类,它的工作就很简单了,基本上只需要继承一下基类就可以了,这就是有一个优秀父亲的好处,呵呵
        public class Equipment : BaseBLL<EquipmentInfo>
        
    {
            
    public Equipment() : base()
            
    {
            }

        }

    基本上,业务层的设计到此应该收尾了,可是我们注意到,很多开发都使用了缓存的机制来进一步提高程序的性能,下面对这方面进行讨论。缓存的机制,一般是把创建过的对象资源放到一个集合中,需要的时候,调出来,如下业务层的工厂类所示。
        public class BLLFactory<T> where T : class
        
    {
            
    private static Hashtable objCache = new Hashtable();
            
    public static T Instance
            
    {
                
    get
                
    {
                    
    string CacheKey = typeof(T).FullName;
                    T bll 
    = (T)objCache[CacheKey];  //从缓存读取  
                    if (bll == null)
                    
    {
                        bll 
    = Reflect<T>.Create(typeof(T).Name, "HuaweiSoftware.IPSPBD.BLL"); //反射创建,并缓存
                    }

                    
    return bll;
                }

            }

        }
      

    这是一个业务逻辑类工厂创建类,我们在界面层只需要如下调用即可构造一个(利用了缓存)具体的业务类出来
    CustomerInfo info = BLLFactory<Customer>.Instance.FindByID(ID);

    在上面的BaseBLL和BLLFactory类中,有一个Reflect的操作类,这是反射缓存的具体实现所在,我们探讨一下它的实现。
        public class Reflect<T> where T : class 
        
    {
            
    private static Hashtable m_objCache = null;
            
    public static Hashtable ObjCache
            
    {
                
    get
                
    {
                    
    if (m_objCache == null)
                    
    {
                        m_objCache 
    = new Hashtable();
                    }

                    
    return m_objCache;
                }

            }


            
    public static T Create(string sName, string sFilePath)
            
    {
                
    return Create(sName, sFilePath, true);
            }

            
    public static T Create(string sName, string sFilePath, bool bCache)
            
    {
                
    string CacheKey = sFilePath + "." + sName;
                T objType 
    = null;
                
    if (bCache)
                
    {
                    objType 
    = (T)ObjCache[CacheKey];    //从缓存读取 
                    if (!ObjCache.ContainsKey(CacheKey))
                    
    {
                        Assembly assObj 
    = CreateAssembly(sFilePath);
                        
    object obj = assObj.CreateInstance(CacheKey);
                        objType 
    = (T)obj;

                        ObjCache.Add(CacheKey, objType);
    // 写入缓存 将DAL内某个对象装入缓存
                    }

                }

                
    else
                
    {
                    objType 
    = (T)CreateAssembly(sFilePath).CreateInstance(CacheKey); //反射创建 
                }


                
    return objType;
            }


            
    public static Assembly CreateAssembly(string sFilePath)
            
    {
                Assembly assObj 
    = (Assembly)ObjCache[sFilePath];
                
    if (assObj == null)
                
    {
                    assObj 
    = Assembly.Load(sFilePath);
                    ObjCache.Add(sFilePath, assObj);
    //将整个DLL装入缓存
                }

                
    return assObj;
            }

        }


    另外,如果你在业务层需要实现更加复杂的功能,而数据库访问基类BaseDAL提供的函数不能满足你的需要,可以扩展数据访问层的接口和实现,如下所示。
        public interface ICustomer : IBaseDAL<CustomerInfo>
        
    {
            List
    <string> GetAllCustomerNumber();

            CustomerInfo GetByCustomerNumber(
    string number);
        }



        
    public class Customer : BaseDAL<CustomerInfo>, ICustomer
        
    {
            
    对象实例及构造函数

            

            
    ICustomer 成员
        }


    那么在业务层的类修改如下
        public class Customer : BaseBLL<CustomerInfo>
        
    {
            
    public Customer() : base()
            
    {
            }


            
    public List<string> GetAllCustomerNumber()
            
    {
                ICustomer customerDAL 
    = baseDal as ICustomer;
                
    return customerDAL.GetAllCustomerNumber();
            }


            
    public CustomerInfo GetByCustomerNumber(string number)
            
    {
                ICustomer customerDAL 
    = baseDal as ICustomer;
                
    return customerDAL.GetByCustomerNumber(number);
            }

        }

    最后,界面方面的设计是见仁见智,但根本一条是利用一些控件,可以统一风格,减少劳动,给出几个界面的设计截图供大家参考
    WinForm方面的(颜色标明的是使用了特定的界面控件,其中红色部分为和整个架构整合起来的分页控件,集成了一些基本的右键菜单操作,包括打印功能、数据导出功能等):
    WinForm_UI1.jpg

    Winform分页控件设计视图
    GridViewPager.jpg

    可以选择列进行打印
    GridViewPager_PrintOption.jpg

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


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

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

    WebForm_UI1.jpg

    修改内容时候的编辑控件
    WebForm_UI2.jpg


    查看内容时候的编辑控件
    WebForm_UI3.jpg


    以上所引用的代码是通过代码生成工具Database2Sharp自动生成(http://www.iqidi.com/Database2Sharp.htm),选择EnterpriseLibrary架构即可。
    Database2Sharp_Enterprise.jpg
    主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发
    专注于Winform开发框架/混合式开发框架Web开发框架Bootstrap开发框架微信门户开发框架的研究及应用
      转载请注明出处:
    撰写人:伍华聪  http://www.iqidi.com 
        
  • 相关阅读:
    asp读书笔记(二)内置对象
    网上收集的关于iframe的自适应高度代码js的
    第一遇到地震,虽然小点
    给网友写的控制页面元素高度的代码(js)
    给用户控件添加可枚举的属性
    标记(Tagging)能给网站带来的7大益处
    代码最重要的读者不再是编译器、解释器或者电脑,而是人!
    亚洲超大数据库会议(XLDB Asia 2012)
    每年15万美元!这是开发人员解决构造问题的总成本!
    华章IT图书书讯(2012年第7期)
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/1236832.html
Copyright © 2011-2022 走看看