设为首页 加入收藏

TOP

[学习笔记]设计模式之Composite(一)
2019-09-03 03:21:44 】 浏览:28
Tags:学习 笔记 设计模式 Composite

为方便读者,本文已添加至索引:

写在前面

Composite(组合)模式中,用户可以使用多个简单的组件以形成较大的组件,而这些组件还可能进一步组合成更大的。它重要的特性是能够让用户一致地对待单个对象和组合对象。不知大家是否还记得女巫格琳达(见笔记Facade模式),她的小屋经营得很顺利,给小伙伴们的生活带来了极大地便利。今天,她又推出了一项全新的销售项目,那就是“私人订制自主行动型魔法小人偶-I”。乍看之下是个稻草人模样,但其实客人们能够通过自己订制小人偶的不同部件,组装成一个可以按照预先设定的期望目标而自主行动的魔法人偶。他们可以帮忙播种,耕地,烹饪,甚至战斗等等等等。

女巫格琳达在设计这个小人偶原型时,采用了Composite模式从而简化了客户们的操作,同时也能利用清晰的树形结构来展示订制的全部内容。在我们进入到示例部分讲解小人偶相关代码之前,先来具体了解下Composite模式的基本知识:

要点梳理

  • 目的分类
    • 对象结构型模式
  • 范围准则
    • 对象(该模式处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性)
  • 主要功能
    • 将对象组合成树形结构以表示“部分-整体”的层次结构。这可以使得用户在使用单个对象和组合对象时有一致性。
  • 适用情况
    • 当我们想表示对象的部分-整体层次结构时;
    • 当我们希望用户忽略组合对象与单个对象的不同,让他们能够统一地去使用时
  • 参与部分
    • Component:为组合中的对象声明接口;或者在适当的情况下,实现所有类共有接口的缺省行为;声明一个接口用于访问和管理Component的子组件;在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它,当然这个是可选的。
    • Leaf:在组合中表示叶节点对象,需要说明的是,叶节点没有子节点。
    • Composite:定义有子部件的那些部件的行为,同时存储子部件,实现Component中与子部件有关的接口。
    • Client:通过Component接口,操纵组合部件的对象。
  • 协作过程
    • 用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶节点,则直接处理请求。如果接收者是Composite, 它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。
  • UML图

示例分析 - 私人订制魔法小人偶-I

从上文的UML图中,可以看到Composite模式描述了如何使用递归组合,使得用户不必对单个类与组合类进行区别。而实现这一点的关键,在于Component抽象类,它既能代表单个组件,又能代表容器。

对于我们的魔法小人偶-I型而言,我们同样定义一个Component类为接下来所有的部件定义一个接口。

 1 class Component {
 2 public:
 3     virtual ~Component();
 4     
 5     const char* name() { return _name; }
 6     
 7     virtual int myFunction();    // power on the function of the component.
 8     virtual int myValue();    // count the value of the component.
 9     
10     virtual void add(Component*);
11     virtual void remove(Component*);
12     virtual Iterator<Component*>* createIterator();
13     
14 protected:
15     Component(const char*);
16     
17 private:
18     const char* _name;
19 };

我们看到Component声明了一些操作来返回一个部件的属性,譬如说它的价格等。子类将为指定的部件实现这些接口。而对于createIterator操作,它能够返回一个访问它零件的Iterator,从而能够在管理零件的时候,进行遍历。

Component类的子类有很多,我们将不会全部讲述(那会显得很冗余)。我们首先看到的是Leaf型的组件,它们不是容器,比如装在原型里面的驱动装置,穿在外面的衣服,戴在头上的帽子,可以使用的武器、工具等等。比如我们Clothes类:

1 class Clothes : public Component {
2 public:
3     Clothes(const char*);
4     virtual ~Clothes();
5     
6     virtual int myFunction();
7     virtual int myValue();
8 };

另一些是Composite型的组件,它们作为容器能够包含其他部件。这种组件的基类CompositeComponent

 1 class CompositeComponent : public Component {
 2     virtual ~CompositeComponent();
 3     
 4     virtual int myFunction();
 5     virtual int myValue();
 6     
 7     virtual void add(Component*);
 8     virtual void remove(Component*);
 9     virtual Iterator<Component*>* createIterator();
10     
11 protected:
12     CompositeComponent(const char*);
13     
14 private:
15     List<Component*> _component;
16 };

它为访问和管理子部件定义了一些操作。操作add/remove将从存储在_component成员变量中的部件列表中插入/删除部件。而作为容器的myValue操作,通过使用createIterator,来累加子部件的价格。

1 int CompositeComponent::myValue() {
2     Iterator<Component*>* iter = createIterator();
3     int total = 0;
4     for (iter->first(); !iter->isDone(); iter->next()) {
5         total += iter->current()->myValue();
6     }
7     delete iter;
8     return total;
9 }

CompositeComponent类的子类之一ProtoBody,是最基本的人偶外壳容器,格琳达可以通过在里面安置一些驱动器Drive,传感器Sensor等来使得它得以正常运作。

1 class ProtoBody : public CompositeComponent {
2 public:
3     ProtoBody(const char*);
4     virtual ~ProtoBody();
5     
6     virtual int myFunction();
7     virtual int myValue();
8 };

好啦,我们还可以定义一些相似的其他容器,譬如战斗人偶的武器袋We

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇BS与CS的联系与区别 下一篇【.NET】单例模式标准写法

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目