• 老生常谈:组合模式


        名词解释:
       
        组合:由几个部分或个体结合成整体或者组织成整体。

        组合模式定义:将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

       组合模式的组成:

      1):Component:它为组合中的对象声明接口,也可以为共有接口实现缺省行为。

      2):角色Leaf:顾名思义,它是单一构件,不存在任何的子项.实现抽象构件角色声明的接口。

      3):角色Composite:复杂对象,一般会包含多个树叶(Leaf)对象.实现抽象构件角色声明的接口;管理树叶(Leaf)对象。


       组合模式一般有两实现方式:安全性与透明性模式

       透明性:

           在Component里面声明所有用来管理子类对象的方法。目的就是为了使客户看来Leaf和Composite没有区别。Leaf是不存在子类的,因此Component声明的一些方法对于Leaf来说是不适用的。这说是它的安全性问题。下面是类图:

     

      

         安全性:

           只在Composite里面声明所有的用来管理子类对象的方法。这样就避免了安全性问题,但是由于Leaf和Composite有不同的接口,所以又失去了透明性。下面是类图:

     


        这两种实现方式各有所长,开发者可以根据自己的实际情况来取舍,本人推荐透明性,因为它对客户端来说是最简单的,它的安全性问题完全可以用些空处理等方式来避免.

        我在这里用一个增送礼物的需求来说明一下组合模式的应用.

        说明:此例子不太符合实际,只是为了说明组合模式的应用生搬的一个例子。在实际中并不会出现这样的情况:

                把第一名得到的五个奖品分五次发送。

        需求:网站需要推行一个有奖活动,中奖的用户可以根据名次来得到相应的奖品.例如,奖项分为五个:

            第五名:一个奖品.
            第四名:两个奖品
            第三名:三个奖品
            第二名:四个奖品

            第一名:五个奖品

        程序要实现的就是根据名次来发送相应的礼品包,同时记录些相关信息,例如礼品包中的礼物信息以后中奖人信息等等.

      

        一个奖品的发送是最简单的,因为信息单一,一个奖品一个用户,录入数据库就OK了,名次越前程序要记录的东西就越多,当在处理第一名时,要判断是单个奖品还是多个奖品(因为单个奖品和礼品包在业务处理上会有不同).这样在客户端调用的时候往往会产生大量的代码.而且最可怕的是这种代码依赖于奖品发送的具体业务处理类。能不能让客户调用的时候不去费心的判断奖品的类型,而是直接调用一个统一的方法,例如sendGift(),这时就要用到组合模式了。

         例子的类结构图

     



         礼物与中奖人信息我用一个实体类来记录 giftAndUserInfo,它包含礼物名称及中奖人用户名.

    Code

        抽象类sendGiftComponent,它定义了发送礼物的方法以及管理子类的方法Add,Romove.

    Code

        发送单个礼物的Leaf,这个类实现单个礼物的发送

    Code

        发送礼物包的Composite,它负责把多个礼物打包成一个整体,然后一个一个发送出去.

    Code

        客户端调用代码:

           本例只为说明问题,只是将要发送的礼品包里面的全部礼品名称以及中奖人信息输出.例子是调用的是发送一个第二名礼品包.

    Code

     

        输出结果:

     

         优点:

              

               1:以上的代码中,客户端不关心要处理的是单个礼物还是礼品包,统一对待,使客户端调用简单化.

               2:如果礼品包中要增加或者是删除一个礼物,都无需更改代码结构,这符合"开闭原则".


         总结:

              无论模式如何强大,用与不用取决于开发人员,如果你有足够的理由不采用那么你可以不屑此模式。 

    注:
      本文引用:
         http://blog.csdn.net/ai92/archive/2005/02/23/298336.aspx
         http://terrylee.cnblogs.com/archive/2006/03/11/347919.html

  • 相关阅读:
    【计算机视觉】OpenCV篇(6)
    【计算机视觉】OpenCV篇(5)
    C++解决头文件相互包含问题的方法
    【计算机视觉】OpenCV篇(4)
    java mysql多次事务 模拟依据汇率转账,并存储转账信息 分层完成 dao层 service 层 client层 连接池使用C3p0 写入库使用DBUtils
    MySQL事务隔离级别 解决并发问题
    在jdbc基础上进阶一小步的C3p0 连接池(DBCP 不能读xml配置文件,已淘汰) 和DBUtils 中两个主要类QueryRunner和ResultSetHandler的使用
    java数据库 JDBC操作MySQL数据库常用API 部门表和员工表 创建表 添加数据 查询数据
    java XML 通过BeanUtils的population为对象赋值 根据用户选择进行dom4j解析
    java基础 xml 使用dom4j解析 xml文件 servlet根据pattern 找到class
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1279571.html
Copyright © 2020-2023  润新知