凭什么要用面向对象编程(补充) - 伍迷家园- 博客园

前言:本来上篇已经是完整篇,可在上篇第22楼中,我发现了上篇文章中的最终解决方案还是存在着本质的缺陷。再看到第24楼,仔细想来,的确应该是像richardzeng的写法一样有更深一步的考虑,感谢两位的回复。我将补充方案的讲解加了进来,希望可以给大家以帮助。

 

接上篇


★2007-10-02  08:00 小菜在家中准备
小菜开始准备给人家讲座的内容,一开始都很顺利。可是当要把不同的验证方式给细化时,发现了问题。

 
24 原有的接口实现关系图

如果要再把是用户名密码验证,还是指纹验证的代码加进来,应该如何写具体的实现类呢?

 
25 SqlServer实现类改造
此时你会发现,如果要实现这个功能,你必须在你的每个实现类中写出上面的判断语句,如果某{yt}要增加一种数据访问(比如MySql)你就得再写一遍类似的代码,如果某天增加一个用户验证的方式(比如人脸识别验证),你就得改动所有的实现类的分支判断。这显然是让人难以接受的。

小菜决定换一种思路
 

26 多个类的多重继承

也就是把分支判断的语句,通过继承的方式给分解掉,这样每一种实现都体现成为一个类。只要有新的数据访问或者用户验证方式,不外乎就是增加类就可以了。应该是解决了问题。

可是,看着这张图,小菜感觉不到设计的美。如果,我们增加一种数据访问(如MySql),我们需要增加至少四个类。如果我们增加一种验证方式(如人脸识别验证),那就需要每个数据访问下都继承一个类。目前是3*3共9个类,当扩展需求来了以后,类的增加会成为一个梦魇。

难道没有办法了吗?

 

1)当想不出解决办法时,分析自己的代码有什么容易被改变的地方,可能找到解决思路


 

回到那个接口

 
 
其实当我们要增加一种验证方式时,这个Users类也是要修改的。而且对于Users类来说,验证时通常只会用到当中的一两个属性,而现实中,Users类的属性如性别、生日、姓名等等都对验证来说没有意义。此时发现,验证和用户类本身还是有区别的,验证属性其实只是用户类一小部分属性而已。对于数据库来说,我们把用户名、密码、门禁卡编号、指纹数据存到Users表里的字段中是没有问题,可在面向对象编程时,将它们混在一起的确不利于应对变化。

2)当想不出解决办法时,再次仔细分析需求,并找出需求的本质是个很好的办法

登录是为了验证用户,验证有很多种表现形式。网络上的验证通常就是用户名和密码,但随着科技的进步,指纹试别、面部试别等技术都可以成为验证用户的手段。而这一切,其本质上,验证就是抽象概念,其它都是它的实现方式。那么验证应该就是接口,那几个表现方式是它的实现类。OK,思路有了。

思路:提炼出验证接口,将不同的验证实现这个接口,将用户管理接口的登录方法聚合这个接口。

 
27 相对较好实现办法的类图

将验证分离成一个接口,不同的验证方式不过是验证的一种表现形式。

 


 
 
 

 
32 更改了原用的参数,改用验证接口

 
33 Sqlserver实现类的代码(其它实现类类似)


 
34 用户名密码登录用的界面事件代码


 
35 指纹登录的界面代码

此时,小菜算是松了口气,不管是增加新的数据访问或是增加新的验证方式,都只不过是增加一个类就可以了,这就把“开放封闭原则”和“依赖倒转原则”再次得到了充分的体现。实际上,在不知不觉中,小菜已经使用了“简单工厂模式”、“门面(外观)模式”、“桥接模式”。在这个完整的例子中,并不是为了模式而模式,而是在需求的变更中,为了应对需求的变化而不断演变出来。相信以后需求再有变化,也可以从容面对。

{zh1},小菜在新建文档的标题处打上“凭什么要用面向对象编程”,开始培训材料的写作。

附:有朋友质疑一个登录功能写这么多的代码的必要性。我想说的是,这是一个讲解面向对象编程的例子,为了理解的需要,杜撰了一些需求的变更。通过这样的讲解,是希望你可以在你的编程工作中,学会如何去设计和考虑问题,更好的应用面向对象技术来创建可维护、可扩展、可复用,并灵活性好的程序。

 

 


 

posted on 2010-05-27 13:15 阅读(2325)   所属分类: , ,

评论

不敢当,只是随便说说。

我一直不敢尝试面向对象的设计,因为自己掌握不好。没有那个水平。

我是看了你的《大话设计模式》之后才进入了面向对象的大门。很感谢。

这是 设计和实现的差距实在是太大了。

往往一个好的设计,在没遇到特殊情况的时候是很美的,但是一遇到特殊情况,就变得很丑陋,如果能想到更好的解决方法,那道还好。

可是如果想不出来好的解决方法的话,那也就只能丑陋下去了。

还是我自己的能力和经验不够呀。

到现在也不明白,用接口和不用接口到底有什么区别,说起来好听,不用区分什么什么,实现类一样要去完成。要加入一点需求,一样要改动N多地方。冻并且随之带来的是,N多的代码。。。。

我再来添点乱。

刚刚看到了“石头儿”写的《本地用户和组 知多少? 》,突然想到了还有一种登录验证方式——域登录。

在局域网里,设置一个服务器,客户端可以登录域,登录后就会有一个“标识”,域登录就是利用这个“标识”来识别用户是否登录,是哪个用户登录了。

以前的一个项目,客户就提出来了域登录。既然都已经登录域了,那么是不是就可以不用在输入一遍用户名、密码了呢?

域登录是不用访问数据库的,由与服务器负责验证。

SQLSERVER\MYSQL\ACCESS\ORACLE都是支持SQL的数据库系统,所以可以把脆弱的sql语句段作为返回值传来传去,在理论上可以随便用来当例子,但是实际上的项目基本不会让SQL散落的到处都是。

咱们假设:保密室需要非常严格的认证措施,需要访客的指纹(10个指头的任何一个)加虹膜(任何一个),这个代码结构都要大改。

再比如:接的是富士康的订单,人家厂区40w员工需要身份验证,为了更快的验证速度,人家用NOSQL的memcached内存数据库(假设)...
这回没有时间看啊
作为例子确实很能说明问题了,顶一个。

当然实际应用中,可能很简单。有些同学不要觉得“怎么可能一开始想到那么多...”,确实想不到的。一开始的时候,最基本的,User的逻辑层里(我们时髦一把,假设叫做UserService)有个方法,接受User参数,类似于这样:public bool Login(User user)。后来,发现认证方式不只一种(不是换数据库,是认证方式不一样),会自然地建立一个IAuthenticator接口,作为IUserService的一个属性。在IAuthenticator里定义Login方法,然后重构,并分别去实现。依赖注入容器里配置具体实现绑定。这个,实际上和LZ{zh1}bridge模式的应用是一个道理。
至于数据库,是IAuthenticator实现里的事情。现实情况中基本上都是ORM容器里配置的事,至于说不用数据库的,那也是分布在不同的实现里而已,如果确实有需要,再做bridge。例如说要用memcache缓存的,也就是在IAuthenticator里加一个ICache的属性,同样的套路去做而已。
Laurence liu:
SQLSERVER\MYSQL\ACCESS\ORACLE都是支持SQL的数据库系统,所以可以把脆弱的sql语句段作为返回值传来传去,在理论上可以随便用来当例子,但是实际上的项目基本不会让SQL散落的到处都是。

咱们假设:保密室需要非常严格的认证措施,需要访客的指纹(10个指头的任何一个)加虹膜(任何一个),这个代码结构都要大改。

再比如:接的是富士康的订单,人家厂区40w员工需要身份验证,为了更快的验证速度,人家用NOSQL的memcached内存数据库(假设)...


感谢您的回复。您可能理解错了我想表达的意思,我这个例子并不是为了提供给大家登录功能的xx解决方案。只是为讲解面向对象设计原则的一个例子。

至于在真实环境中如何去操作,那的确是需要根据实际情况来处理。

通常实际情况,登录功能的改变不太常见,但对登录的安全和性能的考虑会更多一些,这些也许您就是专家,如果有博文与大家分享,那将是更好。
追萝驴:
作为例子确实很能说明问题了,顶一个。

当然实际应用中,可能很简单。有些同学不要觉得“怎么可能一开始想到那么多...”,确实想不到的。一开始的时候,最基本的,User的逻辑层里(我们时髦一把,假设叫做UserService)有个方法,接受User参数,类似于这样:public bool Login(User user)。后来,发现认证方式不只一种(不是换数据库,是认证方式不一样),会自然地建立一个IAuthenticator接口,作为IUserService的一个属性。在IAuthenticator里定义Login方法,然后重构,并分别去实现。依赖注入容器里配置具体实现绑定。这个,实际上和LZ{zh1}bridge模式的应用是一个道理。
至于数据库,是IAuthenticator实现里的事情。现实情况中基本上都是ORM容器里配置的事,至于说不用数据库的,那也是分布在不同的实现里而已,如果确实有需要,再做bridge。例如说要用memcache缓存的,也就是在IAuthenticator里加一个ICache的属性,同样的套路去做而已。


显然您是高手,您讲的很到位,赞一个。
金色海洋(jyk)
你的问题在于基于域的认证方式不需要外部数据库,而作者的案例没有抽象出业务逻辑层。如果把这个登录验证应用三层架构模式表示层,业务逻辑层,数据访问层。用户验证逻辑放在业务逻辑层里面(包括你的基于域的验证或者单点登录验证),那么数据访问层的代码便可以更加关注自己的数据访问逻辑。

不过其实我也是看到作者的这些文章和以前自己的问题把三层的架构的好处更加深有体会。
楼主的讲的大意是:主要让我们了解接口的好处,{zd0}化减少程序的耦合度,以接口来约束底层的具体实现(service(服务层)),增强软件的扩展。
并了解一个原则,对修改关闭,对扩展开放,接口就是一套规范,开发的时候我们面向切面编程,另外想想为什么java的J2EE那么火爆,大公司为何做软件时为用SSH框架来做,实际上里面也是面向接口,依赖注入而已!

所以说接口很重要!
另外有人说开发周期长了,但是殊不知一个良好的软件,是适应任何变化的!

感谢楼主,看了大话设计模式对我帮助很大,学得不是很好,敬请指点指点!呵呵!
祈愿:
楼主的讲的大意是:主要让我们了解接口的好处,{zd0}化减少程序的耦合度,以接口来约束底层的具体实现(service(服务层)),增强软件的扩展。
并了解一个原则,对修改关闭,对扩展开放,接口就是一套规范,开发的时候我们面向切面编程,另外想想为什么java的J2EE那么火爆,大公司为何做软件时为用SSH框架来做,实际上里面也是面向接口,依赖注入而已!

所以说接口很重要!
另外有人说开发周期长了,但是殊不知一个良好的软件,是适应任何变化的!

感谢楼主,看了大话设计模式对我帮助很大,学得不是很好,敬请指点指点!呵呵!

双刃剑,用不好适得其反.
就好像很多人盲目的抄袭petshop的3层,结果呢?
1博客园1:
引用祈愿:
楼主的讲的大意是:主要让我们了解接口的好处,{zd0}化减少程序的耦合度,以接口来约束底层的具体实现(service(服务层)),增强软件的扩展。
并了解一个原则,对修改关闭,对扩展开放,接口就是一套规范,开发的时候我们面向切面编程,另外想想为什么java的J2EE那么火爆,大公司为何做软件时为用SSH框架来做,实际上里面也是面向接口,依赖注入而已!

所以说接口很重要!
另外有人说开发周期长了,但是殊不知一个良好的软件,是适应任何变化的!

感谢楼主,看了大话设计模式对我帮助很大,学得不是很好,敬请指点指点!呵呵!

双刃剑,用不好适得其反.
就好像很多人盲目的抄袭petshop的3层,结果呢?

啊?PetShop的三层不好麽?实现了代码隔离,让每个层次,专注它们所专注的事情,专业的事情还是让专业的人来干!难道这不好麽?不管盲目抄袭也好,都是一种进步啊!可能没理解好你的意思!

昵称:

主页:

邮箱:(仅博主可见)

评论内容:

    

[使用Ctrl+Enter键快速提交评论]

郑重声明:资讯 【凭什么要用面向对象编程(补充) - 伍迷家园- 博客园】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——