设计模式之笔记--组合模式(Composite)
组合模式(Composite)
定义
组合模式(Composite),将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式有两种形式:透明方式的组合模式和安全方式的组合模式。
类图
描述
Component:它可以是接口或抽象类,为叶子和容器对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象类中定义了访问及管理它的子类的方法,如增加子对象、删除子对象、获取子对象等;
Leaf:表示叶子节点对象,叶子节点没有子节点,它实现了在抽象类中定义的行为。对于那些访问及管理子类的方法,可以通过异常等方式进行处理,即在叶子对象中实现子类管理和访问方法时需要提供异常处理或错误提示;
Composite:表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象类中定义的行为,包括那些访问及管理子类的方法,在其业务方法中可以递归调用其子节点的业务方法。
应用场景
树枝有多个叶子和子树枝组成,而子树枝又可以包含多个叶子和子树枝;叶子没有子叶子和子树枝。
一、透明方式的组合模式
类图
描述
透明组合模式中,在抽象类Component中声明了所有用于管理成员对象的方法,如Add()、Remove()以及GetChild()等方法,这样做的好处是确保所有的构件类都有相同的接口。在客户端看来,叶子对象与容器对象所提供的方法是一致的,客户端可以相同地对待所有的对象。
/// <summary>
/// 叶子和树枝的声明接口
/// </summary>
public abstract class Component
{
private string name;
/// <summary>
/// 节点名称
/// </summary>
public string Name
{
get { return name; }
} private int depth;
/// <summary>
/// 节点深度
/// </summary>
public int Depth
{
get { return depth; }
} public Component(string name, int depth)
{
this.name = name;
this.depth = depth;
} #region 管理成员对象的方法
/// <summary>
/// 添加子节点
/// </summary>
/// <param name="component"></param>
public abstract void Add(Component component); /// <summary>
/// 移除子节点
/// </summary>
/// <param name="component"></param>
public abstract void Remove(Component component); /// <summary>
/// 获取子节点
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public abstract Component GetChild(int i);
#endregion /// <summary>
/// 子节点操作
/// </summary>
public abstract void Display(Component component);
} /// <summary>
/// 树枝类
/// </summary>
public class Composite : Component
{
/// <summary>
/// 子节点集合
/// </summary>
private List<Component> children = new List<Component>(); public Composite(string name, int depth)
: base(name, depth)
{ } public override void Add(Component component)
{
this.children.Add(component);
} public override void Remove(Component component)
{
this.children.Remove(component);
} public override Component GetChild(int i)
{
if (i >= && i < this.children.Count)
{
return this.children[i];
}
else
{
return null;
}
} public override void Display(Component component)
{
foreach (Component c in ((Composite)component).children)
{
if (c is Composite)
{
Console.WriteLine(c.Name.PadLeft(c.Depth + c.Name.Length, '-'));
Display(c);
}
else
{
c.Display(c);
}
}
}
} /// <summary>
/// 树叶类
/// </summary>
public class Leaf : Component
{
public Leaf(string name, int depth)
: base(name, depth)
{ } public override void Add(Component component)
{
throw new System.NotImplementedException();
} public override void Remove(Component component)
{
throw new System.NotImplementedException();
} public override Component GetChild(int i)
{
throw new System.NotImplementedException();
} public override void Display(Component component)
{
Console.WriteLine(component.Name.PadLeft(component.Depth + component.Name.Length, '-'));
}
}
二、安全方式的组合模式
类图
描述
安全组合模式中,在抽象类Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。这种做法是安全的,因为根本不向叶子对象提供这些管理成员对象的方法,对于叶子对象,客户端不可能调用到这些方法.
/// <summary>
/// 叶子和树枝的声明接口
/// </summary>
public abstract class Component
{
private string name;
/// <summary>
/// 节点名称
/// </summary>
public string Name
{
get { return name; }
} private int depth;
/// <summary>
/// 节点深度
/// </summary>
public int Depth
{
get { return depth; }
} public Component(string name, int depth)
{
this.name = name;
this.depth = depth;
} /// <summary>
/// 子节点操作
/// </summary>
public abstract void Display(Component component);
} /// <summary>
/// 树枝类
/// </summary>
public class Composite : Component
{
/// <summary>
/// 子节点集合
/// </summary>
private List<Component> children = new List<Component>(); public Composite(string name, int depth)
: base(name, depth)
{ } #region 管理成员对象的方法
/// <summary>
/// 添加子节点
/// </summary>
/// <param name="component"></param>
public void Add(Component component)
{
this.children.Add(component);
} /// <summary>
/// 移除子节点
/// </summary>
/// <param name="component"></param>
public void Remove(Component component)
{
this.children.Remove(component);
} /// <summary>
/// 获取子节点
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public Component GetChild(int i)
{
if (i >= && i < this.children.Count)
{
return this.children[i];
}
else
{
return null;
}
}
#endregion public override void Display(Component component)
{
foreach (Component c in ((Composite)component).children)
{
if (c is Composite)
{
Console.WriteLine(c.Name.PadLeft(c.Depth + c.Name.Length, '-'));
Display(c);
}
else
{
c.Display(c);
}
}
}
} /// <summary>
/// 树叶类
/// </summary>
public class Leaf : Component
{
public Leaf(string name, int depth)
: base(name, depth)
{ } public override void Display(Component component)
{
Console.WriteLine(component.Name.PadLeft(component.Depth + component.Name.Length, '-'));
}
}
透明和安全方式组合模式的区别在于是否在抽象类Component中定义子对象的管理行为。
设计模式之笔记--组合模式(Composite)的更多相关文章
- 设计模式系列之组合模式(Composite Pattern)——树形结构的处理
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 设计模式 笔记 组合模式 Composite
//---------------------------15/04/16---------------------------- //Composite 组合模式----对象结构型模式 /* 1:意 ...
- 设计模式学习心得<组合模式 Composite>
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...
- 学习笔记——组合模式Composite
组合模式,典型的层次结构. 与装饰器类图相似. 区别在于:装饰器模式是为了在接口中增加方法,而组合模式在于层次元素的叠加. ConcreteComponent就是中间结点,可以包含更多的Concret ...
- 《JAVA设计模式》之组合模式(Composite)
在阎宏博士的<JAVA与模式>一书中开头是这样描述合成(Composite)模式的: 合成模式属于对象的结构模式,有时又叫做“部分——整体”模式.合成模式将对象组织到树结构中,可以用来描述 ...
- 设计模式之:组合模式(Composite)
支持原创:http://blog.csdn.net/hguisu/article/details/7530783 设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构 ...
- 设计模式(七)组合模式Composite(结构型)
设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 ...
- 乐在其中设计模式(C#) - 组合模式(Composite Pattern)
原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...
- python 设计模式之组合模式Composite Pattern
#引入一 文件夹对我们来说很熟悉,文件夹里面可以包含文件夹,也可以包含文件. 那么文件夹是个容器,文件夹里面的文件夹也是个容器,文件夹里面的文件是对象. 这是一个树形结构 咱们生活工作中常用的一种结构 ...
随机推荐
- [洛谷P3950]部落冲突
题目大意:给你一棵树,有$3$个操作: $Q\;p\;q:$询问$p,q$是否连通 $C\;p\;q:$把$p->q$这条边割断 $U\;x:$恢复第$x$次操作二 题解:可以在割断时把这条边赋 ...
- cf 460 E. Congruence Equation 数学题
cf 460 E. Congruence Equation 数学题 题意: 给出一个x 计算<=x的满足下列的条件正整数n的个数 \(p是素数,2 ≤ p ≤ 10^{6} + 3, 1 ≤ a ...
- HDOJ(HDU).2044-2049 递推专题
HDOJ(HDU).2044-2049 递推专题 点我挑战题目 HDU.2044 题意分析 先考虑递推关系:从1到第n个格子的时候由多少种走法? 如图,当n为下方格子的时候,由于只能向右走,所以有2中 ...
- SRM13绵津见-终(扫描线+线段树/BIT)
题目大意:求对于每个i求有多少个合法的j以及j对于几个i是合法的,合法的定义:l[i]<=x[j]<=r[i],T[i]-y[i]<=t[j]<=T[i]+y[i]. 设a[i ...
- STL之二:vector容器用法详解
转载于:http://blog.csdn.net/longshengguoji/article/details/8507394 vector类称作向量类,它实现了动态数组,用于元素数量变化的对象数组. ...
- HDU 5645
DZY Loves Balls Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others ...
- TCP/UDP HTTP
TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据.关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:“我们在传输数据时,可以只 ...
- js的数据类型--数字
近期做一些项目的时候发现,自己的js基础还是不够扎实,再看一遍犀牛书,加深自己的理解和印象.所以从这篇文章开始,后面都是关于原生js的一些内容. 这篇文章,我们具体介绍一下js的数据类型其中一种. j ...
- linux查找进程id端口占用和杀死进程
linux 查找进程id端口占用和杀死进程 ps 命令用于查看当前正在运行的进程 辅助上grep 用于搜索匹配ps -ef | grep java ps ax : 显示当前系统进程的列表 ps aux ...
- 转【jenkins插件】
开源版本的Jenkins 具有三大能力:Master-Slave的分布式构建调度能力.Pipeline编排能力.强大的开源生态(插件)能力. 2017年4月,Jenkins创始人KK(Kohsuke ...