关于OA项目BLL层的一点疑问

[ 2297 查看 / 17 回复 ]

下面BLL层的代码中,机构类持有的是一个DALFactory的引用,也就是说,BLL层依赖着DALFactory这个工厂。有点不明白的是,为何不可以持有一个 IDAL 的引用?像这个样子:IDAL机构 dal = null; 然后通过抽象工厂返回一个实现了 IDAL.IDAL机构 接口的对象,通过这个对象去做‘CRUD’,这样也就用到了多态。貌似,只有接口是稳定的,而工厂甚至都不是稳定的,如果不想用抽象工厂模式来构建 接口的实现类 而换成别的,那也是没有问题的(甚至要改变存储的方式,不再持久化到数据库里,而是xml中)。
BLL层是否可以改为 依赖 DAL层的接口呢(也就是IDAL层)?

namespace OA.BLL
{
    public class 机构
    {
        private DALFactory.DALFactory dataFactory = DataProvider.DefaultProvider;

        #region 增
        public int 添加(Entity.机构 obj)
        {
            //通过工厂获得当前提供程序
            //用反射,通过web.config获得当前提供程序的名,再实例化
1

评分次数

    本主题由 管理员 张波老师 于 2009-11-17 11:44:01 执行 设置精华/取消 操作
    TOP

    为何不可以持有一个 IDAL 的引用?像这个样子:IDAL机构 dal = null; 然后通过抽象工厂返回一个实现了 IDAL.IDAL机构 接口的对象
    BLL层是否可以改为 依赖 DAL层的接口呢(也就是IDAL层)?

    这样的话,IDAL实例的创建交给BLL具体每个类了.
    此时,如果需要缓存IDAL实例,这个工作也要由BLL完成.将来再对IDAL实例的创建做出修改的话,N个BLL类,就要修改N次.
    我们是把IDAL实例的创建职责,聚合到工厂类,由工厂统一完成,从而避免了BLL依赖IDAL的同时,还要维护IDAL的创建和变化这种耦合度过高的被动局面.
    设计模式前言中会讲到:类的职责分配原则,每个类应专注于做"自己"的事情.
    TOP

    shenyoujia同学:
    这个回复看到了吗?继续讨论,这个问题本身很好,值得仔细推敲的.
    TOP

    我看到了回复。我个人的理解是,在BLL层的某个类中(就拿机构来说),可以有如下的代码(或者伪代码):
    private IDAL.IDAL机构 idal = DataProvider.DefaultProvider;
    贴出原先的代码如下:
    private DALFactory.DALFactory dataFactory = DataProvider.DefaultProvider;

    两者对比一下,可以发现,仅仅是这个 BLL.机构 其所持有的成员变量有所改变。如果BLL层是依赖于IDAL层,那么我就可以直接持有一个‘接口’的引用,至于在运行时这个接口指向哪个具体实现,那是暂时不必考虑的。也就是说,‘等号右边’(很不专业,只求表达意思)给这个 成员变量 赋值的过程,可能是一个‘抽象工厂’返回的实例,也可以由任何可以使用的方法返回(包括 反射  等等,当然最最不济的就是 new)。
    TOP

    如果BLL层是依赖于IDAL层,那么我就可以直接持有一个‘接口’的引用,至于在运行时这个接口指向哪个具体实现,那是暂时不必考虑的。

    这句话,是很赞同的.

    我想我明白你的意思了.
    在你说:private IDAL.IDAL机构 idal = DataProvider.DefaultProvider;
    这样,应该改一改:private IDAL.IDAL机构 idal = DataProvider.DefaultProvider.IDAL机构;
    而我们之前的代码:
    private DALFactory.DALFactory dataFactory = DataProvider.DefaultProvider;
    然后再在BLL里调用dataFactory.IDAL机构.

    那末,我举一个情形:
    如果在BLL的机构里,需要使用到IDAL员工,该怎么办?
    TOP

    BLL层的机构类中,可以持有多个引用(需要IDAL接口的哪个,就持有那个引用)
    private IDAL.IDAL机构 idal机构 = null;
    private IDAL.IDAL员工 idal员工 = null;

    上面的代码,只是声明持有哪个引用,具体要new(通俗讲是new,其实就是设计模式中的‘创建型模式’,而具体是怎么创建出来的,可以使用工厂模式等等——因为创建的方式本身也是多样化的,可以是工厂模式也可以是别的,貌似也不宜跟某种特定模式耦合)的代码在下面:
    idal机构=DataProvider.DefaultProvider.IDAL机构;
    idal员工=DataProvider.DefaultProvider.IDAL员工;

    说到这样的话,感觉还可以再多一个‘类库’——工具类(比如起名为:Util),专门负责‘创建对象’——其中定义一个方法getDALProvider(OA.Entity entity),通过抽象工厂,返回一个具体的DAL类(如,DAL机构Provider  or DAL员工Provider)。
    这样上述代码就可以改成
    idal机构=(OA.IDAL.IDAL机构)Util.getDALProvider(OA.Entity.机构);
    idal员工=(OA.IDAL.IDAL员工)Util.getDALProvider(OA.Entity.员工);

    以上观点只是‘构思’,不一定成熟,欢迎批评指正,谢谢!
    TOP

    实例创建要通过工厂,这个已经达成一致的.没有问题.

    关于BLL如果引用IDAL,你的做法也是正确的(从运行的角度)完全没有问题,
    我们讨论的,应该是如何引用的问题.这是OOD中一点细微的差别,如果探究,就是一个"代码的感觉舒服不舒服"的话题.

    下面继续讨论:
    private IDAL.IDAL机构 idal机构 = null;
    private IDAL.IDAL员工 idal员工 = null;
    ..................
    这种写法呢,是一个BLL类维护N个引用.哪天增加一个IDALXXXX,那末,所有需要使用IDALXXXX的BLL类都要改代码,以增加一个引用.
    示意:  1个BLL->N个具体产品
    我们上课时讲的,
    是一个BLL只引用 一个DataProvider(也就是一个抽象工厂的引用).由这个抽象工厂的实例(DefaultProvider)提供N个具体IDAL的实例..哪天增加一个IDALXXXX,只需要在工厂的定义中添加一个成员(具体工厂实现也加该成员),所有持有工厂引用 的BLL就自然获得了IDALXXX.
    示意: 1个BLL ->一个工厂实例 ->N个具体产品.

    其实你也意识到了你的那种设计有点"不灵活"吧,所以你说再增加一个Util工具类.
    但你仔细品味一下,这个Util类,其实就是充当了工厂的角色,也就是说,本质上Util类,就是一个简单工厂的应用.
    TOP

    回复 7# 张波老师 的帖子

    恩,这个我倒是没有想过。。如果在BLL层要改需求的话(本来只依赖DAL层中的一个类,现在要依赖2个类,需要改变的地方会比较多)。。

    private IDAL.IDAL机构 idal机构 = null;
    private IDAL.IDAL员工 idal员工 = null;

    这样的设计,是为了使用‘依赖注入’或者‘依赖查找’,也就是说,我在BLL层中的类,只是声明需要使用到的类(也就是依赖于DAL层中的类),至于这个类的实例对象最后怎么拿到,是依赖注入进来(推模式)还是依赖查找取来(拉模式),倒显得不是很重要。设计一个Util类,是为了实现‘依赖查找’,呵呵!如果可以有一个容器来负责专门产生相关的类,那就方便查找了;如果这个容器还能支持‘推模式’可以实现ioc,即只要在配置文件中配上就能给我把这两个类实例化并且给注射进来,那对于调用者就更方便了。对.net体系结构还不是很了解,不清楚这样的设想是否有可能实现,唯假想耳。。
    TOP

    无巧不成书,刚google了一下entlib,发现好像还真提供了依赖注入容器
    http://entlibforum.cnblogs.com/

    依赖注入容器(Unity Application Block) Enterprise Library - Unity Application Block 学习手册(最新版) Part 1
    Enterprise Library - Unity Application Block 学习手册(最新版) Part 2
    Enterprise Library - Unity Application Block 学习手册(最新版) Part 3
    Enterprise Library - Unity Application Block 学习手册(最新版) Part 4
    TOP

    回复 8# shenyoujia 的帖子

    这个话题你现在明白了吗?
    依赖注入的东西,可以单独讨论.但这个话题应该可以关闭了.
    EntLib4就有的,通过看它的源码就能看到,还有提供一个示例程序.
    个人认为,当前我们讨论的话题,还不至于用到依赖注入.
    其他也不算巧合哦,很多我们觉得很复杂的问题,其实已经有人想到过,甚至于系统的开发过框架之类的.
    说明,学无止境.
    但就目前的根基,学的不宜过多,要精一个,通多个.
    TOP