//---------------------------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的更多相关文章

  1. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  2. 二十四种设计模式:组合模式(Composite Pattern)

    组合模式(Composite Pattern) 介绍将对象组合成树形结构以表示"部分-整体"的层次结构.它使得客户对单个对象和复合对象的使用具有一致性.示例有一个Message实体 ...

  3. 【设计模式】组合模式 Composite Pattern

    树形结构是软件行业很常见的一种结构,几乎随处可见,  比如: HTML 页面中的DOM,产品的分类,通常一些应用或网站的菜单,Windows Form 中的控件继承关系,Android中的View继承 ...

  4. [设计模式] 8 组合模式 Composite

    DP书上给出的定义:将对象组合成树形结构以表示“部分-整体”的层次结构.组合使得用户对单个对象和组合对象的使用具有一致性.注意两个字“树形”.这种树形结构在现实生活中随处可见,比如一个集团公司,它有一 ...

  5. python 设计模式之组合模式Composite Pattern

    #引入一 文件夹对我们来说很熟悉,文件夹里面可以包含文件夹,也可以包含文件. 那么文件夹是个容器,文件夹里面的文件夹也是个容器,文件夹里面的文件是对象. 这是一个树形结构 咱们生活工作中常用的一种结构 ...

  6. 设计模式-12组合模式(Composite Pattern)

    1.模式动机 很多时候会存在"部分-整体"的关系,例如:大学中的部门与学院.总公司中的部门与分公司.学习用品中的书与书包.在软件开发中也是这样,例如,文件系统中的文件与文件夹.窗体 ...

  7. 【设计模式】—— 组合模式Composite

    前言:[模式总览]——————————by xingoo 模式意图 使对象组合成树形的结构.使用户对单个对象和组合对象的使用具有一致性. 应用场景 1 表示对象的 部分-整体 层次结构 2 忽略组合对 ...

  8. 结构型设计模式之组合模式(Composite)

    结构 意图 将对象组合成树形结构以表示“部分-整体”的层次结构.C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性. 适用性 你想表示对象的部分-整体层次结构. 你希望用 ...

  9. 设计模式之组合模式(Composite)

    组合模式原理:组合模式的作用是讲继承同一父类的不同子类对象组合起来,形成一个树形的结构,例如公司的部门组织 代码如下 #include <iostream> #include <st ...

随机推荐

  1. 购物商城学习--第三讲(tomcat插件启动web工程)

    此处提到的tomcat插件即maven工程集成的tomcat插件,可以在添加maven的tomcat插件之后,在本地通过脚本或者命令行方式运行web工程,tomcat插件启动只需要修改一个端口即可,非 ...

  2. Mysql binlog 无法删除(purge命令无法删除)

    1.版本 1)操作系统 cat /etc/issueCentOS release 6.6 (Final)Kernel \r on an \m cat /proc/versionLinux versio ...

  3. 【存在问题,待修改】SSH 远程登陆

    0. 前提 设置 hosts 参考链接 Linux 配置 hosts SSH公钥登录原理 1. SSH 是什么 SSH ( Secure Shell ) 是一种协议标准,其目的是实现安全远程登录以及其 ...

  4. 【转】Linux 高级的视角来查看Linux引导过程

    [原文]https://www.toutiao.com/i6594210975480545800/ 1.概述 图 1 是我们在20,000 英尺的高度看到的视图. 当系统首次引导时,或系统被重置时,处 ...

  5. ansible 增加本机/etc/hosts 下hostsname 与IP

    --- - hosts: all vars: IP: "{{ ansible_eth0['ipv4']['address'] }}" tasks: - name: 将原有的host ...

  6. (转)python3 urllib.request.urlopen() 错误UnicodeEncodeError: 'ascii' codec can't encode characters

    代码内容: url = 'https://movie.douban.com/j/search_subjects?type=movie'+ str(tag) + '&sort=recommend ...

  7. sublime text3 当运行报错error时,取消显示路径path的方法

    sublime text3 每当运行报错error时,都会出现一长串的path路径,如何不显示呢? 可以通过注释掉Packages/Default/exec.py的四个特定行来更改. 首先,您需要从P ...

  8. ubuntu 视频播放问题

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/chang_xing/article/details/30976659                ...

  9. POJ 2049— Finding Nemo(三维BFS)10/200

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013497151/article/details/29562915 海底总动员.... 这个题開始 ...

  10. BZOJ2815:[ZJOI2012]灾难(拓扑排序,LCA)

    Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过 ...