学习而来,代码是自己敲的。也有些自己的理解在里边,有问题希望大家指出。

组合模式的定义与特点

 组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式

组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点,树形结构图如下。

组合模式示意图

由上图可以看出,其实根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。

这样,在组合模式中,整个树形结构中的对象都属于同一种类型,带来的好处就是用户不需要辨别是树枝节点还是叶子节点,可以直接进行操作,给用户的使用带来极大的便利。

组合模式的主要优点有:

  • 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
  • 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

其主要缺点是:

  • 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  • 不容易限制容器中的构件;
  • 不容易用继承的方法来增加构件的新功能;

组合模式的结构与实现

组合模式的结构不是很复杂,下面对它的结构和实现进行分析。

1. 模式的结构

组合模式包含以下主要角色。

  1. 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
  2. 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
  3. 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

组合模式分为透明式的组合模式和安全式的组合模式。

(1) 透明方式

在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。其结构图如图 1 所示。

图1  透明式的组合模式的结构图

(2) 安全方式

在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。其结构图如图 2 所示。

图2    安全式的组合模式的结构图​​​​

2. 模式的实现

假如要访问集合 c0={leaf1,{leaf2,leaf3}} 中的元素,其对应的树状图如图 3 所示。

案例

代码样例

using DesignPattern.CompositePattern;
using System; namespace DesignPattern
{
internal class Program
{
static void Main(string[] args)
{
CompositeHelper();
} #region Pattern - Composite
static void CompositeHelper()
{
Composite _root = new TreeLimb("小三门目录"); Composite art = new TreeLimb("美术");
Composite sports = new TreeLimb("体育");
Composite music = new TreeLimb("音乐");
_root.Add(art);
_root.Add(sports);
_root.Add(music); Composite painting = new TreeLimb("油画类");
art.Add(painting); Composite running = new TreeLimb("跑步类");
Composite swimming = new TreeLimb("游泳类");
sports.Add(running);
sports.Add(swimming); Composite soprano = new TreeLimb("高音类");
Composite opera = new TreeLimb("戏曲类");
Composite bass = new TreeLimb("低音类");
music.Add(soprano);
music.Add(opera);
music.Add(bass); Composite painting1 = new Leaf("油画精选1");
Composite painting2 = new Leaf("油画精选2");
painting.Add(painting1);
painting.Add(painting2); Composite opera1 = new TreeLimb("戏曲选集1");
Composite opera2 = new TreeLimb("戏曲选集2");
Composite opera3 = new TreeLimb("戏曲选集3");
opera.Add(opera1);
opera.Add(opera2);
opera.Add(opera3);
opera.Remove(opera2); Composite swimming1 = new Leaf("花样游泳");
Composite swimming2 = new Leaf("200m游泳");
Composite swimming3 = new Leaf("800m接力游泳");
Composite swimming4 = new Leaf("1600m接力游泳");
swimming.Add(swimming1);
swimming.Add(swimming2);
swimming.Add(swimming3);
swimming.Add(swimming4); _root.Depth(0);
Console.WriteLine();
Console.WriteLine("文章数:" + _root.ShowCount()); Console.ReadLine();
}
#endregion
}
} //======================================================================================
using System;
using System.Collections.Generic;
namespace DesignPattern.CompositePattern
{
/// <summary>
/// 抽象合成类
/// </summary>
public abstract class Composite
{
/// <summary>
/// 组件名
/// </summary>
public string Name;
public Composite(string name)
{
Name = name;
} /// <summary>
/// 增加子节点
/// </summary>
public abstract void Add(Composite composite); /// <summary>
/// 删除子节点
/// </summary>
public abstract void Remove(Composite composite); /// <summary>
/// 返回最终子节点数量
/// </summary>
public abstract int ShowCount(); /// <summary>
/// 节点展示深度
/// </summary>
/// <param name="depth"> - 的数量</param>
public abstract void Depth(int depth);
} /// <summary>
/// 枝干节点
/// </summary>
public class TreeLimb : Composite
{
private List<Composite> m_Composite = new List<Composite>(); public TreeLimb(string name) : base(name)
{
Name = name;
}
public override void Add(Composite component)
{
m_Composite.Add(component);
} public override void Depth(int depth)
{
Console.WriteLine(new string('-', depth * 2) + Name);
foreach (Composite item in m_Composite)
{
item.Depth(depth + 1);
}
} public override void Remove(Composite component)
{
m_Composite.Remove(component);
} public override int ShowCount()
{
int count = 0;
foreach (var item in m_Composite)
{
count += item.ShowCount();
}
return count;
}
} /// <summary>
/// 子节点
/// </summary>
public class Leaf : Composite
{
public Leaf(string name) : base(name)
{
Name = name;
}
public override void Add(Composite composite)
{
throw new InvalidOperationException("叶子节点不能添加元素");
} public override void Depth(int depth)
{
Console.WriteLine(new string('-', depth * 2) + Name);
} public override void Remove(Composite composite)
{
throw new InvalidOperationException("叶子节点不能删除元素");
} public override int ShowCount()
{
return 1;
}
}
}

运行结果:


希望大家:点赞,留言,关注咯~

唠家常

今日分享结束啦,小伙伴们你们get到了么,你们有没有更好的办法呢,可以评论区留言分享,也可以加QQ:841298494,大家一起进步。

  • 客官,看完get之后记得点赞哟!
  • 小伙伴你还想要别的知识?好的呀,分享给你们

今日推荐

结构型模式 - 组合模式Composite Pattern的更多相关文章

  1. 【设计模式】结构型05组合模式(Composite Pattern)

    组合模式(Composite Pattern) 意图:将对象组合成树形结构以表示"部分-整体"的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 主要解决:它在我们 ...

  2. 【设计模式】结构型03外观模式(Facade Pattern)

    [设计模式]结构型02装饰模式(Decorator Pattern) 意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 主要解决:降低访问 ...

  3. 【结构型】Flyweight模式

    享元模式的主要目的.意图是为对象的大量使用提供一种共享机制.该模式的思想重在复用.共享复用.像文字.列表中的格子等这类多数都是需要考虑复用技术,否则必将大量耗费内存空间而使资源以及性能等大量耗费.该模 ...

  4. python设计模式---结构型之代理模式

    主要想着nginx:) from abc import ABCMeta, abstractmethod # 结构型设计模式---代理模式 class Actor: def __init__(self) ...

  5. 使用C# (.NET Core) 实现组合设计模式 (Composite Pattern)

    本文的概念性内容来自深入浅出设计模式一书. 本文需结合上一篇文章(使用C# (.NET Core) 实现迭代器设计模式)一起看. 上一篇文章我们研究了多个菜单一起使用的问题. 需求变更 就当我们感觉我 ...

  6. 【设计模式】结构型04桥接模式(Bridge Pattern)

    学习地址:http://www.runoob.com/design-pattern/bridge-pattern.html 桥接模式(Bridge Pattern) 桥接模式(Bridge patte ...

  7. java设计模式--结构型模式--组合模式

    什么是组合模式,这个有待研究,个人觉得是各类组合而形成的一种结构吧. 组合模式: 组合模式 概述 将对象组合成树形结构以表示"部分-整体"的层次结构."Composite ...

  8. JAVA设计模式 5【结构型】代理模式的理解与使用

    今天要开始我们结构型 设计模式的学习,设计模式源于生活,还是希望能通过生活中的一些小栗子去理解学习它,而不是为了学习而学习这些东西. 结构型设计模式 结构型设计模式又分为 类 结构型 对象 结构型 前 ...

  9. Composite模式 组合模式

    Android的ViewGroup 和 View 的关系,即是采用组合模式 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件 ...

随机推荐

  1. Linux--网络基础(概念+协议的了解+OSI七层模型,TCP/IP五层协议,网络数据传输流程)

    网络的发展 网络的发展有下面几个阶段: 独立模式:计算机最开始是以单机模式被广泛使用的.每一台计算机都是独立的,之间不能够进行数据共享与通信 网络互联: 计算机之间可以链接在一起,完成数据共享,计算机 ...

  2. pinpoint:初始化hbase数据库

    安装完成hbase之后,需要初始化hbase的pinpoint库(创建表). 1. 登录数据库 [root@monitor default]# cd /home/pinpoint/hbase-1.7. ...

  3. 重大发现,AQS加锁机制竟然跟Synchronized有惊人的相似

    在并发多线程的情况下,为了保证数据安全性,一般我们会对数据进行加锁,通常使用Synchronized或者ReentrantLock同步锁.Synchronized是基于JVM实现,而Reentrant ...

  4. 强连通分量与tarjan算法初步运用

    模板题:B3609 [图论与代数结构 701] 强连通分量 题目描述 给定一张 n 个点 m 条边的有向图,求出其所有的强连通分量. 注意,本题可能存在重边和自环. 输入格式 第一行两个正整数 n , ...

  5. Seata 1.5.2 源码学习(事务执行)

    关于全局事务的执行,虽然之前的文章中也有所涉及,但不够细致,今天再深入的看一下事务的整个执行过程是怎样的. 1. TransactionManager io.seata.core.model.Tran ...

  6. 解决fpdf不能写入中文问题

    安装依赖 pip3 install FPDF -i https://mirrors.aliyun.com/pypi/simple fpdf 原生是php调用的,不过他也提供了python的调用方式 示 ...

  7. Redis的常见应用场景

    缓存.分布式数据共享.setnx分布式锁.incrby全局id进行分库分表.计数器.限流(ip为key,计数超过阈值则返回false).购物车(hash,用户key-商品field-数量value). ...

  8. 同时容器,k8s和docker区别是什么? 如何简单理解k8s和docker

    1.k8s是一个开源的容器集群管理系统,可以实现容器集群的自动化部署.自动扩缩容.维护等功能. 2.Docker是一个开源的应用容器引擎,开发者可以打包他们的应用及依赖到一个可移植的容器中,发布到流行 ...

  9. ORM数据增删改查 django请求生命周期 django路由层 反向解析

    目录 可视化界面之数据增删改查 补充 1.建表 2.数据展示功能 3.数据添加功能 4.数据编辑功能 5.数据删除功能 django请求生命周期流程图 crsf wsgirel 与 uwsgi ngi ...

  10. adb安装电视apk

    adb 是什么? 百度说明:adb工具即Android Debug Bridge(安卓调试桥) tools.它就是一个命令行窗口,用于通过电脑端与模拟器或者真实设备交互.在某些特殊的情况下进入不了系统 ...