首页 > 学院 > 开发设计 > 正文

在组合模式中实现访问者(Visitor)模式

2019-11-18 12:16:11
字体:
来源:转载
供稿:网友

   本文从一个给定的实现了组合(Composite)模式的例子开始,说明怎么在这个数据结构上实现业务逻辑代码。依次介绍了非面向对象的方式、在组合结构中加入方法、使用访问者(Visitor)模式以及用改进后的访问者(Visitor)模式来实现相同的业务逻辑代码,并且对于每种实现分别给出了优缺点。

  读者定位于具有java程序开发和设计模式经验的开发人员。

  读者通过本文可以学到如何在组合(Composite)模式中实现各种不同的业务方法及其优缺点。

  组合(Composite)模式

  组合模式是结构型模式中的一种。GOF的《设计模式》一书中对使用组合模式的意图描述如下:将对象组合成树形结构以表示"部分-整体"的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

  组合模式应用广泛。根据GOF中对组合模式的定义,Composite模式一般由Component接口、Leaf类和Composite类组成。现在需要对一个软件产品治理系统的实体建模:某公司开发了一系列软件集(SoftwareSet),包含了多种品牌(Brand)的软件产品,就象IBM提供了Lotus、WebsPhere等品牌。每个品牌下面又有各种产品(PRodUCt),如IBM的Lotus下面有Domino Server/Client产品等。建模后的类图如下(代码可以参见随本文带的附件中,包com.test.entity下所有的源文件):

在组合模式中实现访问者(Visitor)模式(图一)


  如图所示:

  (1)接口SoftwareComponent就是对应于组合模式中的Component接口,它定义了所有类共有接口的缺省行为

  (2)AbsSoftwareComposite类对应于Composite类,并且是抽象类,所有可以包含子节点的类都扩展这个类。这个类的主要功能是用来存储子部件,实现了接口中的方法,部分可以重用的代码写在此类中

  (3)SoftwareSet类继续于AbsSoftwareComposite类,对应于软件集,软件集下直接可以包含品牌(Brand),也可以直接包含不属于任何品牌的产品(Product)

  (4)Brand类继续于AbsSoftwareComposite类,对应于品牌,包含了品牌名属性,并且用来存储Product类的实例

  (5)Product类就是对应的Leaf类,表示叶子节点,叶子节点没有子节点

  用不同的方法实现业务逻辑

  数据结构建立好之后,需要在这个数据结构上添加方法实现业务逻辑。比如现在的这个例子中,有这样的需求:给定一些用户选择好的产品,需要计算出这些选中后软件的总价格。下面开始介绍如何使用各种不同的方法来实现这个业务逻辑。

  非面向对象的编程方式

  这种方式下,编程思路最简单:遍历SoftwareSet实例中的所有节点,假如遍历到的当前对象是Product的话就累加,否则继续遍历下一层直到全部遍历完毕。代码片断如下:

  1. /**
  2.  * 取得某个SoftwareComponent对象下面所有Product的价格
  3.  * @param brand
  4.  * @return
  5.  */
  6. public double getTotalPrice(SoftwareComponent softwareComponent) {
  7.     SoftwareComponent temp = softwareComponent;
  8.     double totalPrice = 0;
  9.     //假如传入的实例是SoftwareSet的类型
  10.     if (temp instanceof SoftwareSet) {
  11.         Iterator it = ((SoftwareSet) softwareComponent).getChilds()
  12.                 .iterator();
  13.         while (it.hasNext()) {//遍历
  14.             temp = (SoftwareComponent) it.next();
  15.             //假如子对象是Product类型的,直接累加
  16.             if (temp instanceof Product) {
  17.                 Product product = (Product) temp;
  18.                 totalPrice += product.getPrice();
  19.             } else if (temp instanceof Brand) { 
  20.             //假如子对象是Brand类型的,则遍历Brand下面所有的产品并累加
  21.                 Brand brand = (Brand) temp;
  22.                 totalPrice += getBrandPrice(brand);
  23.             }
  24.         }
  25.     } else if (temp instanceof Brand) {
  26.         //假如传入的实例是SoftwareSet的类型,则遍历Brand下面所有的产品并累加
  27.         totalPrice += getBrandPrice((Brand) temp);
  28.     } else if (temp instanceof Product) {
  29.         //假如子对象是Product类型的,直接返回价格
  30.         return ((Product) temp).getPrice();
  31.     }
  32.     return totalPrice;
  33. }
  34. /**
  35.  * 取得某个Brand对象下面所有Product的价格
  36.  * @param brand
  37.  * @return
  38.  */
  39. private double getBrandPrice(Brand brand) {
  40.     Iterator brandIt = brand.getChilds().iterator();
  41.     double totalPrice = 0;
  42.     while (brandIt.hasNext()) {
  43.         Product product = (Product) brandIt.next();
  44.         totalPrice += product.getPrice();
  45.     }
  46.     return totalPrice;
  47. }



发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表