精华内容
下载资源
问答
  • 一、组合模式定义 二、组合模式的结构和说明 三、组合模式示例 四、组合模式的优缺点 五、组合模式应用场景及案例 六、注意事项

    一、组合模式定义

    Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
    (将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)

    二、组合模式的结构和说明

    在这里插入图片描述
    在这里插入图片描述

    • Component 抽象的组件对象,为参与组合的对象声明接口,让客户端可以通过这个接口来访问和管理整个对象结构,可以定义一些默认的行为或属性。
    • Leaf 叶子节点对象,其下不再包含其它的子节点,也就是遍历的最小单位。
    • Composite 组合对象,通常会存储子组件,形成一个树形结构。

    注意:

    • 这里透明性是指:从客户使用组合模式时,是否需要区分是组合对象还是叶子对象。如果是透明的,那就不需要区分,都是组件对象,跟客户无关。
    • 这里安全性是指:从客户使用组合模式上看是否更安全。能访问的方法都是支持的,就说明是安全的。如果可能会发生误操作,则是不安全的。

    三、组合模式示例

    如下,我们的商品系统中有一个这样的商品类别树,现在需要管理商品类别树并输出它的结构,应该怎么实现呢?

    +服装
      +女装
        -裙子
        -旗袍
      +男装
        -衬衣
        -夹克

    不用模式的解决方案

    观察上边的商品类别树,上边的节点可以分为两类:1、可以包含其它节点的节点,称为容器节点;2、没有子节点的节点,称为叶子节点。
    那我们就可以分别定义一个容器类和一个叶子节点类。

    容器类,也就是组合类。容器类里边可以包含其它容器类或者叶子节点类,由于容器类和叶子类类型不同,所以需要分开保存。

    /**
     * 组合对象,可以包含其它组合对象或者叶子对象
     */
    @Data
    public class Composite {
        /**
         * 用来记录包含的其它组合对象
         */
        private Collection<Composite> childComposite = new ArrayList<>();
        /**
         * 用来记录包含的其它叶子对象
         */
        private Collection<Leaf> childLeaf = new ArrayList<>();
        /**
         * 组合对象的名字
         */
        private String name;
    
        public Composite(String name){
            this.name = name;
        }
        /**
         * 向组合对象加入被它包含的其它组合对象
         * @param c 被它包含的其它组合对象
         */
        public void addComposite(Composite c){
            this.childComposite.add(c);
        }
        /**
         * 向组合对象加入被它包含的叶子对象
         * @param leaf 被它包含的叶子对象
         */
        public void addLeaf(Leaf leaf){
            this.childLeaf.add(leaf);
        }
    
        /**
         * 输出组合对象自身的结构
         * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
         */
        public void printStruct(String preStr){
            //先把自己输出去
            System.out.println(preStr+"+"+this.name);
            //然后添加俩空格,表示向后缩进俩空格,输出自己包含的叶子对象
            preStr+="  ";
    
            // 输出所有的叶子节点
            for(Leaf leaf : childLeaf){
                leaf.printStruct(preStr);
            }
    
            //输出当前对象的子组合对象
            for(Composite c : childComposite){
                //递归输出每个子组合对象
                c.printStruct(preStr);
            }
        }
    }
    

    叶子节点类:

    /**
     * 叶子对象
     */
    @Data
    public class Leaf {
        /**
         * 叶子对象的名字
         */
        private String name;
    
        public Leaf(String name){
            this.name = name;
        }
    
        /**
         * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
         * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
         */
        public void printStruct(String preStr){
            System.out.println(preStr+"-"+name);
        }
    }
    

    我们通过客户端来测试一下:

    public static void main(String[] args) {
    	//定义所有的组合对象
    	Composite root = new Composite("服装");
    	Composite c1 = new Composite("男装");
    	Composite c2 = new Composite("女装");
    	//定义所有的叶子对象
    	Leaf leaf1 = new Leaf("衬衣");
    	Leaf leaf2 = new Leaf("夹克");
    	Leaf leaf3 = new Leaf("裙子");
    	Leaf leaf4 = new Leaf("套装");
    	//按照树的结构来组合组合对象和叶子对象
    	root.addComposite(c1);
    	root.addComposite(c2);
    	
    	c1.addLeaf(leaf1);
    	c1.addLeaf(leaf2);
    	
    	c2.addLeaf(leaf3);
    	c2.addLeaf(leaf4);
    	
    	//调用根对象的输出功能来输出整棵树
    	root.printStruct("");
    }
    

    运行后,输出结果如下:

    +服装
      +女装
        -裙子
        -旗袍
      +男装
        -衬衣
        -夹克

    这样是可以实现需要的功能的,但是存在一个明显的问题:组合对象和叶子对象必须要区别对待,在组合对象中需要将其分开保存,在客户端中使用时,也要分开创建。这样不仅让程序变的复杂,也对功能的扩展带来不便。

    使用组合模式来重构

    下面我们来看下怎么用组合模式来实现需要的功能。
    组合模式通过引入一个抽象的组件对象,作为组合对象和叶子对象的父对象,这样就把组合对象和叶子对象统一起来了,在使用的时候,直接操作组件对象,而不需要区分操作的是组合对象还是叶子对象。

    透明性组合模式:

    定义抽象组件

    /**
     * 抽象的组件对象,为组合中的对象声明接口,实现接口的缺省行为
     */
    @Data
    public abstract class Component {
    
        /**
         * 输出组件自身的名称
         */
        public abstract void printStruct(String preStr);
    
        /**
         * 向组合对象中加入组件对象
         * @param child 被加入组合对象中的组件对象
         */
        public void addChild(Component child) {
            // 缺省的实现,抛出例外,因为叶子对象没有这个功能,或者子组件没有实现这个功能
            throw new UnsupportedOperationException("对象不支持这个功能");
        }
    
    }
    

    组合类,继承抽象组件类。可以保存其它组合对象或者叶子对象,不需要分开保存

    /**
     * 组合对象,可以包含其它组合对象或者叶子对象
     */
    @Data
    public class Composite extends Component{
        /**
         * 用来存储组合对象中包含的子组件对象
         */
        private List<Component> childComponents = new ArrayList<>();
        /**
         * 组合对象的名字
         */
        private String name;
    
        public Composite(String name){
            this.name = name;
        }
        /**
         * 向组合对象加入被它包含的其它组合对象
         * @param c 被它包含的其它组合对象
         */
        @Override
        public void addChild(Component c){
            this.childComponents.add(c);
        }
    
        /**
         * 输出组合对象自身的结构
         * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
         */
        @Override
        public void printStruct(String preStr){
            //先把自己输出去
            System.out.println(preStr+"+"+this.name);
            //然后添加俩空格,表示向后缩进俩空格,输出自己包含的叶子对象
            preStr+="  ";
    
            //输出当前对象的子组合对象
            for(Component c : childComponents){
                //递归输出每个子组合对象
                c.printStruct(preStr);
            }
        }
    }
    

    叶子节点类,也继承抽象组件类

    /**
     * 叶子对象
     */
    @Data
    public class Leaf extends Component{
        /**
         * 叶子对象的名字
         */
        private String name;
    
        public Leaf(String name){
            this.name = name;
        }
    
        /**
         * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
         * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
         */
        @Override
        public void printStruct(String preStr){
            System.out.println(preStr+"-"+name);
        }
    }
    

    我们通过客户端来测试一下:

    public static void main(String[] args) {
    
    	//定义所有的组合对象
    	Component root = new Composite("服装");
    	Component c1 = new Composite("女装");
    	Component c2 = new Composite("男装");
    
    	//定义所有的叶子对象
    	Component leaf1 = new Leaf("裙子");
    	Component leaf2 = new Leaf("旗袍");
    	Component leaf3 = new Leaf("衬衣");
    	Component leaf4 = new Leaf("夹克");
    
    	//按照树的结构来组合组合对象和叶子对象
    	root.addChild(c1);
    	root.addChild(c2);
    
    	c1.addChild(leaf1);
    	c1.addChild(leaf2);
    
    	c2.addChild(leaf3);
    	c2.addChild(leaf4);
    
    	// 打印输出整棵树结构
    	root.printStruct("");
    }
    

    运行完后,会得到同样的输出。

    这样一来,在组合对象中保存时不需要将组合对象和叶子节点对象分开保存,并且在客户端中使用时,也不需要区分操作,都操作组件对象就可以了。

    安全性组合模式:
    上边实现的方式是透明性方式,其实安全性方式跟透明性方式区别很小,透明性组合模式把操作子组件的方法定义在了Component中,这样客户端只需要面对Component,而不需要关心子组件的具体类型。这种方式是以安全性为代价的,假如客户在操作的时候,不清楚叶子节点中没有重写addChild方法,那么通过叶子节点调用了这个方法,就会抛出异常。

    想要将上边透明性组合模式改为安全性组合模式,只需要在两处做简单修改即可。

    第一个地方,去掉抽象组件类中的addChild方法(Composite组合类中的方法去掉@Override注解)

    /**
     * 抽象的组件对象,为组合中的对象声明接口,实现接口的缺省行为
     */
    public abstract class Component {
        /**
         * 输出组件自身的名称
         */
        public abstract void printStruct(String preStr);
    }
    

    第二个地方,在客户端创建使用时,还是需要区分创建组合类和叶子节点类

    //定义所有的组合对象
            Composite root = new Composite("服装");
            Composite c1 = new Composite("女装");
            Composite c2 = new Composite("男装");
    
            //定义所有的叶子对象
            Leaf leaf1 = new Leaf("裙子");
            Leaf leaf2 = new Leaf("旗袍");
            Leaf leaf3 = new Leaf("衬衣");
            Leaf leaf4 = new Leaf("夹克");
    
            //按照树的结构来组合组合对象和叶子对象
            root.addChild(c1);
            root.addChild(c2);
    
            c1.addChild(leaf1);
            c1.addChild(leaf2);
    
            c2.addChild(leaf3);
            c2.addChild(leaf4);
    
            // 打印输出整棵树结构
            root.printStruct("");
    

    运行一下,会得到同样的输出。

    透明性模式和安全性模式的选择
    对于组合模式而言,在选择上会更倾向于透明性。毕竟组合模式的初衷就是要让用户对组合对象和叶子对象的使用具有一致性。

    四、组合模式的优缺点

    优点:

    • 统一了组合对象和叶子节点对象。
    • 简化了客户端调用。 客户端在使用的时候,不需要区分各个组件。
    • 更容易扩展。 新增一个Component节点的子类时,很容易与已有结构一起工作,客户端不需要跟着做改变。

    缺点:

    • 很难限制组合中的组件类型。 在需要检测组件类型的时候,无法依靠编译器的类型约束来完成,必须在运行期间动态检测。

    五、组合模式的应用场景及案例

    • 维护和展示"部分-整体"结构的场景,如树形菜单、文件目录、组织架构等。

    六、注意事项

    组合模式中,如果不是特殊设计,一定要避免出现环状引用的情形。如A包含B,B包含C,C包含A,这样就构成了一个环状引用。环状引用容易出现死循环,或者导致逻辑被重复执行多次的情形。
    检测环状引用,可以通过记录和拼接路径检测,亦或是其它方式,这里就不做拓展了。感兴趣的小伙伴可以自己了解下。

    展开全文
  • 设计模式之--组合模式以及使用场景说明(C++实现)。
            组合模式是一个常用的模式,关于定义和类图网上很多。这里就不重复了。
            本文主要说明下主要的使用场景。希望能够通过通俗易懂的方式把组合模式记住。
            组合模式非常适合有递归迭代性质的结构或者逻辑。即结构上存在树型或者包含关系,逻辑上"整体"和"部分"的行为和状态的对外表现是一致的,或者是类似的。下面通过例子来说明吧。

             比如目录和文件,目录可以只包含子目录,也可以只包含文件,当然可以同时包含子目录和文件。而子目录又可以包含子目录或者文件。

             目录和文件都可以删除或者打开。打开目录其实就是打开目录的全部子目录和该目录下的文件。删除文件就是删除一个文件,删除目录是删除全部子目录和全部文件。   

             再比如公司,部门和员工。公司可以只包含员工,也可以只包含部门,也可以包含子公司,当然可以同时包含员工和部门和子公司。而子公司又可以包含子公司或者部门。

            公司和部门都可以组织开会。全公司开会其实就是组织各个子公司开会。各个子公司开会其实就是各种子公司的全部部门和员工开会。各个部门开会其实就是该部门的全部员工开会。

             组合模式就是抽象出相同的逻辑或者状态,使得访问"整体"和“部分”达到高度统一。

             下面是C++的一个简单例子。我们可以把Open函数理解为“打开文件或者打印目录”,那么应该会很好理解。

              

    /* 对"整体"和"部分"的统一接口抽象 */
    class Component
    {
    public:
    	Component(string name)
    	{
    		m_strName = name;
    	}
    
    	virtual ~Component(){};
    	
    	virtual void Add(Component* pComponent) = 0;
    	virtual void Del(Component* pComponent) = 0;
    	virtual void Open() = 0; 
    	
    	string m_strName;
    };
    
    /* 抽象细粒度不可再分的"部分",比如文件,员工等 */
    class Leaf : public Component
    {
    public:
    	Leaf(string name) : Component(name)
    	{
    	}
    
    	virtual ~Leaf()
    	{
    		printf("Leaf: \"%s\" Destructor.\r\n",m_strName.c_str());
    	};
    
    	virtual void Add(Component* pComponent)
    	{
    		printf("I'm a leaf.Don't support Add.\r\n");
    	}
    	virtual void Del(Component* pComponent)
    	{
    		printf("I'm a leaf.Don't support Del.\r\n");
    	}
    	virtual void Open()
    	{
    		printf("Leaf: \"%s\" Open.\r\n",m_strName.c_str());
    	}
    };
    
    /* 具体的"子结构"或者"整体",比如目录,公司,子公司等等 */
    class Composite : public Component
    {
    public:
    	Composite(string name) : Component(name)
    	{
    
    	}
    
    	/* 需要销毁全部子结构 */
    	virtual ~Composite()
    	{
    		printf("Composite: \"%s\" Destructor.\r\n",m_strName.c_str());
    		for (vector<Component *>::iterator it = m_vComponent.begin(); it != m_vComponent.end(); ++it)
    		{
    			delete (*it);
    		}
    	};
    
    	virtual void Add(Component* pComponent)
    	{
    		m_vComponent.push_back(pComponent);
    	}
    	virtual void Del(Component* pComponent)
    	{
    		for (vector<Component *>::iterator it = m_vComponent.begin(); it != m_vComponent.end(); ++it)
    		{
    			if (*it == pComponent)
    			{
    				delete *it;
    				*it = NULL;
    
    				m_vComponent.erase(it);
    				break;
    			}
    		}
    	}
    	virtual void Open()
    	{
    		printf("Composite: \"%s\" Open.\r\n",m_strName.c_str());
    		for (vector<Component *>::iterator it = m_vComponent.begin(); it != m_vComponent.end(); ++it)
    		{
    			(*it)->Open(); //统一调用各个子对象的Open方法
    		}
    	}
    
    	vector<Component*> m_vComponent;
    };
    
    void TestComposite()
    {
    	Component* root = new Composite("Root");
    
    	root->Add(new Leaf("Root Leaf_A"));
    	root->Add(new Leaf("Root Leaf_B"));
    
    	Component* compon1 = new Composite("Root Sub_A");
    	Component* compon2 = new Composite("Root Sub_B");
    
    	compon1->Add(new Leaf("Root Sub_A Leaf_A"));
    	compon1->Add(new Leaf("Root Sub_A Leaf_B"));
    
    	compon2->Add(new Leaf("Root Sub_B Leaf_A"));
    	compon2->Add(new Leaf("Root Sub_B Leaf_B"));
    
    	root->Add(compon1);
    	root->Add(compon2);
    
    	Component* leaf3 = new Leaf("Root Sub_A Leaf_CC");
    
    	compon1->Add(leaf3);
    
    	printf("\r\nOpen Root:\r\n");
    	root->Open();//打开Root,打开Leaf,打开Composite对外展现的都是一样的方式
    
    	printf("\r\nOpen compon1:\r\n");
    	compon1->Open();
    
    	printf("\r\nOpen compon2:\r\n");
    	compon2->Open();
    
    	printf("\r\nOpen leaf3:\r\n");
    	leaf3->Open();
    
    	printf("\r\nDelete Root:\r\n");
    	delete root; //销毁root,会一直递归销毁全部子结构
    }
    

    展开全文
  • 组合模式 定义:把部分和整体的关系用树形结构表示,从而使...使用时机:当系统要描述的对象是树形结构,并且要在客户端忽略掉子对象和父对象的区别,就需要使用组合模式。 小巩需要统计各个子机构的总人数,如果使用

    组合模式

    定义:把部分和整体的关系用树形结构表示,从而使客户端能把一个一个的部分对象和由它们组合起来的整体对象采用同样方式处理。它也是继承的一个替代方案。

    优点:组合模式能提供比继承关系更灵活的功能,并且可以灵活组合子对象和父对象的关系从而使客户端的调用简单,客户端可以一致地使用组合结构或其中单个对象,简化了客户端代码。

    缺点:很难限制向集合中添加的新组件的类型。

    使用时机:当系统要描述的对象是树形结构,并且要在客户端忽略掉子对象和父对象的区别,就需要使用组合模式。

    小巩需要统计各个子机构的总人数,如果使用多重继承,为每个子机构创建一个对象,每个级别的子机构为一个类,都继承于父类的机构类,这样代码将会变成很长。
    下面使用组合模式
    先定义一个抽象的组织机构类

    
    public interface Organ {
        int personCount();
    }
    
    //子机构1
    public class LeafDepartment1 implements Organ {
        public int personCount() {
            return 100;
        }
    }
    
    //子机构2
    public class LeafDepartment2 implements Organ {
        public int personCount() {
            return 100;
        }
    }
    //抽象的父组织机构类
    import java.util.List;
    import java.util.ArrayList;
    
    public class CompositeDepartment implements Organ {
        private List list = new ArrayList();
    
        public int personCount() {
            int count = 0;
            for (int i = 0; i < list.size(); i++) {
                Organ organ = (Organ)list.get(i);
                count += organ.personCount();
            }
            return count;
        }
    
        public void add(Organ organ) {
    		list.add(organ);
        }
    
        public void remove(Organ organ) {
            list.remove(organ);
        }
    
        public Organ getChild(int i) {
            return (Organ)list.get(i);
        }
    }
    
    

    下面是客户端的示意代码

    public class Client {
        public static void main(String[] argv) {
            CompositeDepartment organ = new CompositeDepartment();
    		organ.add(new LeafDepartment1());
    		organ.add(new LeafDepartment2());
             System.out.println("该机构人数为:"+ organ.personCount());
    	
        }
    }
    
    展开全文
  • Java设计模式之《组合模式》及应用场景 出处地址http://www.cnblogs.com/V1haoge/p/6489827.html  组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是终点对象(不再包含别的对象),也有可能...

    Java设计模式之《组合模式》及应用场景

    出处地址http://www.cnblogs.com/V1haoge/p/6489827.html

      组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是终点对象(不再包含别的对象),也有可能是非终点对象(其内部还包含其他对象,或叫组对象),我们将对象称为节点,即一个根节点包含许多子节点,这些子节点有的不再包含子节点,而有的仍然包含子节点,以此类推。很明显,这是树形结构,终结点叫叶子节点,非终节点(组节点)叫树枝节点,第一个节点叫根节点。同时也类似于文件目录的结构形式:文件可称之为终节点,目录可称之为非终节点(组节点)。

    1、我们首先来看一个目录结构的普通实现:

    目录节点:Noder

    复制代码
     1 import java.util.ArrayList;
     2 import java.util.List;
     3 /**
     4  * 目录节点
     5  * 包含:
     6  *         1、目录名
     7  *         2、下级文件列表
     8  *         3、下级目录列表
     9  *         4、新增文件方法
    10  *         5、新增目录方法
    11  *         6、显示下级内容方法
    12  */
    13 public class Noder {
    14     String nodeName;//目录名
    15     //通过构造器为目录命名
    16     public Noder(String nodeName){
    17         this.nodeName = nodeName;
    18     }
    19     List<Noder> nodeList = new ArrayList<Noder>();//目录的下级目录列表
    20     List<Filer> fileList = new ArrayList<Filer>();//目录的下级文件列表
    21     //新增下级目录
    22     public void addNoder(Noder noder){
    23         nodeList.add(noder);
    24     }
    25     //新增文件
    26     public void addFiler(Filer filer){
    27         fileList.add(filer);
    28     }
    29     //显示下级目录及文件
    30     public void display(){
    31         for(Noder noder:nodeList){
    32             System.out.println(noder.nodeName);
    33             noder.display();//递归显示目录列表
    34         }
    35         for(Filer filer:fileList){
    36             filer.display();
    37         }
    38     }
    39 }
    复制代码

    文件节点:Filer

    复制代码
     1 /**
     2  * 文件节点
     3  * 文件节点是终节点,无下级节点
     4  * 包含:
     5  *         1、文件名
     6  *         2、文件显示方法
     7  */
     8 public class Filer {
     9     String fileName;//文件名
    10     public Filer(String fileName){
    11         this.fileName = fileName;
    12     }
    13     //文件显示方法
    14     public void display(){
    15         System.out.println(fileName);
    16     }
    17 }
    复制代码

    测试类:Clienter

    复制代码
     1 import java.io.File;
     2 
     3 public class Clienter {
     4     public static void createTree(Noder node){
     5         File file = new File(node.nodeName);
     6         File[] f = file.listFiles();
     7         for(File fi : f){
     8             if(fi.isFile()){
     9                 Filer filer = new Filer(fi.getAbsolutePath());
    10                 node.addFiler(filer);
    11             }
    12             if(fi.isDirectory()){
    13                 Noder noder = new Noder(fi.getAbsolutePath());
    14                 node.addNoder(noder);
    15                 createTree(noder);//使用递归生成树结构
    16             }
    17         }
    18     }
    19     public static void main(String[] args) {
    20         Noder noder = new Noder("E://ceshi");
    21         createTree(noder);//创建目录树形结构
    22         noder.display();//显示目录及文件
    23     }
    24 }
    复制代码

    运行结果:

    E:\ceshi\目录1
    E:\ceshi\目录1\目录3
    E:\ceshi\目录1\文件2.txt
    E:\ceshi\目录2
    E:\ceshi\目录2\文件3.txt
    E:\ceshi\文件1.txt

    2、组合模式

      从上面的代码中可以看出,我们分别定义了文件节点对象与目录节点对象,这是因为文件与目录之间的操作不同,文件没有下级节点,而目录可以有下级节点,但是我们能不能这么想:既然文件与目录都是可以作为一个节点的下级节点而存在,那么我们可不可以将二者抽象为一类对象,虽然二者的操作不同,但是我们可以在实现类的方法实现中具体定义,比如文件没有新增下级节点的方法,我们就可以在文件的这个方法中抛出一个异常,不做具体实现,而在目录中则具体实现新增操作。显示操作二者都有,可以各自实现。而且由于我们将文件与目录抽象为一个类型,那么结合多态我们可以进行如下实现:

    抽象类:Node

    复制代码
     1 /**
     2  * 将文件与目录统一看作是一类节点,做一个抽象类来定义这种节点,然后以其实现类来区分文件与目录,在实现类中分别定义各自的具体实现内容
     3  */
     4 public abstract class Node {
     5     protected String name;//名称
     6     //构造器赋名
     7     public Node(String name){
     8         this.name = name;
     9     }
    10     //新增节点:文件节点无此方法,目录节点重写此方法
    11     public void addNode(Node node) throws Exception{
    12         throw new Exception("Invalid exception");
    13     }
    14     //显示节点:文件与目录均实现此方法
    15     abstract void display();
    16 }
    复制代码

    文件实现类:Filter

    复制代码
     1 /**
     2  * 实现文件节点
     3  */
     4 public class Filer extends Node {
     5     //通过构造器为文件节点命名
     6     public Filer(String name) {
     7         super(name);
     8     }
     9     //显示文件节点
    10     @Override
    11     public void display() {
    12         System.out.println(name);
    13     }
    14 }
    复制代码

    目录实现类:Noder

    复制代码
     1 import java.util.*;
     2 /**
     3  * 实现目录节点
     4  */
     5 public class Noder extends Node {
     6     List<Node> nodeList = new ArrayList<Node>();//内部节点列表(包括文件和下级目录)
     7     //通过构造器为当前目录节点赋名
     8     public Noder(String name) {
     9         super(name);
    10     }
    11     //新增节点
    12     public void addNode(Node node) throws Exception{
    13         nodeList.add(node);
    14     }
    15     //递归循环显示下级节点
    16     @Override
    17     void display() {
    18         System.out.println(name);
    19         for(Node node:nodeList){
    20             node.display();
    21         }
    22     }
    23 }
    复制代码

    测试类:Clienter

    复制代码
     1 import java.io.File;
     2 
     3 public class Clienter {
     4     public static void createTree(Node node) throws Exception{
     5         File file = new File(node.name);
     6         File[] f = file.listFiles();
     7         for(File fi : f){
     8             if(fi.isFile()){
     9                 Filer filer = new Filer(fi.getAbsolutePath());
    10                 node.addNode(filer);
    11             }
    12             if(fi.isDirectory()){
    13                 Noder noder = new Noder(fi.getAbsolutePath());
    14                 node.addNode(noder);
    15                 createTree(noder);//使用递归生成树结构
    16             }
    17         }
    18     }
    19     public static void main(String[] args) {
    20         Node noder = new Noder("E://ceshi");
    21         try {
    22             createTree(noder);
    23         } catch (Exception e) {
    24             e.printStackTrace();
    25         }
    26         noder.display();
    27     }
    28 }
    复制代码
    复制代码
    E://ceshi
    E:\ceshi\文件1.txt
    E:\ceshi\目录1
    E:\ceshi\目录1\文件2.txt
    E:\ceshi\目录1\目录3
    E:\ceshi\目录2
    E:\ceshi\目录2\文件3.txt
    复制代码

      从上述实现中可以看出:所谓组合模式,其实说的是对象包含对象的问题,通过组合的方式(在对象内部引用对象)来进行布局,我认为这种组合是区别于继承的,而另一层含义是指树形结构子节点的抽象(将叶子节点与数枝节点抽象为子节点),区别于普通的分别定义叶子节点与数枝节点的方式。

    3、组合模式应用场景

      这种组合模式正是应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。比如:文件目录显示,多及目录呈现等树形结构数据的操作。

    展开全文
  • 一、组合模式简介、 二、组合模式适用场景、 三、组合模式优缺点、 四、组合模式和访问者模式、 五、组合模式代码示例、 1、书籍和目录的抽象父类、 2、书籍类、 3、目录类、 4、测试类、
  • 组合模式概括 定义:将对象组合成树形结构以表示“部分-整体”的层次结构 作用:使客户端对单个对象和组合对象保持一致的处理方式 使用场景:1.希望客户端可以忽略组合对象与单个对象的差异时 2.处理一个树形结构...
  • 组合模式:企业管理系统 桥接模式:新增辅助进程,中间件 享元模式:读写单实例场景 行为型模式 策略模式:营销策略,多态 模板方法模式:虚基类 观察者模式:心跳订阅,数据看板,ui控件监听 状态模式:游
  • 一)故事 ...六)使用场景 1)维护和展示部分一整体关系的场景,如树形菜单、文件和文件夹管理。 2)从一个整体中能够独立出部分模块或功能的场景。 七)注意事项 八)扩展 九)总结
  • 一句话概括: 对象A里面又包含List<A>的一个树状结构。...组合模式使得用户单个对象和组合对象的使用具有一致性。 参与角色: 1)组合类 (包括该类自己的属性以及一个元素为类本身的Li...
  • 由于在软件开发中存在大量的树形结构,因此组合模式是一种使用频率较高的结构型设计模式,在XML解析、组织结构树处理、文件系统设计等领域,组合模式都得到了广泛应用组合模式的分类: ①透明组合模式 透明...
  • 应用场景:一个无状态的类使用单例模式节省内存资源。 二、Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。 应用场景:一系列相互依赖的对象有不同的具体...
  • 场景:医院是由多个科室组成的,此时我们可以定义不同科室的类,这样医院的类我们可以直接使用各个不同科室的类进行组合即可;2.什么时候使用类的继承?当类之间有很大相似的功能,我们可以提取这些共通的功能做成...
  • 主要介绍了javascript 设计模式之组合模式原理与应用,结合实例形式分析了javascript组合模式基本概念、原理、应用场景及操作注意事项,需要的朋友可以参考下
  • 主要介绍了javascript设计模式 – 组合模式,结合实例形式分析了javascript组合模式相关概念、原理、应用场景及相关使用注意事项,需要的朋友可以参考下
  • 桥梁模式应用场景

    千次阅读 2017-12-04 16:44:00
    在环境交互中使用的都是抽象类,并且把平台实现隐藏,在应用程序中new平台的方式也可以根据情况用Singleton模式或者Abstract Factory模式等实现。   结构(Structure) 其中imp的地方就是一个组合。...
  • 应用场景 1、系统只需要一个对象; 2、客户调用类的单个实例只允许使用一个公共访问点,除了该访问点,不能通过其他途径访问该实例。 适配器模式 应用场景 1、系统需要使用一些现有的类,而这些类的接口不符合系统的...
  • 建造者模式应用场景

    千次阅读 2018-12-06 14:53:52
    建造者模式: 建造者模式,又称构建者模式,将一部负责对象的构建分为许多小对象的构建,最后在整合构建的模式。  构建者模式一般用在构建流程或者组成部件固定的场合,将这些部件分开构建成为组件对象,再将...
  • 组合模式

    2019-12-14 20:52:37
    组合模式摘要一、组合模式二、组合模式...  本文通过简洁的模式描述,应用场景的详细代码实现,以及匹配的UML,详解介绍了组合模式的原理及应用。本文可帮助读者快速掌握组合模式,以便工作学习中使用组合模式。 ...
  • 设计模式主要分三个类型...应用场景:一个无状态的类使用单例模式节省内存资源。   二、Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。   应用场景:一系列
  • 组合模式将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。 模式图: 适用场景: 你想表示对象的部分-整体层次结构。 你希望用户忽略组合...
  • 各种设计模式应用场景

    千次阅读 2018-05-04 18:42:05
    创建型模式简单工厂模式(simpleFactory)发音:['simpl] ['fækt(ə)rɪ] 定义: 提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口,抽象类,也可以是具体的类. 1.抽象工厂(Abstract...
  • Java--反射机制原理、几种Class获取方式应用场景

    万次阅读 多人点赞 2021-08-22 11:26:31
    3.1 应用场景3.2 应用场景实现3.2.1 简单工厂模式3.2.2 简单工厂模式优化(应用场景)3.2.1 代理模式中动态代理(应用场景) 学习背景 学习Java的小伙伴,可能听过Java反射机制,但是熟悉又有点陌生,本文主要是通过...
  • 设计模式 | 组合模式及典型应用

    千次阅读 多人点赞 2018-10-05 17:36:55
    源码分析组合模式的典型应用 java.awt中的组合模式 Java集合中的组合模式 Mybatis SqlNode中的组合模式 更多内容可访问我的个人博客:http://laijianfeng.org 推荐阅读 设计模式 | 简单工厂模式及典型应用 设计...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 281,974
精华内容 112,789
关键字:

组合模式的应用场景