MachII HowTo系列教程的译文: Bean使用指南

作者:  Ben Edwards

Mach-II框架(版本 1.0.7 以后)引入对bean的支持。本文主要研究什么是bean以及它们的使用方法。

 

在像JavaCFC这样的基于类的面向对象编程中,应用程序被建模程一系列的类。类是数据和方法的封装体。一个bean就是单一的确定的对象,其中含有明确的数据访问规则。由于历史原因,在Java大行其道的时候,所有跟Java有关的东西都取了与咖啡有关的名称,bean这个听上去很奇怪的称呼因运而生。Bean的思想和它的名称一样来自于Java的世界。

 

Bean最佳实践

Bean起初是扮演邮递员的角色,在应用程序的各个层面(MVC或者体系等级)之间传递信息。它们一般包含最精简的事务逻辑(如果需要的话),并且具有简单一致的接口。

 

作为bean的类,应该有获得和设置数据成员值的方法,后者的样式统一为getXyz()setXyz()。下面例子中bean组件含有一个数据成员——texRate

 

<cfcomponent>

<cfset variables.taxRate = 0 />

<cffunction

name="getTaxRate"

access="public"

returntype="numeric"

output="false">

<cfreturn variables.taxRate />

</cffunction>

<cffunction

name="setTaxRate"

access="private"

returntype="void"

output="false">

<cfargument name="taxRate" type="numeric" required="true" />

<cfset variables.taxRate = arguments.taxRate />

</cffunction>

</cfcomponent>

 

 

例子中,获取者(getter)和设置者(setter)的access属性可以由bean开发者设置,可以是public, private, package,或者remote。不管access者是什么,数据对象(如本例的tacRate)必须是私有的,可以通过分配它的变量域来设置。这样可以保证只有获取者(getter)和设置者(setter)可以访问这个数据。除了这个规则,还有其他最优方法来保持高内聚性。包括:

         ×数据类型或变量首字母小写,且采用混合格式。例如:texRateleghth,以及companyName

         ×设置器(setter)接受与数据成员型发单一变量。见上面示例。

         ×接收器(getter)不接受任何值,而是返回数据成员的值;

         ×bean内部可以包含其他的bean作为数据成员。例如:Company bean中可以包含一个Addressbean作为数据成员使用;

         ×所有bean组件都有一个不含变量、返回本身的init()函数。Init函数必要时可以接受变量。Init函数可以使用设置器来设置传递给init()的任何值。

         ×所有对数据成员(甚至包括bean里那些不含访问者(non-accessor)的方法)的访问,必须使用accessor方法来处理。例如:computeTex(),接受名为Productbean后,使用后者自身的getTaxRate()方法来计算处税金:

 

<cffunction

name="computeTax"

access="public"

returntype="numeric"

output="false">

<cfargument name="product" type="Product" required="true" />

<cfreturn arguments.product.getPrice() * getTaxRate() />

</cffunction>

 

 

方法(而不是访问者(accessor)),需要以getset开头。例如,我们可以将computeTax()更名为getTex()。即使这样改名,这个方法也不是一个“getter”,因为它没有遵循必要的格式。

 

考虑以上写bean的好习惯,我们推荐将单一数据成员的设置器和接受器分组成对排列在一起的这种方法。这就意味着,getTexRate()要和setTexRate()排列在一起,而不是把所有的接收器排列在一起、所有设置器排列在一起。

 

为什么写bean要遵循这么严格的规定呢?代码的一致性可以给开发人员省下宝贵时间、提高效率。一致的方法保证了,你和其他人可以同一件重要工作中相互协调。

 

完整的例子:

 

<cfcomponent

displayName="Address"

hint="An address bean.">

<!--- PROPERTIES --->

<cfset variables.street = "" />

<cfset variables.city = "" />

<cfset variables.state = "" />

<cfset variables.postalCode = "" />

<!--- CONSTRUCTOR --->

<cffunction name="init" access="public" returntype="Address"

output="false">

<cfargument name="street" type="string" required="false" default="" />

<cfargument name="city" type="string" required="false" default="" />

<cfargument name="state" type="string" required="false" default="" />

<cfargument name="postalCode" type="string" required="false" default=""/>

 

<cfset setStreet(arguments.street) />

<cfset setCity(arguments.city) />

<cfset setState(arguments.state) />

<cfset setPostalCode(arguments.postalCode) />

<cfreturn this />

</cffunction>

<!--- GETTERS/SETTERS --->

<cffunction name="getStreet" access="public" returntype="string"

output="false">

<cfreturn variables.street />

</cffunction>

<cffunction name="setStreet" access="public" returntype="void"

output="false">

<cfargument name="street" type="string" required="true" />

<cfset variables.street = arguments.street />

</cffunction>

<cffunction name="getCity" access="public" returntype="string"

output="false">

<cfreturn variables.city />

</cffunction>

<cffunction name="setCity" access="public" returntype="void"

output="false">

<cfargument name="city" type="string" required="true" />

<cfset variables.city = arguments.city />

</cffunction>

<cffunction name="getState" access="public" returntype="string"

output="false">

<cfreturn variables.state />

</cffunction>

<cffunction name="setState" access="public" returntype="void"

output="false">

<cfargument name="state" type="string" required="true" />

<cfset variables.state = arguments.state />

</cffunction>

<cffunction name="getPostalCode" access="public" returntype="string"

output="false">

<cfreturn variables.postalCode />

</cffunction>

<cffunction name="setPostalCode" access="public" returntype="void"

output="false">

<cfargument name="postalCode" type="string" required="true" />

<cfset variables.postalCode = arguments.postalCode />

</cffunction>

</cfcomponent>

 

 

Mach-II bean的支持:

 

1.0.7 版本的Mach-II框架在bean创建上为你节省了事件和精力。你可以使用<event-bean>,作为<event-handler>标签的子标签,这个标签有一下属性:

         ·name:被创建的bean的名称;

         ·type:该组件的位置;

         ·field:用来存放bean的数据成员,是可选项。

 

 

我们来看bean组件Address,该方法的参数是streetcitystate以及pestalCode。因为它是标准的bean,我们必须提供完整函数getStreet (), setAddress(),getCity(), setCity(), getState(), setState(), getPostalCode()以及 setPostalCode()

 

进一步,我们假想有网页表单来请求这个信息。当表单被提交给我们的Mach-II程序,我们希望生成一个新的Address bean,并储存进来自表单的信息。生成的bean将被放置在事件变量中。当然,我们可以写listener来创建bean并装配它的数据成员。但是,<event-bean>标签使事情变得更简单,只需要表单变量名与bean里的相匹配就行了:

 

<event-bean

name="address"

type="model.Address"

fields="street,city,state,postalCode" />

 

Mach-II会创建类型为mode.Addressbean,进而调用设置器根据匹配好的事件变量来确定每个数据成员的值。

 

我们来看另外一个beanRegistrant。它有3个参数firstNamelastName以及address。前两个的数据类型设为字符串,而address则指向Address bean

 

<event-handler event=”register”>

<event-bean

name="address"

type="model.Address"

fields="street,city,state,postalCode" />

<event-bean

name="registrant"

type="model.Registrant"

fields="firstName,lastName,address" />

...

</register>

 

 

变量firstNamelastName会被放进事件变量收集器(collection)里。当address被创建(通过使用<event-bean>方式),它便可以在其创建者registrant里被访问。这个regester事件现在有两个bean——addressregitrant,作为封装单元而不是松散的变量集合,用于事务逻辑。

 

同样的,<event-bean>标签可以用init()函数组装一个bean。如果没有在fields属性中被确定,事件变量将在bean创建时,以变量的形式传递给beaninit()函数。这样就允许我们使用简单的方法调用实现bean的组装,必要时还可以扩展其初始逻辑。

 

Bean时一个简单而又强大的工具,但它们的强大是建立在它们使用的一致性(consistency)上的。本文展示了bean的合理使用方法以及解释了Mach-II如何使bean的创建和使用变得更加简单原理。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值