浅谈设计模式在建安系统中的应用

东湖项目接近尾声,一直想写一下对于该系统设计的感悟,今天就在这里写一写吧。

         首先,评价一个系统的好坏,在我的心里有三个标准:第一是可扩展性,我把它放在第一位,因为没有哪个项目是不需要不断修改的,这是事物客观发展的必然结果,因为从哲学上讲,事物的变化是一直发生着的,所以系统的不断扩展是真理客观决定的结果。第二是稳定性,当然如果你从用户的角度出发,这显然才是最重要的,不过谁让我们是程序员呢,而且我也不是测试人员,编码人员对于某种功能或者模块的疏漏是在所难免的,当然稳定性的提高很大程度上需要测试人员的努力。第三便是性能,虽然它受硬件的很大影响,但是性能的优化途径不仅仅局限于硬件的升级,通过分布式高并发等的设计,或者通过服务器减压,如反爬虫,增加过滤器等优化手段,也可以使得系统性能得到很大提升,这直接影响到用户体验。当然这和本次项目的联系不大,而且作为一名架构与编码的菜鸟,即“软件伪工程师“,上述方面我也并没有很多实际经验。不过想得到才能做得到嘛。

         东湖项目采用的是网络上比较流行的通用权限管理系统Framework,是基于此框架的二次开发。其实涉及到的技术难点也不多,只不过由于其数据层结构略复杂,业务层功能略多,而且用户的特殊性,使得项目周期‘略’长。Framework框架也是将系统分为数据层,逻辑层和表现层,结构很清晰,其中对于各种对象,模块的封装也很到位,有很多值得我学习的地方。首先我们看一下数据层的结构,它的类图大致如下图:


这种设计充分地考虑了可扩展性。之前也用过O/RMapping的工具和框架,像Hibernate等。之前只是去用,去写xml,也没考虑过自己去写一个类似这样的框架。其实我现在觉得那些流行的框架的实现原理也就这么回事,无非是增加了一个xml解析的过程。上面的这个结构就是原理所在。可以发现,这种设计满足了多种数据库的要求,可以自由扩展。那么,在上述的设计中,用了什么设计模式呢?从系统中找设计模式是一个很有意思的过程,就仿佛是在一堆沙子中找金子,在一堆水泥中找钢筋。我的第一印象是简单工厂,但是里面又没有工厂类,那么是什么呢?工厂?还是抽象工厂?首先简单工厂模式中没有抽象类,只有一个含有公用方法的基类,它是根据客户端传入的参数case来判断应该生产哪种Product。就好比苹果公司的工厂(当然是富士康),首先他们有一个iphone的基本设计图纸,这就好比是基类,当你传入iphone4s 时,就会生产iphone4s,传入iphone5时就会生产iphone5 。而工厂模式则是将每种ConcreteProduct对应于一个工厂,就好比现在iphone4s 只由iphone4s工厂来生产,iphone5 只由iphone5工厂来生产。这样的好处是当iphone8开发出来的时候,我们不需要再去像简单工厂一样去修改系统内部的case结构,而只是在客户端更改工厂的类型,满足开放-封闭原则。而抽象工厂如其所言,就是工厂不是专注于一种产品,而是专注于多种相互之间存在联系的产品,就好比iphone4s工厂不仅生产iphone4s,而且还生产iphone4s的充电器,iphone5工厂不仅生产iphone5,而且还生产iphone5的充电器。上述设计其实是用了简单工厂模式,但是为什么没有工厂类呢?其实产品类基类本身就是工厂类(这里虽然它是一个抽象类,但是它并不是工厂模式,它抽象的原因是为了实现不同数据库的访问),在DataProvider的构造函数中,根据Web.config配置文件来决定构造哪一种DataProvider。这个基类最主要的作用是根据从数据库取得的域来将其构造成对象并且放回,.net框架的函数代理很好的配合这一设计并且将其实现,函数代理在C++中就是函数指针,在java中可以通过反射机制或者Interface来实现,其实DataProvider中也可以不使用函数指针,也可以直接通过调用来实现,但是通过使用函数指针形式要更为优雅一些。上述设计中还包含一种设计模式,大家仔细观察,里面有instance属性,而且是private static类型的,对没错,那就是单例模式。因为该系统只能设置一个数据库(非分布式),所以它按照这种设计模式保证该DataProvider只能有一个,所以综合来说,该种设计是单例模式和简单工厂模式的融合,其中工厂类是产品类基类自身。

         第二个我要说的,是他们封装条件查询的方式。如果每次查询都重写一下条件查询前面的sql语句,那就显得臃肿很多,而且在这种条件查询几乎随处随时可见的系统。那么解决办法就是单独将条件查询封装起来,然后通过参数传递给非条件查询逻辑模块来进一步查询。该系统采用的方式是将SQL 条件查询封装成QueryParam这个对象,该对象中包含了条件查询的各种属性,包括where,order by,如果采用分页显示,它还包括pageindex,配合Pager一起使用。在使用的时候,我们首先构造这样的一个对象,然后将其传递给DataProvider中构造sql并且进行查询的模块,该模块根据该对象中各个域的值来构造sql,最后查询出结果并且构造出对象且返回。这里面也有一些问题,比如当你分页显示时,两次倒置可能就使得倒排产生混乱,如这个框架就没有很好的解决这一点。

         第三个我要说的,就是权限管理。权限管理说白了其实就是是否让某个功能的User Interface,如按钮,超链接等等,显示给当前拥有某种权限的用户。当然权限是由超级管理员来设定的,需要用户自己配置,所以权限要基于角色,我们根据角色来设定是否将该Interface暴露给用户,权限的设定无非就是将用户对应于特定的角色。当然这种设计是很灵活的,只要你数据库表的某些字段能体现这些关系,都可以,只是优雅不优雅的问题了。

         先说这么多了,当然这个过程中涉及到的技术细节有很多,那些都只能算作经历罢了,真正有营养的还是上面讲的那些东西,这是skeleton,这才是经验。架构和设计是一门很深奥的学问,也是一门很文艺范儿的学问,既要像学习数学一样灵活,也要像画画一样优雅,这其中的知识,还需要我在今后的日子中不断揣摩。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值