锁定老帖子 主题:面向行为编程!继面向对象的新的软件开发模式
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-01-31
最后修改:2011-02-21
首先这不是一样新技术,而是一种新思想,是基于面向对象思想的一种更符合人的思维习惯的编程模式。如果说面向对象是对现实世界的抽象,那么面向行为就是对人如何与现实世界的交互而做的更易于理解,更动态的封装。该思想的核心是:以“行为”为程序模块的基本单位,在模块开发之前,只需确定该模块 “用来干什么”,而模块的实现,所需参数,返回结果一律不需要关心。从而极大降低模块之间的耦合。
传统的软件开发通常以函数为模块的基本单位,其弊端是很明显的。而面向对象的概念中则提供了对象和接口,它的特色是将有关现实世界的一切“名词”封装成一个代码块(类),从而使模块的内聚性有了很大的提高。但在封装一些功能,或者行为等抽象概念时则表现较差,因为在封装成类之前,仍必须先定义(声明)好类的属性、方法的参数、返回值,而这些在程序没有执行之前可能都是未知,无法确定的,我们必须根据经验去定义,说白了点就是猜测。简单来说:一个基本的功能(方法)模块,主要由四个部分组成:方法名、参数、实现、返回值,如图:
通过面向对象的思想,可以通过接口或抽象方法,只定义方法名,参数和返回值,而不去理会实现:
但这在具体的项目运用中还是不够的,因为有时候一个模块的参数和返回结果根本是不能事先确定定义的!于是笔者很自然地想到当需要一个功能的时候,只需要知道确定这个功能用来干什么(行为),把参数和返回值也统统忽略呢?
比如说我们需要实现一个网站的登录功能,首先我们想到的是定义方法: bool Login(String account, String password); 根据经验,要登录,我们需要:account(账号)和password(密码),返回结果是成功或者失败(true or false)。但事实可能并不这么简单,因为假如在登录成功后,我们可能还需要向服务器的session变量里保存该用户的信息(对象),我们还需要一个参数:服务器Session, 和一个结果:对象User. 假如登录失败,我们可能还需要知道失败的原因(错误码),因为登录失败的原因有许多种:比如密码错误,账号不存在,数据库异常等等,这时网站管理员可能就需要返回一个错误码。
而面向行为的编程则能很好的解决这一点,假设我们要实现一个网站的登录功能,我们只需声明一下这个行为:Behavior Login;就这么简单。要实现该功能,只需重写该行为下的doing()方法。而该功能所需要的参数,返回结果集在实现里用:this.getParameter(String paraName), this.resultSet.set(String resultName, Object value)方法获取。
于是我用Java类对“行为”进行了一个封装,用来模拟“行为”的用法。并定义了一个服务器行为ServerBehavior, 实现了一个简单的面向行为的J2EE框架。实际上这不是个框架,我只是将服务器(Servlet)的“行为”进行了一个定义,定义是(笔者对服务器行为的理解):接收页面表单参数,调用相关业务行为,页面跳转(或者传出ajax数据)。
再拿网站登录来说吧,首先,我们只需确定一个行为:"登录(Login)",然后将其定义,继承一个行为类:
public class Login extends Behavior { protected void doing() throws ParameterNotFoundException, ResultNotFoundException, BehaviorNotFoundException { } }
然后我们就可以不管参数,结果如何直接实现该行为: 首先得到账户名和密码:
protected void doing() throws ParameterNotFoundException, ResultNotFoundException, BehaviorNotFoundException { //登录名 String name = (String) this.getParameter("name"); //密码 String password = (String) this.getParameter("password"); } 然后我们声明并调用下一个“行为”:账户验证,这个行为将登录名和密码提交到数据库中进行验证,如果登录成功,返回User实体。但我们根本不必关心这个行为是如何实现的,在项目开发中,它可能完全由另一个人负责。所以,我只需直接声明该行为:
protected void doing() throws ParameterNotFoundException, ResultNotFoundException, BehaviorNotFoundException { //登录名 String name = (String) this.getParameter("name"); //密码 String password = (String) this.getParameter("password"); Behavior checking = Behavior.getInstance("checking"); } 然后将它可能需要的参数name 和 password进行注入,执行,得到一个结果集:
Behavior checking = Behavior.getInstance("checking"); checking.setParameter("name", name); checking.setParameter("password", password); ResultSet resultSet = checking.execute(); 最后,从结果集里取我们想要的,是否成功:
boolean success = (Boolean) resultSet.get("success"); 如果成功,再从结果集中取出User实体,并跳转到登录成功的界面,如果失败,则提示登录失败:
if (success) { HttpSession session = (HttpSession) this.getParameter("session"); session.setAttribute("user", resultSet.get("user")); this.resultSet.set("redirect", "/boApp/success.jsp"); } else { this.resultSet.set("redirect", "/boApp/failed.jsp"); } 一个登录行为就这样实现好了!具体的内部与数据库交互的实现由行为Checking来完成,当然它也可能调用别的行为,这就要看项目之前的设计文档了。
最后页面表单:(表单action提交的url正是我们刚刚定义的Login行为。为了区别与一般的servlet,我在行为url后加了后缀".bh")
<form action="/boApp/login.bh" method="post"> <p>账号:<input type="text" name="name"/></p> <p>密码:<input type="password" name="password"/></p> <p><button type="submit">登陆</button></p> </form>
由于我们运用了“行为”作为模块的基本单位,而模块所需的参数,返回结果都不需要事先声明定义,所以在模块独立性,可扩展性上都有了一个质的飞跃。但有利必有弊,模块灵活性独立性的提高,必将带来运行效率的降低。
最后附上源码,其实代码的实现非常简单,核心只有两个类,主要表达的是面向行为的思想。里面还有我用面向行为框架做的一个小demo,一个简单的网页聊天系统。本来这个系统我用传统的jsp+servlet实现的非常复杂,模块代码也比较混乱,但使用“行为”包装后,系统的各个模块功能,步骤都显得非常清晰,只用了几个“行为”的“组装”就统统搞定了。
欢迎各位大虾与我探讨! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-01-31
跟Action层有什么不一样吗?
|
|
返回顶楼 | |
发表时间:2011-01-31
我感觉这是概念性的错误!
请回答一个最为简单的问题:行为是谁的行为? 面向对象的核心有几个,比如对象、属性、行为等。 login应该是User对象域的一个行为,仅此而已 有想法是好事,可能是楼主没讲明白 |
|
返回顶楼 | |
发表时间:2011-01-31
最后修改:2011-01-31
itstarting 写道 我感觉这是概念性的错误!
请回答一个最为简单的问题:行为是谁的行为? 面向对象的核心有几个,比如对象、属性、行为等。 login应该是User对象域的一个行为,仅此而已 有想法是好事,可能是楼主没讲明白 谁的行为并不重要啊,“谁”只是一个行为里可能需要被注入的参数,因为“谁”可能也是一个功能中的不确定因素,比如回帖这个行为:可能是用户回的,也有可能是机器的自动回复。总之行为是比对象更广泛的一个概念 |
|
返回顶楼 | |
发表时间:2011-01-31
lyw985 写道 跟Action层有什么不一样吗?
我定义的ServerBehavior跟struts里的Action的确很像!因为struts的本质也就是强制实现MVC的分层,细化servlet和jsp之间的“行为”,将展示层和代码层的分离开来。页面只负责向servlet提交数据,而servlet负责接收数据并调用其它业务Bean,然后转发(重定向)页面,跟我定义的服务器行为ServerBehavior其实是一回事 |
|
返回顶楼 | |
发表时间:2011-01-31
企业应用架构模式
作者: (美)Martin Fowler Transaction Script 特点:一个Transaction Script把它所要做的事情统统放在一起,自己把它做了(没有什么消息链,除了调用更底层的数据库操作)。比如订一个房间,就包含了检查是否有空房,计算租金,更新数据库这系列操作,全由自己完成,放在一个函数中。 很像过程化编程。 优点: 1. 简单。性能高,理解容易。 2. 一个事务的处理,不会影响到其他事务。 缺点: 很难处理复杂的逻辑。如果你在不同的Transaction Script中发现了很多的重复代码,就表示Transaction Script模式已经力不从心了。 说明: 把一个个Transaction Script分开,至少放到不同的函数中,而且最好与UI和数据库操作分开(不同的类和包中)。而且由于它位于中间层,不应该有调用UI的方法。 Transaction Scripts有两种方法来组织类结构。 1.一个类放几个Transaction Scripts,它们都是逻辑相关的。 2.每个Transaction Script对应一个类,这样可以套用Command模式,但是似乎没有必要。 |
|
返回顶楼 | |
发表时间:2011-01-31
行为里的参数调用跟spring里的依赖注入有点像,只不过spring注入的一般是很大的业务
类,而行为里注入的是细化到基本数据类型的参数! |
|
返回顶楼 | |
发表时间:2011-01-31
我看了一下,觉得LZ的意思是把传入的参数和返回的结果与实际的行为分离开来。
但表面上看好像是分离了,实则还有有关,这个东西分离不了的。 LZ所说的另外的一点好处是具体行为的编写可以由另外一个人来负责, 那不用这个面向行为变成也完全没问题啊,一个人专写action,处理参数和返回页面, 一个人专门写service层。 不知道面向行为编程有什么原则? 不过LZ挺有突破创新意识的,挺好 |
|
返回顶楼 | |
发表时间:2011-01-31
lz很有想法啊,代码研究中
|
|
返回顶楼 | |
发表时间:2011-01-31
写了一堆的command,外面通过名字调用command。
好像把每个方法各分到一个类里了,原来想过通过反射实行类似的东西。但是觉得行为多的时候不好维护吧,会比较泛滥。 |
|
返回顶楼 | |