使用Java开发Domino业务应用的设计模式 (cont. 2)

本文介绍了一个图书馆系统的软件设计与实现细节,重点讨论了MVC模式的应用、业务对象的创建及利用Factory和Objectifier模式进行操作的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发 Library

“checkout book” 和“delete book”的用例如下:

Checkout book

说明:一个member能借出一项资源。Library记录借出的日期,而且要求member在预定的日期(dueDate)内返回资源。

前提条件:

Member在library中进行注册

Member没有走出归还日期仍没有归还的书

Member所借出的资源不走出5本

Book现有没有被借出

完成结果:

资源被member借出

资源预定归还日期已设定

资源借出日期已记录

Delete book

说明:管理者可以从library中删除book

前提条件:

Book当前没有被借出

完成结果:

Book被永远从library中删除

Delete member

说明:管理员可以从library中删除member

前提条件:

       当前member没有借出任何资源

完成结果:

Member被永远从系统中删除

使用 MVC 实现借书( checkout

MVC应用流程如图1所示,checkout的事务处理从controller开始。图书馆中的每本书者由一个Notes文档来表示,代表书的Notes文档的unid提交至checkInOut代理(controller),由代理对checkout事务进行调用,因为每个代理都有一定数量的初始化和结束代码,所以减少代码数就是减少维护量.由此,仅用一个checkInOut控制器处理checkout和checkin操作。

Action参数决定了执行是checkout还是checkin。多个固定在单个控制器上也是J2EE中的一个普遍应用。

事务由book表单上的action进行调用。Action传送一个HTTP get请求,如:

http://192.168.1.10/library.nsf.checkInOut?OpenAgent&action=out&unid=XXXXXXXXXXXX

checkInOut 代理的代码如下列表1。其执行了如下的任务:

public class Agent_CheckInOut extends AgentBase{

       public void NotesMain{

try{

Session session = getSession();

AgentContext agentContext = session.getAgentContext();

Document docContext = agentContext.getDocumentContext();

Database dbCurrent = agentContext.getCurrentDatabase();

 

//get params

HTTPAgentRequest request = new HTTPAgentTRequest(docContext);

String strUNID = request.getParameter(“unid”);

String strAction = request.getParameter(“action“);

 

//get book document

Document docBook = dbCurrent.getDocumentByUNID(strUNID);

 

//create Book document

Book book = new Book(docBook);

 

//create member business

//object for current user

Member member = Member.createMemberFromCurrentUser();

 

//perform check in or out

//based on action param

if(strAction.eqauals(“out”)) book.checkOut(member);

else if(strAction.equals(“in”)) book.checkIn();

 

//redirect user to book in read mode

String strUrl = book.getReadModeURL();

getAgentOutput().println(”[” + strUrl + “]”);

 

}catch (Exception e){

ExceptionHAndler.handleException(e);

}

}

}

1、              从查询字符串中读取action和unid。HTTPAgentRequest是作为一个Helper class类(模仿HttpServletRequest)以更易获取查询字符串。

2、              通过unid找到相应的Notes文档。这就是将要被checkout的book文档。

3、              根据book文档创建一个book业务对象。

4、    根据生成代表当前web使用者的member对象的静态方法创建一个Member业务对象。CheckOut代理需要启用“作为Web用户运行代理”的设置。

5、    对book对象调用checkOut()方法,作为当前使用者checkout这本书。这就是调用 model层所产生的效果。

6、    checkOut()完成之后,代理使book文档对使用者为只读状态。getReadModeURL() 是在BusinessDocument基类中定义的helper method,返回一个原始Notes文档的只读状态的Document URL。这就是调用View层所产生的效果。

 

book.checkOut()方法执行了如下的任务:

1、  分别为checkout时间和due时间创建lotus.domino.DateTime对象。

2、  写入新的域值checkout。Library中的每一篇文档都拥有一个唯一的关键字,叫做docID,它是对创建文档时所生成的UNID的稍加更改的计算值。为把book和需要借书的member联系起来,book中存储了member文档的DocID。通过这种方式,每一本book都可以找到借出它的member,而且每一个member也可以找到各自借出的book。

3、  保存文档save()虽然实质上就是执行了标准方法doc.save(true,false),但其中也包括在服务器文档中已启用“允许运行当前代理”的条件下某些用来构造线程安全(thread-safe)的逻辑。在业务对象初始化这段时间内,如果文档已经更改,那么save()方法将操作失败(抛出一个异常)。由于save()是由基类(BusinessDocument)来实现的,所以所有业务对象都拥有安全的特性。

checkout()方法如列表2。

使用 Factory Objectifier 模式调用公共方法

Member和book都拥有deleter()方法,这些方法都对BusinessDocument的delete()方法进行了重载。许多应用都拥有如deleter()和webQuerySave()这样的多个业务对象所共有的公共方法。你可使用Factory和objectifier模式使控制器(agent/servlets)可以有效地使用这些函数。

在到程序执行才能知道对象类型(类)的情况下,你可以使用Factory模式来进行对象的创建。你可以使用带有创建对象的静态方法的类来实现这个模式,其他类仅仅是调用这个静态方法来创建对象。

public void checkOut(Member member) throws Exception{

    //compute new dates

    DateTime dtOut = _global.getSession().createDateTime(new java.util.Date());

    DateTime dtDue = _global.getSession().createDateTime(new java.util.Date());

 

    dtDue.adjust(14);

 

    //perform check-out

    _doc.replaceItemValue("Status",STATUS_OUT);

    _doc.replaceItemValue("MemberName",member.getDoc().getItemValuteString("UserName"));

    _doc.replaceItemValue("MemberID",member.getDoc().getItemValueString("DocID"));

    _doc.replaceItemValue("DateOut",dtOut);

    _doc.replaceItemValue("DateDue",dtDue);

    save();

}}

 

列表3:

 

public final class BusinessObjectFactory {

 

    public static BusinessDocument createBusinessObject(Document doc) throws Exception{

       //get form name

       String strForm = doc.getItemValueString("Form");

 

       //init return object

       BusinessDocument bdoc = null ;

 

       //create appropriate BusinessDocument subclass

       //based on form name. Create a BusinessDocument if

       //no class applies.

       if (strForm.equals(Global.FORM_BOOK))

           bdoc = new Book(doc);

       else if (strForm.equals(Global.FORM_MEMBER))

              bdoc = new Memeber(doc);

           else

           bdoc = new BusinessDocument(doc);

 

       return bdoc;

    }

 

}

根据Notes文档的数据,你可以使用Factory模式创建一个业务对象(book或member)。BusinessObject Factory返回一个book或member对象,并把这个对象作为BusinessDocument的一个可变类型。在面向对象语言中(包括面向对象LotusScript),你可以在定义了超类的任何地方使用子类,因为子类一定拥有超类所有的公共属性和方法。

BusinessObjectFactory代码如列表3。

Objectifier模式允许一个子类对所有给的函数进行选择性重载,以执行这个函数的待定需求。在这个模式中,定义方法来调用表示父类类型的变量,但这个子类是在runtime时确定的,并对这个方法进行了重载以执行选定的需求。

首先,看看在不同使用这些模式的时候是如何调用delete()方法的。似通过个Delete代理处理member和book的删除操作,代码如列表4。

列表 4:

。。。

//get document and form

Document doc = dbCurrent.getDocumentByUNID(strUNID);

String strForm = doc.getItemValueString("Form");

 

//instantiate appropriate object based on form and perform deletion

if(strForm.equals(Global.FORM_BOOK)){

       Book book = new Book(doc);

}else if(strForm.equals(Global.FORM_MEMBER)){

      Member member = new Member(doc);

member.deleter();

}

使用Factory和objectifier模式完成相同的任务,代码如列表5。

列表5:

//Create business object

Document doc = dbCurrent.getDocumentBUNID(strUNID);

BusinessDocument bdoc = BusinessObjectFactory.createBusinessObject(doc);

 

//perform deletion

bdoc.delete();

BusinessObjectFactory.createBusinessObject(doc)返回一个book或member对象,且的对象为超类BusinessDocument的一个变量类型。它对delete()进行调用。

除了代理中只需较少的代码之外,使用这些模式的好处主要体现在维护上。第一种方法中,form-to-business-object的匹配过程体现在代理中。当你需要在应用中增加新的对象类型,例如video,你必须更新为个匹配过程。而且,另一个执行公共任务(如webQuerySave())的代理也必须包含同样的匹配过程。把Factory和Objectfier相结合,你就可以随意 增加或删除新的文档类型,而不用对代理作出修改。

表3 : library 执行所有的方法和过程

用例

执行过程

创建 book

更新 book

注册 member

更新 member

l  文档的创建与更新通过表单和webQuerySave代理来处理。库对所有的表单都使用一个WebQuerySave代理

l  在文档被保存时,代理使用factory和objectifier模式对相应的业务对象调用 webQuerySave()

l  业务对象能够对webQuerySave()进行重载,以执行对业务对象的验证或操作

l  Member和Book中的webQuerySave()方法都确保创建和更新的用例的预处理应在保存进程进行之前。

删除 book

删除 member

l  Delete代理(作为MVC删除控制器)使用Factory和Objectifier模式对于已经建立的member或book对象调用delete()

l  book和member类的deleter()方法使各自的预处理生效,并调用 super.delete()执行删除。

Checkout book

Checkin book

Checkout代理(作为进行checkout和checkin的模式MVC控制器)创建book对象,并根据所得参数“action”的值来调用checkout或checkin方法

其他用例的实现

表3 总结了library执行所有用例的方法和过程。

设计模式的力量

MVC设计模式把表现层代码从业务逻辑中分离出来,Domino中使用MVC可以简化对UI的维护并为应用功能提供了可选的多界面。

Domino应用可以通过某些某些机制(包括ODBC和JDBC驱动器)使它们的数据对于其它系统可用。赋闲的,MVC模式可以使应用实现的功能对于系统可用,除了为web浏览器服务之外,应用可以向web services、WAP、CORBA和其它多种类型的客户端提供服务。

   虽然有很多途径用来组织model层,但是通过使用一个java类且表现出现实世界对象的模式是最好的选择。J2EE中,现实世界的对象通过 enterprise session beans和enterprise entity beans来表现,enterprise session beans包含业务逻辑,而enterprise entity beans包含持久数据。在Domino中,业务对象包含了业务逻辑,Notes文档包含了稳定的数据。

   如果使用业务对象实现编码,对于越复杂的应用,你将会得到 越多的益处。业务对象能够封装与现实世界的对象相关的所有任务和业务规则。与现实世界对象相关的功能代码不 能在不同的代理里面进行跨跃。

   把代码封装进一个对象之后,你可以使用熟悉的设计模式来解决公共问题,对于调用多业务对象(例如删除、更新或批准操作)的公共操作,Factory和Objectifier模式提供了很有效的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值