C#设计模式(12)——组合模式
1.组合模式
在软件开发中我们经常会遇到处理部分与整体的情况,如我们经常见到的树形菜单,一个菜单项的子节点可以指向具体的内容,也可以是子菜单。类似的情况还有文件夹,文件夹的下级可以是文件夹也可以是文件。举一个例子:一个公司的组织架构是这样的,首先是总公司,总公司下边有直属员工和各个部门,各个部门下边有本部门的子部门和员工。我们去怎么去获取这个公司的组织架构呢(就是有层次地遍历出公司的部门名和员工名)?

组合模式可以很好地解决这类问题,组合模式通过让树形结构的叶子节点和树枝节点使用同样的接口,结合递归的思想来处理部分与整体关系,这种方式模糊了简单对象(叶子)和对象组(树枝)间的概念,让我们可以像处理单个对象一样去处理对象组。
树叶和树枝都要使用相同的接口,所以先创建一个抽象类,其内部定义了树枝和树叶的公共接口:
/// <summary>
/// 抽象部件 定义了树枝和树叶的公共属性和接口
/// </summary>
public abstract class Component
{
public string name;
public Component(string name)
{
this.name = name;
}
//添加子节点
public abstract void Add(Component c);
//删除子节点
public abstract void Remove(Component c);
//展示方法,dept为节点深度
public abstract void Display(int dept);
}
员工类,相当于树叶,没有下一级:
//具体员工,树形结构的Leaf
public class Employee : Component
{
public Employee(string name):base(name)
{
this.name = name;
}
//Leaf不能添加/删除子节点所以空实现
public override void Add(Component c)
{
}
public override void Remove(Component c)
{ }
public override void Display(int dept)
{
Console.WriteLine(new string('-', dept)+name);
}
}
部门类,相当于树枝,下边的节点可有有子部门,也可以有员工:
/// <summary>
/// 部门类,相当于树枝
/// </summary>
public class Depart : Component
{
public Depart(string name) : base(name)
{
this.name = name;
}
//添加子节点
public List<Component> children=new List<Component>();
public override void Add(Component c)
{
children.Add(c);
}
//删除子节点
public override void Remove(Component c)
{
children.Remove(c);
}
//展示自己和和内部的所有子节点,这里是组合模式的核心
public override void Display(int dept)
{
Console.WriteLine(new string('-',dept)+name);
foreach (var item in children)
{
//这里用到了递归的思想
item.Display(dept + );
}
}
}
客户端调用:
class Program
{
static void Main(string[] args)
{
Component DepartA = new Depart("A总公司");
Component DepartAX = new Depart("AX部门");
Component DepartAY = new Depart("AY部门");
Component DepartAX1 = new Depart("AX1子部门");
Component DepartAX2 = new Depart("AX2子部门");
Component Ae1 = new Employee("公司直属员工1");
Component AXe1= new Employee("AX部门员工1");
Component AX1e1= new Employee("AX1部门员工1");
Component AX1e2= new Employee("AX1部门员工2");
Component AYe1= new Employee("AY部门员工1");
Component AYe2= new Employee("AY部门员工2");
DepartA.Add(Ae1);
DepartA.Add(DepartAX);
DepartA.Add(DepartAY);
DepartAX.Add(AXe1);
DepartAX.Add(DepartAX1);
DepartAX.Add(DepartAX2);
DepartAX1.Add(AX1e1);
DepartAX1.Add(AX1e2);
DepartAY.Add(AYe1);
DepartAY.Add(AYe2);
//遍历总公司
DepartA.Display();
Console.ReadKey();
}
}
运行结果如下:

上边的例子中部门类中包含了一个List children,这个List内部装的是该部门的子节点,这些子节点可以是子部门也可以是员工,在部门类的Display方法中通过foreach来遍历每一个子节点,如果子节点是员工则直接调用员工类中的Display方法打印出名字;如果子节点是子部门,调用部门类的Display遍历子部门的下级节点,直到下级节点只有员工或者没有下级节点为止。这里用到了递归的思想。
2.小结
上边例子的类图

组合模式的使用场景:当我们处理部分-整体的层次结构时,希望使用统一的接口来处理部分和整体时使用。
组合模式的优点:在树形结构的处理中模糊了对象和对象组的概念,使用对象和对象组采用了统一的接口,让我们可以像处理简单对象一样处理对象组。
C#设计模式(12)——组合模式的更多相关文章
- 设计模式-12组合模式(Composite Pattern)
1.模式动机 很多时候会存在"部分-整体"的关系,例如:大学中的部门与学院.总公司中的部门与分公司.学习用品中的书与书包.在软件开发中也是这样,例如,文件系统中的文件与文件夹.窗体 ...
- JavaScript设计模式之----组合模式
javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...
- C#设计模式(10)——组合模式(Composite Pattern)
一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...
- c++设计模式15 --组合模式
今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...
- 乐在其中设计模式(C#) - 组合模式(Composite Pattern)
原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...
- C#设计模式(10)——组合模式(Composite Pattern)(转)
一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...
- C#设计模式:组合模式(Composite Pattern)
一,C#设计模式:组合模式(Composite Pattern) using System; using System.Collections.Generic; using System.Linq; ...
- [设计模式] 8 组合模式 Composite
DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构.组合使得用户对单个对象和组合对象的使用具有一致性.注意两个字“树形”.这种树形结构在现实生活中随处可见,比如一个集团公司,它有一 ...
- 【GOF23设计模式】组合模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_组合模式.树状结构.杀毒软件架构.JUnite底层架构.常见开发场景 package com.test.composite ...
- iOS设计模式之组合模式
组合模式(Composite) 基本理解 整体和部分可以一直对待. 组合模式:将对象组合成树形结构以表示"部分--整体"的层次结构.组合模式使得用户对单个对象和组合独享的使用具有一 ...
随机推荐
- I - Tunnel Warfare HDU - 1540 线段树最大连续区间
题意 :一段区间 操作1 切断点 操作2 恢复最近切断的一个点 操作3 单点查询该点所在最大连续区间 思路: 主要是push_up : 设区间x 为母区间 x<<1 ,x< ...
- 白兔的刁难 IDFT
题目描述 给你\(n,k\),求 \[ \forall 0\leq t< k,s_t=\sum_{i=-t}^{n-t}[k|i]\binom{n}{i+t} \] 对\(998244353\) ...
- project 2013 显示标题
1.分析 右键只能插入任务,不能插入标题,而插入任务会被编号,目前只能在打印设置标题,不能在编辑界面显示标题的,或者使用最高级任务的方式 2.解决 文件,打印,页面设置,页眉,居中,输入标题,这样打印 ...
- HAOI2017 简要题解
「HAOI2017」新型城市化 题意 有一个 \(n\) 个点的无向图,其中只有 \(m\) 对点之间没有连边,保证这张图可以被分为至多两个团. 对于 \(m\) 对未连边的点对,判断有哪些点对满足将 ...
- luogu5024 [NOIp2018]保卫王国 (动态dp)
可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵 #include<bits/stdc++.h> #define CLR(a,x) memset(a ...
- MySQL 到底能不能放到 Docker 里跑?
https://weibo.com/ttarticle/p/show?id=2309404296528549285581 前言 前几月经常看到有 MySQL 到底能不能放到 Docker 里跑的各种讨 ...
- docker cmd list
436 wget -qO- https://get.docker.com/ | sh 437 sudo apt-get update 438 sudo apt-get install -y docke ...
- poj2083 Fractal
我一开始的想法是间断性的输出空格和solve(k-1) 但是发现问题很大. 雨菲:可以用一个数组保存啊 我:那不爆了? 雨菲:不会爆. 我一算:729 × 729,还真没爆. 然后就直接WA了.... ...
- 系统API执行没效果,可以检查一下是否与 360安全卫士 有关?!
今天在写一个工具软件,使用到一个系统API: mouse_event() 代码如下: mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x2, ...
- Vue中data返回对象和返回值的区别
速记:粗浅的理解是,事件的结果是影响单个组件还是多个组件.因为大部分组件是要共享的,但他们的data是私有的,所以每个组件都要return一个新的data对象 返回对象的时候 <!DOCTYPE ...