实例
下面以一个逻辑树为例子,以上面的原理图为蓝本,看看如何实现并如何使用这个树,这个结构很简单,但是如何去使用树,遍历树、为我所用还是有一定难度的。
 
这里主要用到树的递归遍历,如何递归、如何控制遍历层级,如何将逻辑关系转换为(类似)物理关系,这些都是有相当难度的。
 
废话就不说了,看看便知。
/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-8-2 16:13:59
* 抽象文件角色
*/
public interface IFile {
    //返回自己的实例
    IFile getComposite(); 

    //某个商业方法
    void sampleOperation(); 

    //获取深度
    int getDeep(); 

    //设置深度
    void setDeep(int x); 

}

/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-8-2 16:15:03
* 文件夹角色
*/
public class Folder implements IFile {
    private String name;    //文件名字
    private int deep;       //层级深度,根深度为0
    private Vector<IFile> componentVector = new Vector<IFile>(); 

    public Folder(String name) {
        this.name = name;
    } 

    //返回自己的实例
    public IFile getComposite() {
        return this;
    } 

    //某个商业方法
    public void sampleOperation() {
        System.out.println("执行了某个商业方法!");
    } 

    //增加一个文件或文件夹
    public void add(IFile IFile) {
        componentVector.addElement(IFile);
        IFile.setDeep(this.deep + 1); 

    } 

    //删除一个文件或文件夹
    public void remove(IFile IFile) {
        componentVector.removeElement(IFile);
    } 

    //返回直接子文件(夹)集合
    public Vector getAllComponent() {
        return componentVector;
    } 

    public String getName() {
        return name;
    } 

    public void setName(String name) {
        this.name = name;
    } 

    public int getDeep() {
        return deep;
    } 

    public void setDeep(int deep) {
        this.deep = deep;
    }
}

/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-8-2 16:27:15
* 文件
*/
public class File implements IFile {
    private String name;    //文件名字
    private int deep;       //层级深度 

    public File(String name) {
        this.name = name;
    } 

    //返回自己的实例
    public IFile getComposite() {
        return this;
    } 

    //某个商业方法
    public void sampleOperation() {
        System.out.println("执行了某个商业方法!");
    } 

    public String getName() {
        return name;
    } 

    public void setName(String name) {
        this.name = name;
    } 

    public int getDeep() {
        return deep;
    } 

    public void setDeep(int deep) {
        this.deep = deep;
    }
}

import java.util.Iterator;
import java.util.Vector; 

/**
* Created by IntelliJ IDEA.
* User: leizhimin
* Date: 2008-8-2 16:35:25
* 遍历树的一个测试
*/
public class Client {
    public static String indentChar = "\t";       //文件层次缩进字符 

    public static void main(String args[]) {
        new Client().test();
    } 

    /**
     * 客户端测试方法
     */
    public void test() {
        //根下文件及文件夹
        Folder root = new Folder("树根"); 

        Folder b1_1 = new Folder("1_枝1");
        Folder b1_2 = new Folder("1_枝2");
        Folder b1_3 = new Folder("1_枝3");
        File l1_1 = new File("1_叶1");
        File l1_2 = new File("1_叶2");
        File l1_3 = new File("1_叶3"); 

        //b1_2下的文件及文件夹
        Folder b2_1 = new Folder("2_枝1");
        Folder b2_2 = new Folder("2_枝2");
        File l2_1 = new File("2_叶1"); 

        //缔造树的层次关系(简单测试,没有重复添加的控制)
        root.add(b1_1);
        root.add(b1_2);
        root.add(l1_1);
        root.add(l1_2); 

        b1_2.add(b2_1);
        b1_2.add(b2_2);
        b1_2.add(l2_1);
        root.add(l1_3);
        root.add(b1_3);
        //控制台打印树的层次
        outTree(root);
    } 

    public void outTree(Folder folder) {
        System.out.println(folder.getName());
        iterateTree(folder);
    } 

    /**
     * 遍历文件夹,输入文件树
     *
     * @param folder
     */
    public void iterateTree(Folder folder) {
        Vector<IFile> clist = folder.getAllComponent();
        //todo:遍历之前可以对clist进行排序,这些都不是重点
        for (Iterator<IFile> it = clist.iterator(); it.hasNext();) {
            IFile em = it.next();
            if (em instanceof Folder) {
                Folder cm = (Folder) em;
                System.out.println(getIndents(em.getDeep()) + cm.getName());
                iterateTree(cm);
            } else {
                System.out.println(getIndents(em.getDeep()) + ((File) em).getName());
            }
        }
    } 

    /**
     * 文件层次缩进字符串
     *
     * @param x 缩进字符个数
     * @return 缩进字符串
     */
    public static String getIndents(int x) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < x; i++) {
            sb.append(indentChar);
        }
        return sb.toString();
    }
}

三、运行测试
 
控制台输出如下:
 
 
 
可见,树逻辑关系已经成功展示出来了。
 
四、总结
1、上面所用的合成模式是安全合成模式,所谓的安全是指File与Folder中的方法不同。Folder有对聚集对象的管理,File没有。
 
2、合成模式在程序设计中有着广泛的应用,比如Dom4j、资源管理器、Java GUI容器层次图等等都是合成模式应用的典范。
 
3、合成模式很多都是需要分析思考才能鉴别出来的,比如要做一个复杂的数学表达式计算器,有四种运算符号。分析发现,运算量有两种,一种是数字、一种是数字的表达式,但是表达式也是由数字组成,因此数字和表达式可以抽象为运算量。然后去表达要运算的表达式。问题迎刃而解。

本文转载自:http://lavasoft.blog.51cto.com/62575/90824/

java设计模式---合成模式3的更多相关文章

  1. Java设计模式-合成模式

    合成模式有时也叫组合模式,对象组合成树形结构以表示"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性.掌握组合模式的重点是要理解清楚 "部分/ ...

  2. java设计模式---合成模式2

    合成模式属于对象的结构模式,有时又叫做"部分--整体"模式.合成模式将对象组织到树结构中,可以用来描述整体与部分的关系.合成模式可以使客户端将单纯元素与复合元素同等看待. 合成模式 ...

  3. Java设计模式——组合模式

    JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...

  4. java设计模式--单列模式

    java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...

  5. 3.java设计模式-建造者模式

    Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...

  6. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  7. Java设计模式——外观模式

    JAVA 设计模式 外观模式 用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构

  8. 【设计模式】Java设计模式 -工厂模式

    [设计模式]Java设计模式 -工厂模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目 ...

  9. 【设计模式】Java设计模式 - 原型模式

    [设计模式]Java设计模式 - 原型模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起 ...

随机推荐

  1. 【Java关键字-Interface】为什么Interface中的变量只能是 public static final

    三个关键字在接口中的存在原因:public:接口可以被其他接口继承,也可以被类实现,类与接口.接口与接口可能会形成多层级关系,采用public可以满足变量的访问范围: static:如果变量不是sta ...

  2. 1-学习GPRS_Air202(Air202开发板介绍)

    记得自己第一次实现远程通信是在学校里用SIM900A实现的,随着WIFI模块的普及自己就开始用WIFI模块了,当然WIFI模块已经用的很... WIFI模块要想实现远程控制必须连接路由器,其实在做王哥 ...

  3. exp和imp的使用场合

    1.检测冲突 使用exp工具,在数据库中预先检测到物理或逻辑冲突. 导出的同时,将全扫描数据库中的每张表,读出所有行.如果某处表中有个损坏的块,必然能找到它. 2.可以用来快速恢复数据库. 使用exp ...

  4. python学习之路前端-jQuery

    jQuery简介      JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF1.5+, Safa ...

  5. 模仿天猫实战【SSM版】——后台开发

    上一篇文章链接:模仿天猫实战[SSM版]--项目起步 后台需求分析 在开始码代码之前,还是需要先清楚自己要做什么事情,后台具体需要实现哪些功能: 注意: 订单.用户.订单.推荐链接均不提供增删的功能. ...

  6. AngularJs 笔记

    初识 directive 指令 ng-app 初始化一个AngularJs应用程序(通过一个值(比如 ng-app="myModule")连接到代码模块.) ng-init 初始化 ...

  7. Win7 环境下虚拟机内 Samba 服务器的安装、配置以及与主机的通信实现

    考虑到window和linux虚拟机之间互传文件较为麻烦,遂打算在虚拟机中安装Samba服务器,以此实现共享文件给window使用.然而安装配置过程曲折,遂作记录如下: 一.samba服务器的安装 正 ...

  8. 决策树之ID3、C4.5

    决策树是一种类似于流程图的树结构,其中,每个内部节点(非树叶节点)表示一个属性上的测试,每个分枝代表该测试的一个输出,而每个树叶节点(或终端节点存放一个类标号).树的最顶层节点是根节点.下图是一个典型 ...

  9. How To determine DDIC Check Table, Domain and Get Table Field Text Data For Value?

     How To determineDDIC Check Table, Domain and Get Table Field Text Data For Value? 1.Get Table Fie ...

  10. iOS objc_msgSend 野指针Crash 从 Log 提取 Crash 时 selector 的地址和名字并打印

    从 crash stack log 里面,提取 objc_msgSend 关键字,定位是否是野指针问题导致的crash,如果是则打印 crash 时的 objc_msgSend 调用的第二个参数,即 ...