设计模式 笔记 组合模式 Composite
//---------------------------15/04/16----------------------------
//Composite 组合模式----对象结构型模式
/*
1:意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和
组合对象的使用具有一致性。
2:动机:
3:适用性:
1>你想表示对象的部分-整体层次结构。
2>你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
4:结构:
Client--------->Component:<--------------
Operation() |
Add(Component) |
Remove(Component) |
GetChild(int) |
| |
| |
-------------- |
| | |
Leaf: Composite: |
Operation() children---------
Operation()
{ for all g in children
{ g.Operation()}
}
Add(Comonent)
Remove(Component)
GetChild(int)
5:参与者:
1>Component
1)为组合中的对象声明接口。
2)在适当的情况下,实现所有类共有接口的缺省行为。
3)声明一个接口用于访问和管理Component的子组件。
4)(可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
2>Leaf
1)在组合中表示叶节点对象,叶节点没有子节点。
2)在组合中定义图元对象的行为。
3>Composite
1)定义有子部件的那些部件的行为。
2)存储子部件。
3)在Component接口中实现与子部件有关的操作。
4>Client
通过Component接口操纵组合部件的对象。
6:协作:
用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶节点,则直接处理请求。
如果接受者是Composite,它通常将请求发送给它的子部件,在转发请求之前与(或)之后可能执行一些
辅助操作。
7:效果:
1>定义了包含基本对象和组合对象的类层次结构。
基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断递归下去。客户
代码中,任何用到基本对象的地方都可以使用组合对象。
2>简化客户代码。
客户可以一致地使用组合结构和单个对象。通常用户不知道(也不关心)处理的是一个叶节点还是一个
组合对象。这样就简化了客户代码,不必写一大堆选择语句来区分它们。
3>使得更容易增加新类型的组件。
新定义的Composite或Leaf子类自动地与已有的结构和客户代码一起工作,客户程序不需因新增
的Component类而改变。
4>使你的设计变得更加一般化。
容易增加新组件意味着很难限制组合中的组件。如果你希望一个组合只能由一些特定的组件,
在使用Composite模式时却不能依赖类型系统施加这些约束,而必须在运行时刻进行检查。
8:实现:
1>显示的父部件引用。(也就是存储一个父节点的指针)
保持从子部件到父部件的引用能简化组合结构的遍历和管理。父部件引用可以简化结构的上移和
组件的删除,同时也能支持责任链模式。
对于父部件引用必须维护一个不变式,即一个组合的所有子节点以这个组合为父节点,而反之
该组合以这些节点为子节点。可以选择在Composite类的Add和Remove操作中实现这种方法。
2>共享组件:
共享组件可以减少对存储的需求,可以使用Flywight方式来实行共享。
3>最大化Component接口
Composite模式的目的之一是使得用户不知道他们正在使用的具体的Leaf和Composite类。
为了达到这个目的,Component类应该为Leaf和Composite类尽可能多定义一些公共操作。
为了不限制Leaf类,可以对Composite类才需要的
操作实现缺省的操作。
4>声明管理子部件的操作
选择在Component类还是在Composite类中声明管理子部件的操作,这需要在安全性和透明性之间
做出选择:
1)在Component中声明:这样拥有良好的透明性,因为这样可以一致地使用所有组件,但是会付出
安全性的代价,因为客户有可能会在Leaf中做出无意义的操作,比如增加或删除对象。
2)在Composite类中声明:这样做女友良好的安全性,但损失了透明性。接口变得不一致了。
这里我们比较看重透明性:所以要在Component中定义缺省的Add和Remove操作。这时又带来一个问题
客户可能会向一个Leaf中添加或删除组件,所以通常可以使用缺省方式处理Add和Remove的失败。
有一个方式是:产生一个异常,这样客户就能知道失败原因了。
5>Component是否应该实现一个Component列表。
也就是在Component中是否应该存放子节点的指针,这个答案是只有在叶子节点相对很少时才值得
这么做,因为叶子节点没有子节点,存放指针会浪费空间。
6>子部件排序。
如果需要考虑子节点的顺序时,必须仔细地设计对子节点的访问和管理接口,以便管理子节点序列。
可以参考iterator模式。
7>使用高速缓存改善性能。
使用缓存机制可以加速对子部件的访问。但是如果子部件发生了变化,那么这个子部件必须通知他的
父节点高速缓存失效了。所以需要在Compnent中定义一个private接口。
8>应该由谁删除Component
通常最好由Composite负责删除其子节点。Leaf对象不会改变,所以可以被共享而不删除。
9>存贮组件最好用哪一种数据结构
什么效率高就用什么,包括数组,树,hash表,链表。
9:代码示例: */
//假设我们要组装一台电脑,这里每个设备只需要知道其价格就行,所以可以设计一个component类
//Compnent类:
给出了设备名 和价格
以及对子部件的操作
class Equipment
{
public:
virtual ~Equipment();
const char* Name() {
return _name;}
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
virtual void Add(Equipment*);
virtual void Remove(Equipment*);
virtual Iterator<Equipment*>* CreateIterator();
protected:
Equipment(const
char*);
private:
const char* _name;
};
//Leaf组件:实现了Compnent类中的组件特有操作
class FloppyDisk :
public Equipment
{
public:
FloppyDisk(const
char*);
virtual ~FloppyDisk();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
};
//Composite类:实现了对子部件的操作
class CompositeEquipment :
public Equipment
{
public:
virtual ~CompositeEquipment();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
virtual void Add(Equipment*);
virtual void Remove(Equipment*);
virtual Iterator<Equipment*>* CreateIterator();
protected:
CompositeEquipment(const
char*);
private:
List<Equipment*> _equipment;
};
//具体的实现,统计每个子部件的价格
Currency CompositeEquipment::NetPrice()
{
Iterator<Equipment*>* i = CreateIterator();
Currency total =
;
for(i->First(); !i->IsDone(); i->Next())
{
total += i->CurrentItem()->NetPrice();
}
delete i;
return total;
}
//具体的Composite类,主板
class Chassis :
public CompositeEquipment
{
public:
Chassis(const
char*);
virtual ~Chassis();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
};
//机箱
Cabinet* cabinet =
new Cabinet("PC Cabinet");
Chassis* chassis =
new Chassis("PC Chassis");
cabinet->Add(chassis);
//适配卡bus
Bus* bus =
new Bus("MCA Bus");
//加了张网卡
bus->Add(new Card("16Mbs Token Ring"));
chassis->Add(bus);
//加了张软盘
chassis->Add(new FloppyDisk("3.5in Floppy"));
cout<<"Thee net Price is"<<chassis->NetPrice()<<endl;
设计模式 笔记 组合模式 Composite的更多相关文章
- 乐在其中设计模式(C#) - 组合模式(Composite Pattern)
原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...
- 二十四种设计模式:组合模式(Composite Pattern)
组合模式(Composite Pattern) 介绍将对象组合成树形结构以表示"部分-整体"的层次结构.它使得客户对单个对象和复合对象的使用具有一致性.示例有一个Message实体 ...
- 【设计模式】组合模式 Composite Pattern
树形结构是软件行业很常见的一种结构,几乎随处可见, 比如: HTML 页面中的DOM,产品的分类,通常一些应用或网站的菜单,Windows Form 中的控件继承关系,Android中的View继承 ...
- [设计模式] 8 组合模式 Composite
DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构.组合使得用户对单个对象和组合对象的使用具有一致性.注意两个字“树形”.这种树形结构在现实生活中随处可见,比如一个集团公司,它有一 ...
- python 设计模式之组合模式Composite Pattern
#引入一 文件夹对我们来说很熟悉,文件夹里面可以包含文件夹,也可以包含文件. 那么文件夹是个容器,文件夹里面的文件夹也是个容器,文件夹里面的文件是对象. 这是一个树形结构 咱们生活工作中常用的一种结构 ...
- 设计模式-12组合模式(Composite Pattern)
1.模式动机 很多时候会存在"部分-整体"的关系,例如:大学中的部门与学院.总公司中的部门与分公司.学习用品中的书与书包.在软件开发中也是这样,例如,文件系统中的文件与文件夹.窗体 ...
- 【设计模式】—— 组合模式Composite
前言:[模式总览]——————————by xingoo 模式意图 使对象组合成树形的结构.使用户对单个对象和组合对象的使用具有一致性. 应用场景 1 表示对象的 部分-整体 层次结构 2 忽略组合对 ...
- 结构型设计模式之组合模式(Composite)
结构 意图 将对象组合成树形结构以表示“部分-整体”的层次结构.C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性. 适用性 你想表示对象的部分-整体层次结构. 你希望用 ...
- 设计模式之组合模式(Composite)
组合模式原理:组合模式的作用是讲继承同一父类的不同子类对象组合起来,形成一个树形的结构,例如公司的部门组织 代码如下 #include <iostream> #include <st ...
随机推荐
- Appium环境搭建python篇(mac系统)
1.安装Appium 通过终端安装: 安装nodejs,下载地址:https://nodejs.org/download/,安装完成后打开终端输入node -v,检查是否安装成功 安装npm,打开终端 ...
- Prometheus Node_exporter 之 Node Exporter
Node Exporter 1. Node Exporter Scrape Time type: GraphUnit: secondsLabel: Seconds{{collector}} - 各个收 ...
- eclipse中整合ejb和web工程
用 Eclipse JEE 版本的话,新建一个 Enterprise Application Project 工程(New --> Java EE --> Enterprise Appli ...
- 开发中解决Access-Control-Allow-Origin跨域问题的Chrome神器插件,安装及使用
背景: 笔者在用cordova开发安卓程序的时候在安卓设备上不存在跨域问题,但是在浏览器端模拟调试的时候却出现了Access-Control-Allow-Origin跨域问题,报错如下 No 'Acc ...
- 使用mysqldump备份时为什么要加上 -q 参数(5.7默认为on)
使用mysqldump备份时为什么要加上 -q 参数(5.7默认为on) 写在前面:我们在使用mysqldump备份数据时,请一定记住要加上 -q 参数,后果可能是很严重的,不要给自己挖坑哦. 先来看 ...
- RSA 非对称加密,私钥转码为pkcs8 错误总结
RSA 非对称加密,私钥转码为pkcs8 错误总结 最近在和某上市公司对接金融方面的业务时,关于RSA对接过程中遇到了一个坑,特来分享下解决方案. 该上市公司简称为A公司,我们简称为B公司.A-B两家 ...
- 详解动态规划(Dynamic Programming)& 背包问题
详解动态规划(Dynamic Programming)& 背包问题 引入 有序号为1~n这n项工作,每项工作在Si时间开始,在Ti时间结束.对于每项工作都可以选择参加与否.如果选择了参与,那么 ...
- PAT乙级真题及训练题 1025. 反转链表 (25)
PAT乙级真题及训练题 1025. 反转链表 (25) 感觉几个世纪没打代码了,真是坏习惯,调了两小时把反转链表调出来了,心情舒畅. 这道题的步骤 数据输入,数组纪录下一结点及储存值 创建链表并储存上 ...
- 详解--从地址栏输入url到页面展现中间都发生了什么?
这是一个综合性很强的问题,个人理解包含以下七个基本点: 1.在浏览器地址栏输入url并按下回车. 2.浏览器检查当前url是否存在缓存和缓存是否过期. 3.域名解析(DNS解析url对应的ip). 4 ...
- git版本管理工具-git的概述
什么是git Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目的一种工具 Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不 ...