实例
下面以一个逻辑树为例子,以上面的原理图为蓝本,看看如何实现并如何使用这个树,这个结构很简单,但是如何去使用树,遍历树、为我所用还是有一定难度的。
 
这里主要用到树的递归遍历,如何递归、如何控制遍历层级,如何将逻辑关系转换为(类似)物理关系,这些都是有相当难度的。
 
废话就不说了,看看便知。
/**
* 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. Mysql--七种 Join 查询

    Mysql 系列文章主页 =============== 1 准备数据 1.1 建立 Employee 表 DROP TABLE IF EXISTS employee; CREATE TABLE IF ...

  2. ConcurrentHashMap1.7和1.8的不同实现

    ConcurrentHashMap 在多线程环境下,使用HashMap进行put操作时存在丢失数据的情况,为了避免这种bug的隐患,强烈建议使用ConcurrentHashMap代替HashMap,为 ...

  3. javascript templating

    JavaScript Micro-Templating I’ve had a little utility that I’ve been kicking around for some time no ...

  4. day0203 XML 学习笔记

    day02, 03 1. xml语言和作用 2. xml语法详解 2.1 xml 语法声明 2.1.1 encoding 属性 2.1.2 standalone 属性 2.2 xml 元素(Eleme ...

  5. 解释session

    我理解的session就是,多个页面都要使用某一个或一些数据,这时就可以用session,将数据暂时保存起来,这样其他的页面开启session,就能将那些数据拿出来使用.

  6. js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题

    js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题 js模拟form表单提交数据源码: /** * js模拟form表单提交 * @param ...

  7. asp.net使用session完成: 从哪个页面进入登录页面,登录成功还回到那个页面

    1.在Login.aspx页面Load中加入 if (!IsPostBack && Request.UrlReferrer != null) {      Session[ " ...

  8. ACM Meteor Shower

    贝茜听到一场非同寻常的流星雨( meteor shower)即将来临;有报道称这些流星将撞击地球并摧毁它们所击中的任何东西.为了安全起见(Anxious for her safety), ,她发誓(v ...

  9. webpack4.x配置详解,多页面,多入口,多出口,新特性新坑!!

    花了差不多一天多的时间,重新撸了一遍webpack4.x的常用配置. 基本上常用的配置都熟悉了一遍,总体上来讲,为了对parcel进行反击,webpack从4.x开始,正在朝着尽可能的简化配置文件的方 ...

  10. 安卓高级4 第三方库SlidingMenu的使用

    源码位于github上(本人fork地址):点击进入地址 效果图: 使用方法:下载源码后 解压其中的文件夹library 到任意地方 修改library中gragle 其方法参考另一个博客(建议先修改 ...