跳至主要內容

《C++设计模式》视频_李建忠

LincZero大约 4 分钟

《C++设计模式》视频_李建忠

目录

[toc]

组合模式 Composite

所属分类——“数据结构” 模式

  • “数据结构” 模式
    • 常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。 这时候,将这些特定数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。
  • 典型模式
    • 组合模式 Composite
    • 迭代器模式 Iterator
    • 职责链模式 Chain of Resposibility

动机(Motivation)

简概

  • “数据结构” 模式
    • 常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。 这时候,将这些特定数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。
  • 典型模式
    • 组合模式 Composite
    • 迭代器模式 lterator
    • 职责链模式 Chain of Resposibility

代码体现

其实就是树结构用多态的方式来实现

举例(组合模式)

#include <iostream>
#include <list>
#include <string>
#include <algorithm>

using namespace std;

// 定义节点的抽象接口,抽象基类(树节点和叶子节点共同组成树形结构)
class Component
{
public:
	virtual void process()=0;
    virtual ~Component(){}
};

// 枝干节点。继承Component
class Composite : public Component{	
	string name;
	list<Component*> elements;				// 节点,list存储多态指针
public:
    Composite(const string & s):name(s){}	// 构造函数
    void add(Component* element) {			// 添加节点
		elements.push_back(element);
	}
	void remove(Componentx element){		// 移除节点
		elements.remove(element) ;
	}
	void process( ){
		// 1. process current node,处理当前节点
        // 2. process leaf nodes,处理叶子节点
        for (auto &e : elements)			// 这里是C++11的基于范围循环
			e->process();					// 【虚函数调用、多态调用,且为递归调用】
    }
};

// 叶子节点。继承Component
class Leaf : public Component{
    string name;
public:
	Leaf(string s):name(s){}				// 构造函数
    
    void process(){
		//process current node
	}
};

// 客户程序
void Invoke(Component & c){	// 传入树形节点
    //...
	c.process( );			// 调用树形节点(底层会递归遍历处理)
	//...
};

// 运行函数
int main(){
    // 构造枝干节点和叶子节点
	Composite root("root") ;
	Composite treeNode1("treeNode1");
    Composite treeNode2("treeNode2");
    Composite treeNode3("treeNode3");
    Composite treeNode4("treeNode4");
    Leaf left1("left1");
	Leaf left2("left2");

    // 组合枝干节点和叶子节点,组合成为树形结构
    root.add(&treeNode1) ;
	treeNode1.add(&treeNode2);
    treeNode2.add(&leaf1);
	root.add(&treeNode3);
	treeNode3.add(&treeNode4);
    treeNode4.add(&leaf2);
    
    // 开始处理节点
	process(root) ;
}

设计模式

模式定义

将对象组合成树形结构以表示 “部分-整体” 的层次结构。 Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)

——《设计模式》GoF

结构(Structure)

题外话:感觉这个结构有些问题

树叶比较尴尬,也不知道要不要实现这几个函数,实现为空的话,又违背接口原则

解决提案:Add、Remove、GetChild不一定要放在抽象基类、可只放在枝干节点中。

要点总结

  • Composite模式采用树形结构来实现普遍存在的对象容器,从而将 “一对多” 的关系转化为 “一对一” 的关系, 使得客户代码可以一致地(复用)处理对象和对象容器,无需关心处理的是单个的对象,还是组合的对象容器
  • 将 “客户代码与复杂的对象容器结构" 解耦是Composite的核心思想,解耦之后, 客户代码将与纯粹的抽象接口(而非对象容器的内部实现结构)发生依赖,从而更能 “应对变化”
  • Composite模式在具体实现中,可以让父对象中的子对象反向追溯;如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率