Compare commits
2 Commits
c49faa4780
...
1550d371d4
| Author | SHA1 | Date | |
|---|---|---|---|
| 1550d371d4 | |||
| 51f8bd9f99 |
86
08_bridge.cpp
Normal file
86
08_bridge.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Texture {
|
||||||
|
public:
|
||||||
|
Texture() = default;
|
||||||
|
virtual ~Texture() = default;
|
||||||
|
|
||||||
|
virtual const string& show_texture() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Shape {
|
||||||
|
protected:
|
||||||
|
shared_ptr<Texture> t;
|
||||||
|
public:
|
||||||
|
Shape(shared_ptr<Texture> t) : t(t) {}
|
||||||
|
virtual void draw() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Square : public Shape {
|
||||||
|
int x1;
|
||||||
|
int y1;
|
||||||
|
int x2;
|
||||||
|
int y2;
|
||||||
|
public:
|
||||||
|
Square(shared_ptr<Texture> t, int x1, int y1, int x2, int y2) :
|
||||||
|
Shape(t), x1(x1), y1(y1), x2(x2), y2(y2) {}
|
||||||
|
|
||||||
|
virtual void draw() {
|
||||||
|
// Maybe you have to use different show_texture. For example,
|
||||||
|
// show_texture_square for Square, show_texture_circle for Circle,
|
||||||
|
// so that the actions is M*N, but that is unavoidable, and the
|
||||||
|
// class's count is M+N.
|
||||||
|
cout << "draw square: " << x1 << " " << y1 << " " << x2 << " " << y2
|
||||||
|
<< " with texture " << t->show_texture() << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Circle : public Shape {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int r;
|
||||||
|
public:
|
||||||
|
Circle(shared_ptr<Texture> t, int x, int y, int r) :
|
||||||
|
Shape(t), x(x), y(y), r(r) {}
|
||||||
|
|
||||||
|
virtual void draw() override {
|
||||||
|
cout << "draw circle: " << x << " " << y << " " << r << " with texture "
|
||||||
|
<< t->show_texture() << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SoilTexture : public Texture {
|
||||||
|
string s;
|
||||||
|
public:
|
||||||
|
SoilTexture(int level) : s("Soil") { s += to_string(level); }
|
||||||
|
virtual const string& show_texture() override {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WaterTexture : public Texture {
|
||||||
|
string s;
|
||||||
|
public:
|
||||||
|
WaterTexture(int level) : s("Water") { s += to_string(level + 256); }
|
||||||
|
virtual const string& show_texture() override {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
shared_ptr<Texture> ts = make_shared<SoilTexture>(123);
|
||||||
|
shared_ptr<Texture> tw = make_shared<WaterTexture>(11);
|
||||||
|
// When you want to create a new texture, you just need to create one
|
||||||
|
// texture class and use it when generating shape.
|
||||||
|
// you don't need to create a set of shapes.
|
||||||
|
// You can switch different Textures esaily when running.
|
||||||
|
|
||||||
|
auto c = make_shared<Circle>(ts, 1, 2, 3);
|
||||||
|
auto s = make_shared<Square>(tw, 1, 2, 3, 4);
|
||||||
|
c->draw();
|
||||||
|
s->draw();
|
||||||
|
}
|
||||||
55
09_composite.cpp
Normal file
55
09_composite.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Shape {
|
||||||
|
public:
|
||||||
|
virtual void draw() = 0;
|
||||||
|
virtual ~Shape() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Square : public Shape {
|
||||||
|
public:
|
||||||
|
virtual void draw() {
|
||||||
|
cout << "Square" << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Circle : public Shape {
|
||||||
|
public:
|
||||||
|
virtual void draw() {
|
||||||
|
cout << "Circle" << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Both derived from shape, so that they can be treated as same
|
||||||
|
class ShapeGroup : public Shape {
|
||||||
|
vector<shared_ptr<Shape>> shapes;
|
||||||
|
public:
|
||||||
|
void add_shape(shared_ptr<Shape> item) {
|
||||||
|
shapes.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void draw() {
|
||||||
|
cout << "draw group" << endl;
|
||||||
|
for (auto item : shapes) {
|
||||||
|
item->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto s1 = make_shared<Square>();
|
||||||
|
auto s2 = make_shared<Square>();
|
||||||
|
auto c1 = make_shared<Circle>();
|
||||||
|
auto sg = make_shared<ShapeGroup>();
|
||||||
|
|
||||||
|
sg->add_shape(s1);
|
||||||
|
sg->add_shape(s2);
|
||||||
|
sg->add_shape(c1);
|
||||||
|
sg->draw();
|
||||||
|
}
|
||||||
|
|
||||||
17
notes.md
17
notes.md
@ -49,3 +49,20 @@
|
|||||||
适配器类可以继承自 `A`,并将 `B` 作为构造参数。在构造过程中,适配器将 `B` 的接口转换为符合 `A` 的接口形式。这样,通过适配器,`B` 就可以像 `A` 一样调用接口,达到接口兼容的效果。考虑到适配性,比如希望这个适配器类还能适配其他的 `C`,`D` 等,可以让适配器类接受一个更普遍的共性作为构造参数。
|
适配器类可以继承自 `A`,并将 `B` 作为构造参数。在构造过程中,适配器将 `B` 的接口转换为符合 `A` 的接口形式。这样,通过适配器,`B` 就可以像 `A` 一样调用接口,达到接口兼容的效果。考虑到适配性,比如希望这个适配器类还能适配其他的 `C`,`D` 等,可以让适配器类接受一个更普遍的共性作为构造参数。
|
||||||
|
|
||||||
需要注意的是,这种做法显然会使得代码复杂很多,条件允许的话,还是直接修改 `B` 类较好。
|
需要注意的是,这种做法显然会使得代码复杂很多,条件允许的话,还是直接修改 `B` 类较好。
|
||||||
|
|
||||||
|
## 桥接模式(Bridge)
|
||||||
|
|
||||||
|
有时类有多个变化维度需要组合。以图形为例,它既有“形状”的维度,也有“纹理”的维度。若采用继承来组合这两个维度,将导致类数量呈乘法增长(`M * N`)。而且,一个维度的变更都可能影响到多个类。
|
||||||
|
|
||||||
|
桥接模式给出的解决方案是:“组合优于继承”。它通过将“形状”和“纹理”分别建模为独立的类层次结构,并在“形状”中组合一个“纹理”的引用,使两者的组合关系从原来的 `M * N` 转变为 `M + N`。这样可以自由扩展任意一侧,而无需影响另一侧。即使实现中可能仍需要 `M * N` 种行为(这是无法减少的),但是当一个纹理要改变时,也只需要改这个纹理类而不影响其他类。此外,这种组合关系是运行时决定的,因此可以动态地将不同的抽象与实现配对,增强了系统的灵活性。
|
||||||
|
|
||||||
|
在桥接模式中,抽象部分(也称为接口)定义的是高层的控制逻辑,而真正的工作则由被称为实现部分的组件完成。抽象层在调用时,会将具体任务委派给实现层,从而实现灵活的组合与运行时绑定。
|
||||||
|
|
||||||
|
## 组合模式(Composite)
|
||||||
|
|
||||||
|
在实际开发中,我们经常需要将多个对象组织成一个整体来进行处理。例如,在一个绘图应用中,一个画板可能包含多个图形元素(如圆形、矩形、线条等),我们希望能够将这些元素打包成一个更大的组件,便于统一地移动、缩放或删除。
|
||||||
|
|
||||||
|
但这就引出一个问题:组件和基本元素类型不同,无法使用统一的接口进行操作,需要额外判断和处理。
|
||||||
|
|
||||||
|
组合模式正是为了解决这个问题。它的核心思想是:将对象组合成树形结构来表示“整体-部分”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。也就是说,我们可以将一个组件(由多个元素组成)当作一个普通元素一样来处理,统一操作接口,简化客户端代码。
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user