【设计模式系列】--组合模式

在前面的博文中,小编介绍了三个工厂模式,三世同堂,各司其职,各有千秋,今天我们继续来学习设计模式的相关知识,今天这篇博文,我们继续来学习设计模式的相关知识,今天这篇博文小编主要和小伙伴们来学习组合模式。小编会从什么是组合模式、组合模式的结构图、组合模式的角色和职责以及结合相关的deom来进行讲解。

一、什么是组合模式

组合模式,英文名字叫Composite,是结构型的设计模式,通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。

二、组合模式的结构图

三、组合模式的角色和职责

Component(树形结构的节点抽象)

为所有的对象定义统一的接口(公共属性,行为等的定义)

提供管理子节点对象的接口方法

[可选]提供管理父节点对象的接口方法

Leaf(树形结构的叶结点)

Component的实现子类

Composite(树形结构的枝节点)

Component的实现子类

接着,小编举一个简单的例子,小伙伴们看下面这幅图

        

上面两幅图片我们可以看作是一个文件结构,对于这样的结构我们称之为树形结构,在程杰老师的大话设计模式一书中,我们知道可以通过调用某个方法来遍历整棵树,当我们找到某个叶子节点后,就可以对叶子节点进行相关的操作,我们可以将这棵树理解成一个大容器,容器里面包含很多的成员对象,这些成员对象既可以是容器对象也可以是叶子对象,但是由于容器对象和叶子对象在功能上面的区别,使得我们在使用的过程中要区分容器对象和叶子对象,但是这样会给用户带来不必要的麻烦,对于客户而言,始终希望能够一致的对待容器对象和叶子对象,这就是组合模式的设计动机,组合模式定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一直的处理。接着小编通过一个简单的demo讲解组合模式如何在项目中使用,希望可以帮助到有需要的小伙伴,不足之处,还请小伙伴多多指教`(*∩_∩*)′。

四、组合模式小demo

新建项目Composite项目,新建接口IFile也就是文件节点的抽象相当于设计模式结构图中的Component,编写相关代码,如下所示:

import java.util.List;

/**
 * 文件节点抽象(是文件和目录的父类)
 * @author Flower
 *
 */
public interface IFile {
	//显示文件或文件夹的名称
	public void display();
	//添加
	public boolean add(IFile file);
	//移除
	public boolean remove(IFile file);
	//获得子节点
	public List<IFile> geChild();

}

接着新建File,相当于结构图中的Leaf,具体代码如下所示:

import java.util.List;

public class File implements IFile {

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

	@Override
	public void display() {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean add(IFile file) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean remove(IFile file) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public List<IFile> geChild() {
		// TODO Auto-generated method stub
		return null;
	}

}

新建类Folder,相当于结构图中的Composite,编写相关的代码部分,如下所示:

import java.util.ArrayList;
import java.util.List;

public class Folder implements IFile {
	private String name;
	private List<IFile> children;

	public Folder(String name){
		this.name = name;
		children= new ArrayList<IFile>();
	}

	@Override
	public void display() {
		System.out.println(name);

	}

	@Override
	public boolean add(IFile file) {
		return children.add(file);
	}

	@Override
	public boolean remove(IFile file) {
		return children.remove(file);
	}

	@Override
	public List<IFile> geChild() {
		return children;
	}

}

编写客户端的代码,新建类MainClass,具体代码如下所示:

import java.util.List;

public class MainClass {
	 public static void main(String[] args){
		 //C盘
		 Folder rootFolder = new Folder("C:");
		 //beifeng目录
		 Folder beifengFolder = new Folder("beifeng");
		 //beifeng.txt文件
		 File beifengFile = new File("beifeng.txt");

		 rootFolder.add(beifengFile);
		 rootFolder.remove(beifengFile);

		 displayTree(rootFolder);

	 }

	private static void displayTree(IFile rootFolder) {
		rootFolder.display();
		List<IFile> children = rootFolder.geChild();

		//遍历子数
		for(IFile file:children){
			if(file instanceof File){
				file.display();
			}else{
				displayTree(file);
			}

		}
	}

}

运行,如下所示:

小伙伴们可能觉得这样看起来层次结构不是很清晰,我们来完善一下我们的MainClass部分,如下所示:

import java.util.List;

public class MainClass {
	 public static void main(String[] args){
		 //C盘
		 Folder rootFolder = new Folder("C:");
		 //beifeng目录
		 Folder beifengFolder = new Folder("beifeng");
		 //beifeng.txt文件
		 File beifengFile = new File("beifeng.txt");

		 rootFolder.add(beifengFolder);
		 rootFolder.add(beifengFile);

		 //ibeifeng目录
		 Folder ibeifengFolder = new Folder("ibeifeng");
		 File ibeifengFile = new File("ibeifeng.txt");
		 beifengFolder.add(ibeifengFolder);
		 beifengFolder.add(ibeifengFile);

		 displayTree(rootFolder);

	 }

	private static void displayTree(IFile rootFolder) {
		//显示自身的名称
		rootFolder.display();
		//获得子树
		List<IFile> children = rootFolder.geChild();

		//遍历子数
		for(IFile file : children){
			if(file instanceof File){
				file.display();
			}else{
				displayTree(file);
			}

		}
	}

}

运行一下,效果如下所示:

这样层次结构就比较深了,接着我们加上层次结构,完善MainClass的代码部分,如下所示:

import java.util.List;

public class MainClass {
	 public static void main(String[] args){
		 //C盘
		 Folder rootFolder = new Folder("C:");
		 //beifeng目录
		 Folder beifengFolder = new Folder("beifeng");
		 //beifeng.txt文件
		 File beifengFile = new File("beifeng.txt");

		 rootFolder.add(beifengFolder);
		 rootFolder.add(beifengFile);

		 //ibeifeng目录
		 Folder ibeifengFolder = new Folder("ibeifeng");
		 File ibeifengFile = new File("ibeifeng.txt");
		 beifengFolder.add(ibeifengFolder);
		 beifengFolder.add(ibeifengFile);

		 displayTree(rootFolder,0);

	 }

	private static void displayTree(IFile rootFolder,int deep) {
		for(int i = 0;i<deep;i++){
			System.out.println("--");
		}
		//显示自身的名称
		rootFolder.display();
		//获得子树
		List<IFile> children = rootFolder.geChild();

		//遍历子数
		for(IFile file : children){
			if(file instanceof File){
				for(int i =0;i<deep;i++){
					System.out.println("--");
				}
				file.display();
			}else{
				displayTree(file,deep+1);
			}

		}
	}

}

运行效果如下所示:

我们再来添加一个,完善代码,如下所示:

import java.util.List;

public class MainClass {
	 public static void main(String[] args){
		 //C盘
		 Folder rootFolder = new Folder("C:");
		 //beifeng目录
		 Folder beifengFolder = new Folder("beifeng");
		 //beifeng.txt文件
		 File beifengFile = new File("beifeng.txt");

		 rootFolder.add(beifengFolder);
		 rootFolder.add(beifengFile);

		 //ibeifeng目录
		 Folder ibeifengFolder = new Folder("ibeifeng");
		 File ibeifengFile = new File("ibeifeng.txt");
		 beifengFolder.add(ibeifengFolder);
		 beifengFolder.add(ibeifengFile);

		 Folder iibeifengFolder = new Folder("iibeifeng");
		 File iibeifengFile = new File("iibeifeng.txt");
		 ibeifengFolder.add(iibeifengFolder);
		 ibeifengFolder.add(iibeifengFile);

		 displayTree(rootFolder,0);

	 }

	private static void displayTree(IFile rootFolder,int deep) {
		for(int i = 0; i < deep; i++) {
			System.out.print("--");
		}
		//显示自身的名称
		rootFolder.display();
		//获得子树
		List<IFile> children = rootFolder.geChild();

		//遍历子数
		for(IFile file : children){
			if(file instanceof File){
				for(int i = 0; i <= deep; i++) {
					System.out.print("--");
				}
				file.display();
			}else{
				displayTree(file,deep+1);
			}

		}
	}

}

运行效果,如下所示:

小编寄语:该博文小编主要简单的介绍了设计模式中组合模式的相关知识,对于设计模式的演练,仅仅掌握理论知识是远远不够的,人类智慧的结晶还是需要我们在大量的实战中去慢慢体会,慢慢去锤炼,总的来说,组合模式呢,将对象组合成树形结构以表示部分和整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式。小伙伴们可以结合日常生活中的系统目录结构和网站导航结构帮助理解`(*∩_∩*)′。

时间: 2024-09-01 12:16:02

【设计模式系列】--组合模式的相关文章

C#设计模式(10)——组合模式(Composite Pattern)

原文:C#设计模式(10)--组合模式(Composite Pattern) 一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象和复合对象在功能上区别,导致在操作过程中必须区分简单对象和复合对象,这样就会导致客户调用带来不必要的麻烦,然而作为客户,它们希望能够始终一致地对待简单对象和复合对象.然而组合模式就是解决这样的问题.下面让我们看看组合模式是

乐在其中设计模式(C#) - 组合模式(Composite Pattern)

原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:webabcd 介绍 将对象组合成树形结构以表示"部分-整体"的层次结构.它使得客户对单个对象和复合对象的使用具有一致性. 示例 有一个Message实体类,使其单个对象和复合对象具有一致性. MessageModel using System;using System.Collections.Ge

【设计模式】—— 组合模式Composite

模式意图 使对象组合成树形的结构.使用户对单个对象和组合对象的使用具有一致性. 应用场景 1 表示对象的 部分-整体 层次结构 2 忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象. 模式结构 [安全的组合模式] 这种组合模式,叶子节点,也就是单个对象不具有对象的控制功能.仅仅有简单的业务操作. 1 package com.xingoo.composite.safe; 2 3 import java.util.ArrayList; 4 import java.util.List; 5

深入理解JavaScript系列(40):设计模式之组合模式详解_基础知识

介绍 组合模式(Composite)将对象组合成树形结构以表示"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 常见的场景有asp.net里的控件机制(即control里可以包含子control,可以递归操作.添加.删除子control),类似的还有DOM的机制,一个DOM节点可以包含子节点,不管是父节点还是子节点都有添加.删除.遍历子节点的通用功能.所以说组合模式的关键是要有一个抽象类,它既可以表示子元素,又可以表示父元素. 正文 举个例子,有家餐厅提

设计模式:组合模式(Composite)

将对象组合成属性结构以表示"部分-整体"的层次结构.组合使得用户和单个对象和组合对象的使用具有一致性. 组合模式设计的角色: 1. Component:是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为.声明一个接口用于访问和管理Component. 2. Leaf:在组合中表示叶子节点对象,叶子节点没有子节点. 3. Composite:定义树枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加和删除等. 举个简单例子(树枝和叶子) 1

C++设计模式之组合模式_C 语言

问题描述 上图,是一个公司的组织结构图,总部下面有多个子公司,同时总部也有各个部门,子公司下面有多个部门.如果对这样的公司开发一个OA系统,作为程序员的你,如何设计这个OA系统呢?先不说如何设计实现,接着往下看,看完了下面的内容,再回过头来想怎么设计这样的OA系统. 什么是组合模式? 在GOF的<设计模式:可复用面向对象软件的基础>一书中对组合模式是这样说的:将对象组合成树形结构以表示"部分-整体"的层次结构.组合(Composite)模式使得用户对单个对象和组合对象的使用

温故而知新:设计模式之组合模式(Composite)

场景: 如果想模拟windows的开始菜单,分析一下会发现里面的菜单项:有些有子菜单,有些则没有:因此大体可以将菜单类分为二类,设计代码如下:   /// <summary> /// 菜单的显示接口 /// </summary> public interface IMenu { void Show(); } /// <summary> /// 菜单基类 /// </summary> public class MenuBase { public string

php设计模式 Composite (组合模式)

复制代码 代码如下: <?php /** * 组合模式 * * 将对象组合成树形结构以表示"部分-整体"的层次结构,使得客户对单个对象和复合对象的使用具有一致性 */ abstract class MenuComponent { public function add($component){} public function remove($component){} public function getName(){} public function getUrl(){} p

iOS设计模式之组合模式

组合模式(Composite) 基本理解 整体和部分可以一直对待. 组合模式:将对象组合成树形结构以表示"部分--整体"的层次结构.组合模式使得用户对单个对象和组合独享的使用具有一致性. 透明方式和安全方式 透明方式:在Component(为组合中的对象声明接口)中声明所有用来管理子对象的方法 .这样实现该接口的子类都具有了该接口中的方法.这样的好处就是叶节点和枝节点对于外界没有区别,他们具有完全一致的行为接口.但问题也很明显,因为Leaf类本身不具备添加删除方法的功能,所以实现它是没

设计模式学习--组合模式,c++代码

下面是组合模式的UML类图:     <span style="font-family:Microsoft YaHei;font-size:18px;"><span style="font-family:Microsoft YaHei;font-size:18px;">//composite.h #ifndef _COMPOSITE_H_ #define _COMPOSITE_H_ #include <vector> using