组合模式(Composite Pattern)

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/403 访问。

组合模式属于结构型模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

角色:

1、抽象构件(Component )

它是所有叶子构件和容器构件的共同父类,里面声明了叶子构件和容器构件的所有方法;

2、叶子构件(Leaf)

在组合中表示叶子结点对象,叶子结点没有子结点,对于从父类中继承过来的容器构件的方法,由于它不能实现,可以抛出异常;

3、容器构件(Composite)

定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(Attach)和删除(Detach)等。

示例:

命名空间CompositePattern包含文件系统FileSystem基类充当抽象构件类,文件File类充当叶子构件,文件夹Folder类充当容器构件,文件无效操作FileInvalidException 类进行异常处理。本案例尝试通过一个简单的文件系统来向大家阐述组合模式在调用方使用一致性方面的表现。

namespace CompositePattern
public abstract class FileSystem {

    protected string _name = null;

    protected const char SPLIT_CHAR_FILE = ' ';

    protected const char SPLIT_CHAR_DIR = '▼';

    public FileSystem(string name) {
this._name = name;
} public abstract FileSystem Attach(FileSystem component); public abstract FileSystem Detach(FileSystem component); public abstract void Print(int depth = 0); }

抽象构件,文件系统FileSystem类。

public class File : FileSystem {

    public File(string name) : base(name) {

    }

    public override FileSystem Attach(FileSystem component) {
throw new FileInvalidException(
"You can not attach a component in a file!");
} public override FileSystem Detach(FileSystem component) {
throw new FileInvalidException(
"You can not detach a component from a file!");
} public override void Print(int depth = 0) {
Console.WriteLine(new string(SPLIT_CHAR_FILE, depth) + _name);
} }

叶子构件,文件File类。

public class Folder : FileSystem {

    private List<FileSystem> _childrens = null;

    public Folder(string name) : base(name) {
_childrens = new List<FileSystem>();
} public override FileSystem Attach(FileSystem component) {
_childrens.Add(component);
return this;
} public override FileSystem Detach(FileSystem component) {
_childrens.Remove(component);
return this;
} public override void Print(int depth = 0) {
Console.WriteLine(new string(SPLIT_CHAR_DIR, depth) + _name);
foreach (var component in _childrens) {
component.Print(depth + 1);
}
} }

容器构件,文件夹Folder类。

public class FileInvalidException : Exception {

    public FileInvalidException(string message) : base(message) {

    }

    public FileInvalidException(string message, Exception innerException)
: base(message, innerException) { } }

无效的文件操作FileInvalidException类进行简单的异常处理。

public class Program {

    public static void Main(string[] args) {
try {
var root = new Folder("Root"); var music = new Folder("My Music");
music.Attach(new File("Heal the world.mp3"))
.Attach(new File("When You Say Nothing At All.mp3"))
.Attach(new File("Long Long Way to Go.mp3"))
.Attach(new File("Beautiful In White.mp3")); var video = new Folder("My Video");
video.Attach(new File("The Shawshank Redemption.avi"))
.Attach(new File("Schindler's List.avi"))
.Attach(new File("Brave Heart.avi")); var png = new File("missing.png");
root.Attach(png)
.Detach(png)
.Detach(png); root.Attach(new File("readme.txt"))
.Attach(new File("index.html"))
.Attach(new File("file.cs"))
.Attach(music)
.Attach(video)
.Print(); png.Attach(new File("error.json")); }
catch (Exception ex) {
Console.WriteLine(ex.Message);
} Console.ReadKey();
} }

以上是调用方的代码,以下是这个案例的输出结果:

Root
readme.txt
index.html
file.cs
▼My Music
Heal the world.mp3
When You Say Nothing At All.mp3
Long Long Way to Go.mp3
Beautiful In White.mp3
▼My Video
The Shawshank Redemption.avi
Schindler's List.avi
Brave Heart.avi
You can not attach a component in a file!

优点:

该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/403 访问。

1、可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易;

2、客户端调用简单,客户端可以一致的使用组合结构或其中单个对象;

3、定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构;

4、更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。

缺点:

1、使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联;

2、增加新构件时可能会产生一些问题,很难对容器中的构件类型进行限制。

使用场景:

1、你想表示对象的部分-整体层次结构;

2、你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象;

3、对象的结构是动态的并且复杂程度不一样,但客户需要一致地处理它们。

C#设计模式之8-组合模式的更多相关文章

  1. java23种设计模式——八、组合模式

    目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模式 java23种设计模式-- ...

  2. [设计模式] javascript 之 组合模式

    组合模式说明 组合模式用于简单化,一致化对单组件和复合组件的使用:其实它就是一棵树: 这棵树有且只有一个根,访问入口,如果它不是一棵空树,那么由一个或几个树枝节点以及子叶节点组成,每个树枝节点还包含自 ...

  3. 设计模式学习之组合模式(Composite,结构型模式)(10)

    转载地址:http://www.cnblogs.com/zhili/p/CompositePattern.html 一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系 ...

  4. 设计模式之:组合模式(Composite)

    支持原创:http://blog.csdn.net/hguisu/article/details/7530783 设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构 ...

  5. [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表

    所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理, ...

  6. C#设计模式之十组合模式(Composite)【结构型】

    一.引言   今天我们要讲[结构型]设计模式的第四个模式,该模式是[组合模式],英文名称是:Composite Pattern.当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达 ...

  7. 设计模式学习心得<组合模式 Composite>

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...

  8. C#设计模式之九组合模式(Composite Pattern)【结构型】

    一.引言 今天我们要讲[结构型]设计模式的第四个模式,该模式是[组合模式],英文名称是:Composite Pattern.当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达的意 ...

  9. Java设计模式学习记录-组合模式

    前言 今天要介绍的设计模式是组合模式,组合模式也是结构型设计模式的一种,它主要体现了整体与部分的关系,其典型的应用就是树形结构.组合是一组对象,其中的对象可能包含一个其他对象,也可能包含一组其他对象. ...

  10. java设计模式-----13、组合模式

    Composite模式也叫组合模式,是构造型的设计模式之一.通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树. 组合(Composite)模式的其它翻译名称也很多,比如合成模式.树 ...

随机推荐

  1. Ethical Hacking - Web Penetration Testing(11)

    SQL INJECTION Preventing SQLi Filters can be bypassed. Use a blacklist of commands? Still can be byp ...

  2. CPU核数

    今天想看CPU核数,又忘记怎么看了QAQ. CPU的基本信息都被记录在/proc/cpuinfo中,一般直接cat /proc/cpuinfo就可以了. 主要是学习一下物理cpu核数/逻辑cpu核数的 ...

  3. 消除win10桌面图标的右下方小箭头

    很容易的小东西,在这里简单提一下 新建一个记事本,写下以下代码,改为.bat后缀,双击运行,然后箭头消失 reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Micro ...

  4. 【Java面试】- 并发容器篇

    JDK 提供的并发容器 ConcurrentHashMap: 线程安全的 HashMap CopyOnWriteArrayList: 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vec ...

  5. javascript 通信协议

    简介 javascript 通信协议是一个伪协议[1], 用于指定 URL 为 JavaScript 代码 语法: javascript:someScript; someScript 是一个或多个使用 ...

  6. 启动扫描闪退,因为忘了在manifest里申请手机镜头使用许可了。

    启动扫描闪退,因为忘了在manifest里申请手机镜头使用许可了.

  7. 今天完成了deviceman的程序,压缩成deivceman.rar

    目录在d:\android_projects\deviceman 压成了deviceman.rar 发送到了yzx3233@sina.com

  8. 自动化不知如何参数化(二)?xlrd来帮你解决

    在昨天的博文中介绍了普通单元格数据的获取,以及单元格数据类型的转换,详细见博文:自动化不知如何参数化(一)?xlrd来帮你解决. 昨天的那篇博文中,还有个获取合并单元格数据的问题没解决,今天就专门来讲 ...

  9. 基于Centos7安装Docker-registry2.0

    我们可能希望构建和存储包含不想公开的信息或数据的镜像,因为Docker公司的团队开源了docker-registry的代码,这样我们就可以基于此代码在内部运行自己的registry. 服务端1.拉去仓 ...

  10. Spring Boot AOP的使用

    简单来说讲,动态地将代码切入到类的指定方法.指定位置上的编程思想就是面向切面的编程. 目录 AOP几个术语 AOP Demo 引入Maven依赖 一个简单的Controller 定义切面类 调用服务 ...