总体介绍:
UI工厂是一套基于NC-UAP的UI开发框架。它的产生同构对大量的业务节点的总结,把常见的UI进行分类,分别抽取其中公有的代码,形成不同的UI基类。UI工厂综合运用了单据模板,查询模板,打印模板,实现对这些基本构件得到运用的最优化。UI工厂提供给了UI相关的常见任务的推荐实现方法,比如通过ButtonManager来统一管理界面按钮的状态,使代码更清晰可读,等等。
基本介绍:
UI工厂基本策略就是:细分职责,高度重用。仔细分析客户端的各种功能可以发现,有些功能间有较强的相互关联,而这些功能与其他功能间的关联也是。对这些有较强的功能一般陈其具有一定的内聚性。UI工厂中把客户端的各种功能根据其内聚性分成若干组。针对每组功能,都抽象出一个Class来负责这部分“职责”。比如一个Buffer来专门负责缓存多张单据和翻页等相关任务;ButtonManager负责处理创建按钮以及维护按钮的状态。
UI : 继承ToftPanel , 功能节点注册需注册该类,是一个节点的入口类。在UI工厂的框架中,相当于Mediator角色。
ButtonManager : 按钮管理器,负责按钮的创建和运行期状态控制。
BusinessDelegator : 业务委托类,负责和后台进行交互。除了BusinessAction中的任务,其他所有的和后台交互,即对XXXBO_Client调用都必须放到该类中,其他类必须通过这个Delegator与后台交互。
IController : 界面控制器。不要把它和MVC模式中的"C"之间划上等号,它在这里相当于一个配置文件的作用。在使用具体的模式时都有对于IController实现,使用者需要根据实际情况补充其中的信息。
EventHandle : 按钮事件处理器。所有对按钮事件的处理都在这个类实现。
BusinessAction : 业务动作处理类。处理保存、审批等“业务”动作。
HYQueryDlg :查询对话框。支持增加常用条件页签。
单据模型:
主子表:也就是UI工厂的默认形式。这种情况不需特别的配置。只需实现IControllerBase.getBillVOName()方法,通过一个String数组返回聚和VO,主表VO,子表VO的ClassName即可。
多子表:有多个子表这种情况需要继承专门的多子表基类,在IControllerBase.getBillVOName()的方法里依次返回聚合VO,主表VO,子表VO1...... 的ClassName即可。其中聚合VO需要实现IExAggVO接口。
单表头:没有表体的卡片。实际实现时把聚合VO的子表当成NULL处理。需要让UI的Controller实现ISingleController接口。并在isSingleDetai方法返回false。
单表体:没有表头的卡片。一般用于一些基本档案节点。实现时把聚合VO的主表当成NULL处理。需要让UI的Controller实现ISingleController接口。并在isSingleDetail方法中返回true。
BillUIBuffer:
在很多节点中需要对多张单据进行浏览、操作;在执行完一个查询任务后返回的结果也是很多张单据;这就要求客户端有个单据的缓冲区,用户可以操作其中的任何一个单据而不必去每次都去后台查询相应的数据。BillUIBuffer被设计出来完成这个任务。这是一个“线性”的缓冲,其内部是把多个单据保存在一个ArrayList中,有一个名为CurrentRow的指针,其所指的单据就是当前用户所选的单据,如果想通过程序选择特定的单据,只需调用BillUIBuffer.setCurrentRow即可。
BillUIBuffer和UI共同实现了一个Observer模式。前者作为一个Observable的子类允许后者对其的“Observing”。当BillUIBuffer的数据发生改变时,比如setCurrentRow被调用,它会通知UI刷新界面数据。对单据进行浏览的功能,比如上一页,下一页等就是调用setCurrentRow来实现的
BillUIBuffer在UI工厂中的角色不能上直接和MVC模式中的Model划等号,其在UI工厂中的角色主要是一个Buffer,而不是一个Model。当对单据进行编辑时,通过BillUIBuffer.getCurrentVO() 得到VO并不是你在界面上看到的数据,这是因为当进行编辑操作时,界面上的数据和BillUIBuffer实际上“脱钩”了的。只有编辑完,保存后,BillUIBuffer才能更新。
加载界面:
UI工厂的AbstractBillUI对加载界面做任何的封装。真正的界面的加载工作都是由具体的子类,比如卡片界面来实现的。NC中的UI大多是基于单据模板实现的。要使用单据模板便少不了加载模板,设置模板各项参数等“苦差事”。于是BillCardPanelWrapper和BillListPanelWrapper被设计出来专门处理卡片式和列表式的单据模板的加载及设置工作。另外这两个Wrapper提供了一些单据模板自身不够完善的功能,比如按行执行公式等等。
上述的两个Wrapper是UI工厂的两个重要的基本工具类,但是其也可以被独立于UI工厂使用。只需提供合适的Controller,Wrapper就能完成单据模板的加载和设置。通过调用getBillCaardPanel可以得到单据模板类的实例,这个Panel可以被放到其他任何Panel或者Dialog中。
按钮:
UI工厂通过ButtonManager统一管理按钮的创建和状态。具体的业务节点不负责创建各个ButtonManager的实例,而是通过一个ID号来向ButtonManager注册一个按钮,ButtonManager会对所有该节点注册的按钮生成一个实例,业务代码可以使用按钮ID向ButtonManager获取对应按钮的实例。具体vde业务节点不负责控制按钮的可用与不可用,而是配合UI状态来设置按钮的“可用策略”的。对每一个按钮可以设置当UI处于何种状态时按钮是可用的。当程序运行时ButtonManager自动根据UI状态变迁来设计各个按钮的可用与不可用。通常,在刷新单据数据时会根据UI相关状态和扩展状态重新自动设置按钮的“可以策略”,如果单据和平台相关,还需要根据相关状态设置按钮“可以策略”。确保后者的方法是使单据UI控制类的isExistBillStatus方法返回true。
UI工厂预先注册了很多常见的按钮,比如新增,编辑,保存等等。这些按钮的显示名称,状态信息,热键以及策略都是预置好的,一般各个业务节点不需要修改。如前文所述,每一个按钮有一个ID号与之对应。比如新增为(Add)、查询(Query)完整的列表可以参看IBillButton的定义。业务节点根据实际的需要可以指定需要哪些按钮,当程序初始化时ButtonManager会负责把这些按钮创建出来。比如对于基于“卡片界面”实现的节点可以在ICardController.getCardButtonAry()指定需要的按钮。
每个Btn的配置信息保存在ButtonVO中,在ButtonObject.getData可以得到整个ButtonVO,对特定按钮的可用策略的修改可以通过得到该按钮一个实例修改ButtonVO的值。