|
|
3#

楼主 |
发表于 2007-9-19 22:49:35
|
只看该作者

列表 F
<cfcomponent output="false">
<cffunction name="init" access="public" returntype="AbstractContentState" hint="Constructor.">
<cfargument name="stateName" type="string" required="true" />
<cfset setStateName(arguments.stateName) />
<cfreturn this />
</cffunction>
<cffunction name="save" access="public" returntype="void" output="true" hint="">
<cfthrow message="State '#getStateName()#' does not implement the save method." />
</cffunction>
<cffunction name="approve" access="public" returntype="void" output="true" hint="">
<cfthrow message="State '#getStateName()#' does not implement the approve method." />
</cffunction>
<cffunction name="deploy" access="public" returntype="void" output="true" hint="">
<cfthrow message="State '#getStateName()#' does not implement the deploy method." />
</cffunction>
<cffunction name="makeDraft" access="public" returntype="void" output="true" hint="">
<cfthrow message="State '#getStateName()#' does not implement the makeDraft method." />
</cffunction>
<cffunction name="getStateName" access="private" returntype="string" output="false" roles="" hint="I return the stateName.">
<cfreturn variables.instance.stateName />
</cffunction>
<cffunction name="setStateName" access="private" returntype="void" output="false" roles="" hint="I set the stateName.">
<cfargument name="stateName" type="string" required="true" hint="stateName" />
<cfset variables.instance.stateName = arguments.stateName />
</cffunction>
</cfcomponent>
<cfcomponent name="DraftState" extends="AbstractContentState" hint="I am a Singleton state object. I have no instance data, I only manage logic.">
<cffunction name="init" access="public" returntype="DraftState" hint="Constructor.">
<cfset super.init('Draft') />
<cfreturn this />
</cffunction>
<cffunction name="save" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' saving content item...<br/>
</cfoutput>
</cffunction>
<cffunction name="approve" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' saving content item and alerting reviewer about content for review...<br/>
</cfoutput>
<cfset arguments.context.setStateByName('review') />
</cffunction>
</cfcomponent>
<cfcomponent name="ReviewState" extends="AbstractContentState" hint="I am a Singleton state object. I have no instance data, I only manage logic.">
<cffunction name="init" access="public" returntype="ReviewState" hint="Constructor.">
<cfset super.init('Review') />
<cfreturn this />
</cffunction>
<cffunction name="approve" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' alerting content author that content is approved...<br/>
State '#getStateName()#' marking content as ready for publish approval...<br/>
</cfoutput>
<cfset arguments.context.setStateByName('publishApproval') />
</cffunction>
<cffunction name="reject" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' alerting content author that content is rejected...<br/>
State '#getStateName()#' setting back to draft mode...<br/>
</cfoutput>
<cfset arguments.context.setStateByName('draft') />
</cffunction>
</cfcomponent>
<cfcomponent name="ApprovePublishState" extends="AbstractContentState" hint="I am a Singleton state object. I have no instance data, I only manage logic.">
<cffunction name="init" access="public" returntype="ApprovePublishState" hint="Constructor.">
<cfset super.init('ApprovePublish') />
<cfreturn this />
</cffunction>
<cffunction name="approve" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' Marking content as deployed...<br/>
State '#getStateName()#' Pushing live and updating content cache...<br/>
</cfoutput>
<cfset arguments.context.setStateByName('published') />
</cffunction>
<cffunction name="reject" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' alerting reviewer that publishing is rejected...<br/>
State '#getStateName()#' setting back to review mode...<br/>
</cfoutput>
<cfset arguments.context.setStateByName('review') />
</cffunction>
</cfcomponent>
<cfcomponent name="PublishedState" extends="AbstractContentState" hint="I am a Singleton state object. I have no instance data, I only manage logic.">
<cffunction name="init" access="public" returntype="PublishedState" hint="Constructor.">
<cfset super.init('Published') />
<cfreturn this />
</cffunction>
<cffunction name="save" access="public" returntype="void" output="true" hint="">
<cfargument name="context" type="ContentItemContext" required="true" />
<cfset var local = structNew() />
<cfoutput>
State '#getStateName()#' setting the content to draft mode...<br/>
</cfoutput>
<cfset arguments.context.setStateByName('draft') />
</cffunction>
</cfcomponent>
列表G
<h2>Now, using the State pattern:</h2>
<cfset draftState = createObject('component','DraftState').init() />
<cfset reviewState = createObject('component','ReviewState').init() />
<cfset approvePublishState = createObject('component','ApprovePublishState').init() />
<cfset publishedState = createObject('component','PublishedState').init() />
States created...<br/>
<hr/>
<cfset content = createObject('component','ContentItemContext').init(draftState,reviewState,approvePublishState,publishedState,'draft') />
Context created in <strong>draft</strong>...<br/>
<cfset content.save() />
<cfset content.approve() />
<cfset content.approve() />
<cfset content.approve() />
<cfset content.save() />
<cfset content.approve() />
<cfset content.reject() />
<hr/>
<cfset content2 = createObject('component','ContentItemContext').init(draftState,reviewState,approvePublishState,publishedState,'review') />
Context created in <strong>review</strong>...<br/>
<cfset content2.reject() />
<cfset content2.save() />
<cfset content2.approve() />
<cfset content2.approve() />
<cfset content2.reject() />
ContentItemContext所做的是,当调用方法时将每个状态的参数“this”传递给自身。通过这种方式,状态CFC可以执行它的行为,然后指示ContentItemContext进入下个状态。
如果需要添加状态,我们只要创建一个新的状态对象,然后添加部分代码让ContentItemContext知道新添加的状态。所有将来添加的状态的行为被封装起来,尽量避免改变已经存在的代码。
当然,绝大多数情况下,每个状态是一个单独对象,也就是说它们不包含实例数据,且它们只需要创建一次。可能我们需要大量ContentItemContext CFCs(每个内容项对应一个),但是均可用同样一个实例。这就减少了我们需要创建的CFCs数量。虽然并不是总是如此,但也时有发生。
为了展示状态模式,为大家附加一个UML图,如下表A。对于熟悉模式的人,可能会注意到对象之间的关系与策略模式和桥模式类似。虽然它们间的关系类似,但是每种模式的用途不同。
表 A
![]()
状态模式UML图
值得一试
本文向大家展示了如何利用状态模式解决CFC中的方法或条件爆炸问题。虽然模式的应用可能会给系统带来另外的复杂性,但是对它所带来的优点来说这还是值得的。 |
|