赛迪网 > IT技术 Java > 技术动态
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

进阶:Composite模式及其在JSF中的应用

发布时间:2007.12.26 07:34     来源:赛迪网    作者:IceCreamChen

一 学习背景

   在学习关于JSF组件时涉及到了composite模式,于是就查看一些资料,以下是自己对这种模式的理解。

二  自己整理的一些资料(见参考资料)

1.composite模式意在组成任意复杂度的整体--部分组件层次结构,同时将单个组件或复合组件视为统一的接口。树形组织结构就是其中一种表现形式。

树形结构中有叶子结点和非叶子结点(根结点是特例),非叶子结点可以添加,删除(add(),delete())子结点,获取子结点(getChild()),叶子结点没有;此外树结构的所有节点还有共同的操作(operator()).
用户界面通常由两种基本类型的组件构造:基本组件和容器组件,容器组件可以在其内部嵌套任意数目的组件,而基本组件则不行。使用这两种组件类型,开发者可以建立更强大的组件,进而创建多姿多彩的用户界面。
但是在与复杂的组件层次结构打交道时,必须在容器组件和基本组件之间进行区分,比较麻烦,composite提供了一种解决方案。适用它的情况:
a. 要表现“部分-整体”的层次结构时
b. 希望在事件组件层次中,同等对待复合组件与单个组件。

2. 通过下面的示例来理解
示例1: 
基类shape 类有两个派生类Circle和Square(相当于叶子结点或者是单个组件),第三个派生类CompositeShape是个组合体(相当于非叶子结点或者是容器组件),它持有一个含有多个shape实例的列表,当调用CompositeShape中的draw()时,它就把这个方法委托给列表中的每一个实例。
 
对于系统而言,一个CompositeShape实例就像是一个独立的shape,可以把它传给使用shape的方法或者对象。实际上,它只是一组shape实例的proxy.
程序:

  1. Shape.java:
  2. Public interface Shape {
  3.     Public void draw();
  4. }
  5. CompositeShape.java:
  6. [code]Public class CompositeShape implements Shape {
  7.   private Vector Comshape = new Vector();
  8.   public void add(Shape shape) {
  9.     Comshape.add(shape);
  10.   }
  11.   Public void draw() {
  12.     forint i = 0; i < comshape.size(); i ++ ) {
  13.        Shape shape = (Shape) comshape.elementAt(i);
  14.        Shape.draw();
  15.     }
  16.   }
  17. }

示例2: 
抽象类Equipment就是Component定义,代表着组合体类的对象们,Equipment中定义几个共同的方法。
  1. package com.interf;
  2. public abstract class Equipment {
  3.     private String name;
  4.     private double netPrice;
  5.     private double discountPrice;
  6.     
  7.     public Equipment(String name) {
  8.         this.name = name;
  9.     }
  10.     public abstract double netPrice();
  11.     public abstract double discountPrice();
  12. }
Disk是组合体内的一个对象,或称一个部件,这个部件是个单独元素( Primitive)。
Disk.java:
  1. package implEquip;
  2. import com.interf.Equipment;
  3. public class Disk extends Equipment {
  4.     public Disk(String name) {
  5.         super(name);
  6.         // TODO Auto-generated constructor stub
  7.     }
  8.     
  9.     //定义Disk实价为1
  10.     public double netPrice() {
  11.         return 1.; 
  12.     }
  13.     //定义了disk折扣价格是0.5 对折。
  14.     public double discountPrice() { 
  15.         return .5; 
  16.     }    
  17. }
还有一种可能是,一个部件也是一个组合体,就是说这个部件下面还有'儿子',这是树形结构中通常的情况,应该比较容易理解。现在我们先要定义这个组合体:
CompsiteEquipment.java:
  1. package implEquip;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import java.util.NoSuchElementException;
  6. import com.interf.Equipment;
  7. public class CompositeEquipment extends Equipment {
  8.     
  9.     private int i=0; 
  10. //    定义一个Vector 用来存放'儿子'
  11.     private List equipment = new ArrayList();
  12.     
  13.     public CompositeEquipment(String name) {
  14.         super(name);
  15.         // TODO Auto-generated constructor stub
  16.     }
  17.     public boolean add(Equipment equipment) { 
  18.         this.equipment.add(equipment); 
  19.         return true
  20.     }
  21.     public double netPrice() {
  22.         double netPrice=0.;
  23.         Iterator iter=equipment.iterator();
  24.         while(iter.hasNext())
  25.           netPrice+=((Equipment)iter.next()).netPrice();
  26.         return netPrice;
  27.     }
  28.     public double discountPrice() {
  29.         double discountPrice=0.;
  30.         Iterator iter=equipment.iterator();
  31.         while(iter.hasNext())
  32.           discountPrice+=((Equipment)iter.next()).discountPrice();
  33.         return discountPrice;
  34.     }
  35. //    注意这里,这里就提供用于访问自己组合体内的部件方法。
  36. //    上面dIsk 之所以没有,是因为Disk是个单独(Primitive)的元素.
  37.     public Iterator iter() {
  38.         return equipment.iterator() ;
  39.     }
  40. //    重载Iterator方法
  41.     public boolean hasNext() { return i//    重载Iterator方法
  42.     public Object next(){
  43.     if(hasNext())
  44.         return equipment.get(i++);
  45.     else 
  46.         throw new NoSuchElementException();
  47.     }
  48. }

上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口,是Iterator模式的实现.
我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet,箱子里面可以放很多东西,如底板,电源盒,硬盘盒等;盘盒里面可以放一些小设备,如硬盘 软驱等。无疑这两个都是属于组合体性质的。
  1. Cabinet.java:
  2. package implEquip;
  3. public class Cabinet extends CompositeEquipment {
  4.     public Cabinet(String name) {
  5.         super(name);
  6.         // TODO Auto-generated constructor stub
  7.     }    
  8.     public double netPrice() { 
  9.         return 1.+super.netPrice(); 
  10.     }
  11.     public double discountPrice() { 
  12.         return .5+super.discountPrice();
  13.     }
  14. }



Chassi.java:
  1. package implEquip;
  2. public class Chassis extends CompositeEquipment {
  3.     public Chassis(String name) {
  4.         super(name);
  5.         // TODO Auto-generated constructor stub
  6.     }
  7.     public double netPrice() { 
  8.         return 1.+super.netPrice(); 
  9.     }
  10.     public double discountPrice() { 
  11.         return .5+super.discountPrice();
  12.     }
  13. }

至此我们完成了整个Composite模式的架构。我们可以看看客户端调用Composote代码:

CompositeTest.java:
  1. package test;
  2. import implEquip.Cabinet;
  3. import implEquip.Chassis;
  4. import implEquip.Disk;
  5. public class CompositeTest {
  6.     /**
  7.      * @param args
  8.      */
  9.     public static void main(String[] args) {
  10.         // TODO Auto-generated method stub
  11.         Cabinet cabinet=new Cabinet("Tower");
  12.         Chassis chassis=new Chassis("PC Chassis");
  13. //        将PC Chassis装到Tower中 (将盘盒装到箱子里)
  14.         cabinet.add(chassis);
  15. //        将一个10GB的硬盘装到 PC Chassis (将硬盘装到盘盒里)
  16.         chassis.add(new Disk("10 GB"));
  17. //        调用 netPrice()方法;
  18.         System.out.println("netPrice="+cabinet.netPrice());
  19.         System.out.println("discountPrice="+cabinet.discountPrice());
  20.     }
  21. }

上面调用的方法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
第三层:command1 command2

UI组件是在服务器的视图或者组件树中进行管理,组件可以直接关系到JavaBean属性的值(任何遵循了JavaBean命名约定的Java对象都可以为JSF组件命使用),在客户端表现为HTML语言(或者其他显示语言)。JavaBean用来收集用户输入的数据,并在需要时重新封闭到页面中。
      (责任编辑:包春林)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· JSP/Servlet/JSF:JavaEE 不再需要 Ajax (12-25) · 开发框架:深入了解 Struts Validator (12-25)
· J2SE综合:如何在Java中实现条件编译 (12-25) · 在Eclipse RCP中实现控制反转(IoC) (12-25)
· Eclipse使用技巧 (12-25) · java 中使用websphere MQ (12-24)
· Web Services:处理XML字符串中特殊字符 (12-24) · 数据库相关:数据库连接池的原理机制 (12-24)
· Java语言深入:在Java中使用VC++组件 (12-24) · 如何在jsp中使用 jquery 的 ajax 功能 (12-24)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
· 电子商务行业规范出台 电子商务发展目标与规划
· 中小企业网站存在盲目性 消费习惯需重点培养
· 天灾中信息化显力量 CIO如何应对新领导IT改革
· 河南网通数据中心工程 网御神州VPN解决方案
  IT博客 ·曾剑秋·项立刚·Java学习·网管
  IT技术论坛 ·开发·网管·安全·数据库·系统