PetShop4.0--泛型升级

 

 

 

 

下载“泛型PetShop”源码网络上太多人在研究微软的一个开源项目了,可以用一句话来形容:麻省虽小,五脏俱全!那么这个小小的项目为什么会有那么多的人去议论它呢?它是什么项目呢?
名字叫做PetShop(宠物商店),它主要体现了微软的三层架构的思想。在此中主要体现为:

这就是微软的三层架构体系,如果还有不懂的朋友,建议上网找找这方面的资料,我在这里就不多说了。PetShop4.0就是为了让我们这些微软门外汉认识他的三层架构而开源的。下面就是PetShop4.0的主要架构:

以下是各层之间的关系:

 


因为它的架构不是我这次的重点,所以这里就一笔带过了。这个项目总体来说是不错的,此中利用了工厂模式、策略模式、对象封装(实体类,相当于JavaBean),面向接口编程及反射等技术。我主要是觉得在工厂模式和接口策略的时候不是很灵活,所以在此基础上作了一些改进:这是原来的DALFactory工厂,主要用于生成DAL接口的对象:

    public class Factory
    {
        public Factory()
        {

        }
        /// <summary>
        /// 返回IDAL.IAuthors的一个对象
        /// </summary>
        /// <returns></returns>
        public IDAL.IAuthors GetIAuthors()
        {
           String dal_authors = ConfigurationManager.AppSettings["DAL_Authors"];
            String path = dal_authors + ".Authors";
            return (IDAL.IAuthors)Assembly.Load(path).CreateInstance("Authors");
        }
    }

可以看到,在这里,想要生成不同的对象,只能再写一个方法。这太不灵活,也影响效率,更要命的是,这个工厂只能生成特定类型的对象。所以,就有了下面的这个升级版:

public class Factory<T>
    {

        public Factory()
        {
        }
        /// <summary>
        /// 根据配置文件生成一个传入的对象,并将其转为IDAL.IDALConll泛型接口
        /// </summary>
        /// <returns>IDAL.IDALConll</returns>
        public static IDAL.IDALConll<T> GetIDAL(String path, String Obj)
        {
            return (IDAL.IDALConll<T>)Assembly.Load(path).CreateInstance(Obj);
        }
    }

其实只作了一点改进,应用了泛型类,就已经使得原来只能生产一种对象的方法变成了可生成多种类型的方法,不管你有多少种,只要你传入<T>类型就可了,,而且在工厂里读取配置文件并不是一件令人愉快的事,所以这里改为方法里的参数接收;其实这里的作用是基于接口的,泛型工厂的产生是为了泛型接口,如果泛型接口不存在,那泛型工厂也没有存在的意义了,来看一下下面的代码:

    public interface IAuthors
    {
        /// <summary>
        /// 返回Authors实体类的集合
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        IList<Model.Authors> GetItemByAuthors(String qureystring);
        /// <summary>
        /// 返回Authors实体类单个对象
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        Model.Authors GetItem(SqlDataReader reader);        
    }

思考一下上面的代码,如果我有四个不同的类,每个类都有增删改查的方法,四个不同的类可不可以从接口继承来呢?作案是否定的,因为接口里面定义的方法返回的都是特定类型的值。那如果改成下面的泛型接口呢?

   public interface IDALConll<T>
    {
       /// <summary>
       /// 返回一个项集合
       /// </summary>
       /// <param name="sql"></param>
       /// <returns></returns>
       IList<T> GetItemConll(String sql);
       /// <summary>
       /// 返回一个单项
       /// </summary>
       /// <param name="reader"></param>
       /// <returns></returns>
       T GetItem(SqlDataReader reader);
       //以下是四个对数据库基本操作的方法
       T InsertInfo(T obj);
       T InsertInfo(T obj);
       T InsertInfo(T obj);
       T InsertInfo(T obj);
    }

从这里面大家应该看到了不同的东西,扩展性呢?当然是更上一层楼,其实这里的每个方法的返回值为T,只是为了一个展示,完全可以按照不同的需求改,但是方法里面的参数就不同了,代码简洁及可实现正是从此而来,子类在实现接口中的方法时,方法里的参数类型可改成实现类型;即:DAL.Authors:IDALConll<Model.Authors>

其中Model.Authors是实体类,

方法可写成public Model.Authors InsertInfo(Model.Authors authors){};

从这短短两行代码中,我们看到,这相当于子类继承抽象类的方法重写,是的,是相当于重写,但是比重写更灵活,重写的方法体里的参数不能改变,但是在这里却可以做到!

说到这里,大家是不是发现了什么?在百度这里的图片显示确实有点问题,那么大个图片只显示了一点点,抱歉了各位。以上只是看了PetShop4.0后的一点心得,欢迎大家留言探讨!

posted @ 2007-12-22 23:49 veter 阅读(399) 评论(16)  编辑 收藏

  回复  引用  查看    
#1楼 2008-01-28 13:39 | flyingchen      
图片都是百度的,这里一张看不到
  回复  引用  查看    
#2楼 [楼主]2008-01-29 00:17 | viter      
不好意思,之前的图片是在百度我的博客粘贴过来的,现在改了,谢谢你!
  回复  引用    
#3楼 2008-04-03 01:59 | beniao [未注册用户]
楼主可以发份实例给我学习下吗
我做了没成功.
在接口的实现类上报错
beniao123@163.com

  回复  引用  查看    
#4楼 [楼主]2008-04-03 18:10 | veter      
我已上传文件,在页首有链接!
  回复  引用    
#5楼 2008-04-03 18:32 | beniao [未注册用户]
@veter
老师,没找到你说的连接.
  回复  引用    
#6楼 2008-04-03 18:33 | beniao [未注册用户]
下载“泛型PetShop”源码
发现了. 藏在那不仔细还嘿难发现的.
  回复  引用  查看    
#7楼 2008-05-04 10:58 | 私家侦探      
高招!
看来兄弟对泛型技术已经炉火纯青.只是。。。

你这种做法必须要求dal层各个实现类中都有相同的方法名称,这似乎。。嘿嘿,有些强迫性,不太好,因为它们都实现相同的接口IDALConll
  回复  引用  查看    
#8楼 [楼主]2008-05-04 12:32 | veter      
其实这是充分利用了“面向对象”的思想,共性的东西当然可以实现同一个接口,不同的特点可以通过类实例访问,这应该是没什么问题的了,如果有两个以上的类有相同的属性,那又可以定义一个接口了。
  回复  引用  查看    
#9楼 2008-05-05 00:21 | 私家侦探      
---引用----------
不同的特点可以通过类实例访问
-----------------------------

如果这么做的话又失去切换dal层的作用啊,我有一个办法就是写一个适配器类用空的方法(方法中没有任何实现内容)去实现IDALConll中每个方法,然后dal层的每个类再去继承该适配器类,并重写和自己有关的方法

如果你每个dal类都只有增删改查存在这五个方法,那么这些类实现同一个接口没有错,但是dal类只有这五个方法能保证(估计)足够业务层使用吗?我看不一定.其实主要是要兼顾"能随时切换数据库"的作用,所以dal层会使用接口来隔离业务层,难啊,dal层和业务层的代码不好写,特别是业务层中能灵活的使用事务并兼顾各种数据库更不好写
  回复  引用  查看    
#10楼 [楼主]2008-05-05 19:22 | veter      
这倒是个不错的方法,看来兄弟“设计模式”研究得有深度呀!
  回复  引用  查看    
#11楼 2008-05-05 20:23 | 私家侦探      
java的c/s的事件编程就经常用到适配器类,要想部分实现接口的方法,就是在两个类中间加一个适配器类,

我们两个是半斤八两啊呵呵
  回复  引用    
#12楼 2008-08-01 10:42 | VinnyZhao [未注册用户]
我有个疑问,想请教搂主!
原来IDAL中有许多专用接口(IOrder,ICategory等),每个专用接口的方法签名都不尽相同。
现在统一成一个泛型接口,也就是说DAL层的实现类都要实现同一个接口。
那这个泛型接口IDALConll<T>就要包括原来所有的专用接口中的所有方法,否则的话,不能满足业务层的调用!

可这样的话,在业务层中调用IOrder的方法时,ICategory的方法也会出现!
会让调用者摸不着头脑!

而且面向对象的单一接口原则也说 多个专用接口优于统一接口!

请楼主解答!我是个菜鸟,初学泛型,请不要拍砖!谢谢!!!
  回复  引用  查看    
#13楼 [楼主]2008-08-01 19:20 | veter      
@VinnyZhao
可能这里有点误会,不好意思!这个泛型接口的意思很明显,就是要定义一组通用的方法,比如每个接口实现在所必须的方法(增,删,改,查),对于类特性,可以定义不同的接口去实现。
我个人认为泛型接口主要应用在小型系统比较好,帮助快速开发。
  回复  引用    
#14楼 2008-08-11 11:45 | VinnyZhao [未注册用户]
我有一个想法,不知道行不行,请搂主看看

把IDALConll<K>作为基接口,如果业务层需要特殊方法,从基接口中派生出专用接口,修改工厂类如下:

public class Factory<T> where T : IDALConll<K>
{

public Factory()
{
}
/// <summary>
/// 根据配置文件生成一个传入的对象,并将其转为T泛型接口
/// </summary>
/// <returns>T</returns>
public static T GetIDAL(String path, String Obj)
{
return (T)Assembly.Load(path).CreateInstance(Obj);
}
}

这样工厂类同样可以生成很多不同的类型,同时避免代码臃肿。
这只是我一个临时想法,不知道行不行的通,请各位指教!
  回复  引用  查看    
#15楼 [楼主]2008-08-11 19:40 | veter      
这有违你所说的OO原则吧?和抽象类重写差不多,慎用!
  回复  引用    
#16楼 2008-08-12 10:35 | VinnyZhao [未注册用户]
这有违你所说的OO原则吧?@veter
我不太明白。
我之所以定义基接口是因为:
1、将专用接口中相同的方法提取出来,省得重复定义
2、对工厂类中的类型参数T进行限制(T必须继承基接口IDALConll<K>)public class Factory<T> where T : IDALConll<K>

然后定义专用接口

interface ICategory : IDALConll<CategoryInfo>
{......}

定义类实现专用接口

public class Category : ICategory {......}

因为Icategory继承于IDALConll<K>,所以Category也要实现IDALConll<K>中的方法。

在BLL中调用工厂类时,使用专用接口

ICategory dal = Factory<ICategory>.GetIDAL(path,Obj)

这样在业务层调用时不会出现不相关的方法,工厂类也能不用修改就能生成各种类型(必须继承于IDALConll<K>)。

我对设计模式和泛型都是初学,哪地方不对,请楼主说的详细一些!
非常感谢搂主,你对泛型的运用对我有很大启发!谢谢!


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-04-03 18:10 编辑过


相关链接: