设计模式 | 组合模式、桥接模式

举报
mindtechnist 发表于 2023/05/11 14:34:42 2023/05/11
【摘要】 目录一、组合模式1. 什么是组合模式2. 组合模式案例 二、桥接模式1. 什么是桥接模式 2. 桥接模式案例一、组合模式1. 什么是组合模式Composite Pattern,组合模式,是一种结构型模式。组合模式将对象组合成树形结构以表示“整体-部分”的层次结构,并使得用户对单个对象和组合对象的使用具有一致性。组合模式构造了一个树形的对象结构,并且通过一个属性对象可以可以访问整棵树的对象。组...

目录

一、组合模式

1. 什么是组合模式

2. 组合模式案例

 二、桥接模式

1. 什么是桥接模式

 2. 桥接模式案例


一、组合模式

1. 什么是组合模式

Composite Pattern,组合模式,是一种结构型模式。

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

组合模式构造了一个树形的对象结构,并且通过一个属性对象可以可以访问整棵树的对象。

组合模式的三种角色:

  • Component:抽象角色,代表树形结构的抽象结点,它定义了所有实现类的统一接口(属性、方法、行为),并提供了访问和管理子结点的接口;简言之,Component定义了Leaf和Composite共同的操作接口,比如增加子结点,删除子结点等行为,是一个抽象基类。
  • Leaf:叶子结点,叶子结点中没有子结点,类似于树中的叶子结点,或文件系统中的文件。
  • Composite :枝结点,可以存储子结点,并实现子结点的操作,类似于文件系统的文件夹。

2. 组合模式案例

首先定义一个抽象类,为Leaf和Composite提供统一接口,假设要做一个文件系统,文件夹(Composite)中可以放入文件和文件夹,文件(Leaf)中不可以放入任何子结点。

class Component
{
public:
	virtual void display() = 0; //显示当前文件或文件夹名称
	virtual void add(Component* node) = 0; //在当前文件夹增加一个文件或文件夹
	virtual void remove(Component* node) = 0; //在当前文件夹删除一个文件或文件夹
	virtual vector<Component*>* get_child() = 0; //获取文件夹下属文件或文件夹
};

定义一个文件类,文件中不可加入子结点

class Leaf : public Component
{
private:
	string name;
public:
	Leaf(string name)
	{
		this->name = name;
	}
	virtual void display()
	{
		cout << "Leaf: " << this->name << endl;
	}
	virtual void add(Component* node)
	{
		cout << "叶子结点,无法加入" << endl;
	}
	virtual void remove(Component* node)
	{
		cout << "叶子结点,无此操作" << endl;
	}
	virtual vector<Component*>* get_child()
	{
		cout << "叶子结点,无子结点" << endl;
		return NULL;
	}
};

定义一个文件夹类,可以加入问价或文件夹

class Composite : public Component
{
private:
	string name;
	vector<Component*>* vec;
public:
	Composite(string name)
	{
		this->name = name;
		vec = new vector<Component*>;
	}
	~Composite()
	{
		if (vec != NULL)
		{
			delete vec;
			vec = NULL;
		}
	}
	virtual void display()
	{
		cout << "Composite: " << this->name << endl;
	}
	virtual void add(Component* node)
	{
		vec->push_back(node);
	}
	virtual void remove(Component* node)
	{
		for (vector<Component*>::iterator it = vec->begin(); it != vec->end(); it++)
		{
			if (*it == node)
			{
				vec->erase(it);
			}
		}
	}
	virtual vector<Component*>* get_child()
	{
		cout << "*" << this->name << " child: " << "*\n";
		for (vector<Component*>::iterator it = vec->begin(); it != vec->end(); it++)
		{
			(*it)->display();
		}
		return vec;
	}
};

客户端操作

int main()
{
	Component* root = NULL;
	Leaf* l1 = NULL;
	Leaf* l2 = NULL;
	Composite* dir = NULL;

	root = new Composite("/root");
	l1 = new Leaf("1.cpp");
	l2 = new Leaf("2.cpp");
	dir = new Composite("/home");

	root->add(dir);
	dir->add(l1);
	dir->add(l2);

	cout << "============" << endl;
	root->display();
	root->get_child();
	dir->get_child();
	cout << "============" << endl;

	delete dir;
	delete l2;
	delete l1;
	delete root;

	system("pause");
	return 0;
}

 二、桥接模式

1. 什么是桥接模式

 Bridge Pattern,桥接模式,是一种结构型设计模式。

桥接模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。

也就是说,通过桥接模式可以实现抽象部分与实现部分的解耦合,使得抽象和实现都可以独立的发生变化,当通过继承不能实现开闭原则的时候,就可以考虑桥接模式。比如,图形和颜色,把图形设计一个抽象类,颜色设计一个抽象类,然后根据需要的图形去实现图形类,并根据需要的颜色实现颜色类,通过两个抽象类就可以实现颜色和图形的组合。

  • Abstractions:抽象类接口,包含了一个对行为实现类Implementor的引用,也就是说二者具有关联关系。
  • Refined Abstraction:抽象类接口的实现类,实现了Abstractions中定义的接口,并可以调用Implementor中的方法(包含了Implementor的引用)。
  • Implementor:行为实现类接口,定义了一系列操作。
  • Concretelmp lementor:具体实现类,实现了Implementor中的操作。

 2. 桥接模式案例

实现对不同图形上不同颜色,首先定义两个抽象类,颜色类和图形类

class Color
{
public:
	virtual void get_color() = 0;
};

class Graph
{
protected:
	Color* mGraphColor;
public:
	Graph(Color* mGraphColor)
	{
		this->mGraphColor = mGraphColor;
	}
	virtual void smear_color() = 0; //给图形上色
};

定义三个具体的颜色

class Red : public Color
{
public:
	virtual void get_color()
	{
		cout << "红色" << endl;
	}
};

class Blue : public Color
{
public:
	virtual void get_color()
	{
		cout << "蓝色" << endl;
	}
};

class Yellow : public Color
{
public:
	virtual void get_color()
	{
		cout << "黄色" << endl;
	}
};

实现具体的图形

class Circle : public Graph
{
public:
	Circle(Color* mGraphColor) : Graph(mGraphColor) {};
	virtual void smear_color()
	{
		cout << "圆形 + ";
		mGraphColor->get_color();
	}
};

class Triangle : public Graph
{
public:
	Triangle(Color* mGraphColor) : Graph(mGraphColor) {};
	virtual void smear_color()
	{
		cout << "三角形 + ";
		mGraphColor->get_color();
	}
};

客户端操作,为图形上色

int main()
{
	Color* m_color = NULL;

	m_color = new Red;
	Circle* m_circle = new Circle(m_color);
	m_circle->smear_color();

	delete m_color;
	m_color = new Blue;
	Triangle* m_triangle = new Triangle(m_color);
	m_triangle->smear_color();

	delete m_color;
	delete m_triangle;
	delete m_circle;

	system("pause");
	return 0;
}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。