一学习背景在学习关于JSF组件时涉及到了composite模式于是就查看一些资料以下是自己对这种模式的理解
二自己整理的一些资料(见参考资料)
posite模式意在组成任意复杂度的整体部分组件层次结构同时将单个组件或复合组件视为统一的接口树形组织结构就是其中一种表现形式
树形结构中有叶子结点和非叶子结点(根结点是特例)非叶子结点可以添加删除(add()delete())子结点获取子结点(getChild())叶子结点没有此外树结构的所有节点还有共同的操作(operator())
用户界面通常由两种基本类型的组件构造基本组件和容器组件容器组件可以在其内部嵌套任意数目的组件而基本组件则不行使用这两种组件类型开发者可以建立更强大的组件进而创建多姿多彩的用户界面
但是在与复杂的组件层次结构打交道时必须在容器组件和基本组件之间进行区分比较麻烦composite提供了一种解决方案适用它的情况
a要表现部分整体的层次结构时
b希望在事件组件层次中同等对待复合组件与单个组件
通过下面的示例来理解
示例
基类shape类有两个派生类Circle和Square(相当于叶子结点或者是单个组件)第三个派生类CompositeShape是个组合体(相当于非叶子结点或者是容器组件)它持有一个含有多个shape实例的列表当调用CompositeShape中的draw()时它就把这个方法委托给列表中的每一个实例
对于系统而言一个CompositeShape实例就像是一个独立的shape可以把它传给使用shape的方法或者对象实际上它只是一组shape实例的proxy
程序
Shapejava:
PublicinterfaceShape{
Publicvoiddraw();
}
CompositeShapejava:
PublicclassCompositeShapeimplementsShape{
privateVectorComshape=newVector();
publicvoidadd(Shapeshape){
Comshapeadd(shape);
}
Publicvoiddraw(){
for(inti=;i<comshapesize();i++){
Shapeshape=(Shape)comshapeelementAt(i);
Shapedraw();
}
}
}
示例
抽象类Equipment就是Component定义代表着组合体类的对象们Equipment中定义几个共同的方法
packagecominterf;
publicabstractclassEquipment{
privateStringname;
privatedoublenetPrice;
privatedoublediscountPrice;
publicEquipment(Stringname){
thisname=name;
}
publicabstractdoublenetPrice();
publicabstractdoublediscountPrice();
}
Disk是组合体内的一个对象
或称一个部件
这个部件是个单独元素(Primitive)
Diskjava:
packageimplEquip;
importcominterfEquipment;
publicclassDiskextendsEquipment{
publicDisk(Stringname){
super(name);
//TODOAutogeneratedconstructorstub
}
//定义Disk实价为
publicdoublenetPrice(){
return;
}
//定义了disk折扣价格是对折
publicdoublediscountPrice(){
return;
}
}
还有一种可能是
一个部件也是一个组合体
就是说这个部件下面还有
儿子
这是树形结构中通常的情况
应该比较容易理解
现在我们先要定义这个组合体
CompsiteEquipmentjava:
packageimplEquip;
importjavautilArrayList;
importjavautilIterator;
importjavautilList;
importjavautilNoSuchElementException;
importcominterfEquipment;
publicclassCompositeEquipmentextendsEquipment{
privateinti=;
//定义一个Vector用来存放儿子
privateListequipment=newArrayList();
publicCompositeEquipment(Stringname){
super(name);
//TODOAutogeneratedconstructorstub
}
publicbooleanadd(Equipmentequipment){
thisequipmentadd(equipment);
returntrue;
}
publicdoublenetPrice(){
doublenetPrice=;
Iteratoriter=erator();
while(iterhasNext())
netPrice+=((Equipment)iternext()Price();
returnnetPrice;
}
publicdoublediscountPrice(){
doublediscountPrice=;
Iteratoriter=erator();
while(iterhasNext())
discountPrice+=((Equipment)iternext())discountPrice();
returndiscountPrice;
}
//注意这里这里就提供用于访问自己组合体内的部件方法
//上面dIsk之所以没有是因为Disk是个单独(Primitive)的元素
publicIteratoriter(){
returnerator();
}
//重载Iterator方法
publicbooleanhasNext(){returni<equipmentsize();}
//重载Iterator方法
publicObjectnext(){
if(hasNext())
returnequipmentget(i++);
else
thrownewNoSuchElementException();
}
}
上面CompositeEquipment继承了Equipment同时为自己里面的对象们提供了外部访问的方法重载了IteratorIterator是Java的Collection的一个接口是Iterator模式的实现
我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet箱子里面可以放很多东西如底板电源盒硬盘盒等盘盒里面可以放一些小设备如硬盘软驱等无疑这两个都是属于组合体性质的
Cabinetjava:
packageimplEquip;
publicclassCabinetextendsCompositeEquipment{
publicCabinet(Stringname){
super(name);
//TODOAutogeneratedconstructorstub
}
publicdoublenetPrice(){
return+super}
publicdoublediscountPrice(){
return.5+super.discountPrice();
}
}
Chassi.java:
packageimplEquip;
publicclassChassisextendsCompositeEquipment{
publicChassis(Stringname){
super(name);
//TODOAuto-generatedconstructorstub
}
publicdoublenetPrice(){
return1.+super}
publicdoublediscountPrice(){
return.5+super.discountPrice();
}
}
至此我们完成了整个Composite模式的架构。tW.WIngwiT.cOM我们可以看看客户端调用Composote代码:
CompositeTest.java:
packagetest;
importimplEquip.Cabinet;
importimplEquip.Chassis;
importimplEquip.Disk;
publicclassCompositeTest{
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
//TODOAuto-generatedmethodstub
Cabinetcabinet=newCabinet("Tower");
Chassischassis=newChassis("PCChassis");
//将PCChassis装到Tower中(将盘盒装到箱子里)
cabinet.add(chassis);
//将一个10GB的硬盘装到PCChassis(将硬盘装到盘盒里)
chassis.add(newDisk("10GB"));
//调用netPrice()方法;
System.out.println("netPrice="+Price());
System.out.println("discountPrice="+cabinet.discountPrice());
}
}
上面调用的方法netPrice()或discountPrice(),实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.
控制台输出:
netPrice=3.0
discountPrice=1.5
三.JSF组件提供的实现非常接近Composite模式给出的一般性解决方案,不过(和Swing不同)这里的顶层和一般组件之间没有明显差异。
JSF提供了一个所有组件都要实现的UIComponent接口,UIComponentBase类为了方便组件开发者,定义了默认的行为。JSF有许多基本组件如UIForm和UIInput。另外可以创建自己的自定义组件。创建自定义组件时,必须要实现UIComponent接口或者继承UIComponentBase类
JSF为使用默认组件提供了方便的标记库。当页面被应用的用户提交时,FacesServlet将根据这些标记所提供和搜集的信息实际建立一个组件树(本人想法:具体建树过程以及管理被封装起来了,在管理和使用UI组件的原理应该同composite模式一致;实际是什么???能找到实现的代码最好了)
第一层:form
第二层:label,outputtext,panel
第三层:command1command2
UI组件是在服务器的视图或者组件树中进行管理,组件可以直接关系到JavaBean属性的值(任何遵循了JavaBean命名约定的Java对象都可以为JSF组件命使用),在客户端表现为HTML语言(或者其他显示语言)。JavaBean用来收集用户输入的数据,并在需要时重新封闭到页面中。
四.参考资料:
1设计模式之Composite(组合)板桥里人;2002/04/27
网址:
2《MasteringJavaServerFaces》中文版(第一章1.4)
3《敏捷软件开发:原则、模式与实践》
4.《JSF实战》