【设计模式学习笔记】组合模式与桥接模式案例详解(C++实现)
目录
一、组合模式
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;
}