[扫盲]利用架构实例解析面向对象的封装,多态,继承,接口,泛型

刚刚看到园子里有人问这个问题,心血来潮,整理一番,希望对初学oop的有所帮助,同时有理解不对的欢迎指正。

1. 架构实例基础准备

假设我们做一个简单的小系统,需要的操作为:

1.管理用户,对用户进行增、删、改(User表)

2.管理角色,对角色进行增、删、改(Role表)

3.管理功能,对系统功能进行增、删、改(Fun表)

由此可以分析,我们这个小系统需要的表为,User用户表,Role角色表,Fun权限表,还要派生出一张表 角色-权限(RoleFun) 关联表。其中用户表里面有字段存放角色Role的ID。

2. 搭建项目基础框架

一般情况下,我们都采用的是3层架构模式,即使是复杂模式也是在此基础上延伸的。

上面这幅图是最最基础的一个框架。总共分为5个层次,Model层,DAL层,BLL层,Tools层,UI层

3. 代码实现基础架构

对于一般的编程者来说,实现起来并不复杂,可能不会将那么多的思想应用到实例中来,那么这里我们模拟下,先抛开这些思想。

(1)首先每个数据库表对应一个Model类这个是必须的吧,那么我们在Model层新建4个类,User,Role,RoleFun,Fun

(2)这个四个对象都需要数据库增、删、改操作,那么我们在DAL里面对应的创建4个类,UserDAL,RoleDAL,RoleFunDAL,FunDAL,然后每个类里面写入相同的方法,增、删、改。

       Insert(对象),Delete(对象),Update(对象)

       这里你可能已经意识到问题了,hold,继续看。

(3)同样在BLL层要实现对DAL的调用,需要建立同样的四个业务操作类,UserMgr,RoleMgr,RoleFunMgr,FunMgr,每个类里面实现同样的调用方法。

(4)Tools暂不考虑,主要存放经常用的类

(5)UI层,表现层,可以是Web或者Winform等形式

搭建好的代码框架如下:

4. 开始OOP的分析应用--封装

面向对象的第一个特性是:封装,其实我们已经实现了,分层就是封装的最好体现,各层相互调用,“低耦合,高内聚”

这里不在解释封装了。

5. OOP--继承

通过上面的代码编写你肯定遇见了灾难了,当随着我们业务功能的不断增加,我们的DAL和BLL类越来越多,越来越难管理了。

更悲催的是,如果每个实体类我想实现一个查询(Search)操作,那么需要在众多的类里面实现这个Search代码,试想那是多么的可怕,你的价值全部浪费在了基础代码的编写上。

如何解决这个问题呢?

那就是采用继承的思想实现,父子类来实现,一个公共的父类(BASE),所有子类继承这个子类,那么子类也就具有了父类的public方法,如果需要增加公共的方法,只需要在父类中添加方法即可实现,所有子类自动会继承。

模式如上图所示,这样实现一个Search()方法,我们只需要变动BaseDAL类即可,而其他实体类都不需要动了。试想对若干实体类的系统,这意思想是多么的重要,可以节省大量的时间。

还没有结束,细心的你可能发现,我们的Insert,Update,Delete都需要自己的Model呀,那BaseDAL应该如何实现呢?怎么知道具体的方法去调用具体的Model呢?

哈哈,这里C#提出了引以为豪的“泛型”思想。通过泛型,可以轻松的解决这个问题。

6. 泛型

对于BaseDAL我们可以设计成为泛型的类,在使用该类的时候需要将该类具体的实例化,看代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DAL
{
    public class BaseDAL<T> where T:new ()
    {
        public bool Insert(T t)
        {
            //TODO 解析T,通过反向工程构造SQL
            return true;
        }

        public bool Update(T t)
        {
            //TODO 解析T,通过反向工程构造SQL
            return true;
        }

        public bool Delete(T t)
        {
            //TODO 解析T,通过反向工程构造SQL
            return true;
        }
    }
}

 这样,我们其他的类可以直接继承父类了。但为了整体架构的可塑行,我们DAL层将不做对BaseDAL的继承操作,原因很简单,因为我们可能会切换DAL的技术,例如由ADO.Net切换成HNibernate等,同时DAL作为数据操作层尽量要保持简约。

我们这里在业务逻辑层BLL来实现继承,同样也需要一个BaseBLL的基类。

 

using DAL;
using System.Collections;
using System.Collections.Generic;

namespace BLL
{
    public class BaseMgr<T> where T : new()
    {
        //可以重写
        public virtual bool Insert(T t)
        {
            return new BaseDAL<T>().Insert(t);
        }

        public bool Update(T t)
        {
            return new BaseDAL<T>().Update(t);
        }

        public bool Delete(T t)
        {
            return new BaseDAL<T>().Delete(t);
        }
        //重载
        public bool Delete(List<T> list)
        {
            return true;
        }
    }
}

 

然后具体的实体类继承这个BaseMgr

using Model;

namespace BLL
{
    public class UserMgr : BaseMgr<User> //继承
    {
        //继承基类最大的好处是,可以写本类自己的特有方法
        //例如User,我想获取所有的用户,而其他的业务逻辑不需要实现这个方法,
        //那么我们可以单独写在这个类里面
        //当然你也可以写在BaseMgr里面,哪样所有的子类都具有这个方法了

        //可以对基类进行重写(多态)
        public override bool Insert(User t)
        {
            return true;
        }

        //继承基类前的代码
        //public bool Insert(User t)
        //{
        //    return new UserDAL().Insert(t);
        //}

        //public bool Delete(User t)
        //{
        //    return new UserDAL().Delete(t);
        //}

        //public bool Update(User t)
        //{
        //    return new UserDAL().Update(t);
        //}


    }
}

 

通过泛型实现继承我们获得的最大好处:

1,数据库每增加一个实体,代码的Model层只需要增加一个对应的实体类,那么该类的基础操作随即产生了(即,BaseDAL类的所有方法)

2,通过在业务层对基类的继承,可以实现特有方法,当然并不是所有的实体类都需要继承,具体看自己的需求

7. OOP-多态

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

实现多态,有二种方式,覆盖,重载。

覆盖:override,上面代码UserMgr类中的Insert方法就是用的覆盖方法,可以重写父类的某些方法来达到自己的业务要求。一定要注意将允许重写的方法事先声明为virtual

重载:通俗点就是一个方法名,不同的参数类型,例如我想实现一个批量删除功能,方法的名字同样想起名为Delete,那么只需要改变参数即可

         public bool Delete(List<T> listT);

 

8. 接口

顾名思义,接口,即插即用,例如插座,只要有对应插头,插入即可使用了。

接口:在编程里面起到的是一种规范,既然是规范,必定是约束若干人的,也就是团队开发项目,大家共同遵循一个规范,协调开发代码,而且互不干扰。

接口更多的是被软件架构师使用,设计好整体的软件架构,直接交给程序员开发即可,程序员只需要按照这种规范做就可以了,对每个接口进行具体的实现。

注意哦:接口不实现,是可以通过编译的哦

 

9. 引申架构

通过采用上面的思想,基本上我们可以实现一套牢固的架构了,而且可以复用到任何的系统中。

但技术是在不断革新的,而且需求也是不断变化的,更可怕的是能够运行系统的设备越来越多了,从PC到普通手机,再到智能手机(Android,IOS,WP7),再到平板电脑等等。

还有语言的差异,Java,php等等

这就要求一套架构不但要牢固,更能够适用于各种平台的开发。

为此我们的架构可以引申成一个服务,将上面的架构在加上一个服务层(可以用WCF,可以用MVC4的WebAPI,Restful规范),那么整体的架构就是下面这个样子了。

 

10. 总结

软件开发其实就是一种思想,将人的一种思想通过代码形式反映出来。好好用心思考,你就明白为什么会这么做,仔细体会其中的妙处。

posted @ 2012-05-13 00:53  jackchain  阅读(2929)  评论(21编辑  收藏  举报