3.1 预想方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>

struct Point2D
{
int x;
int y;
};

class Wall
{
Point2D start, end;
int elevation, height;
public:
Wall(Point2D start, Point2D end, int elevation, int height)
: start{start}, end{end}, elevation{elevation}, height {height} { }
};

enum class Material
{
brick,
aerated_concrete,
drywall
};

class SolidWall : public Wall
{
int width;
Material material;
public:
SolidWall(Point2D start, Point2D end, int elevation,
int height, int width, Material material)
: Wall{start, end, elevation, height}, width{width}, material{material} {}
};

SolidWall::SolidWalll(const Point2D start, const Point2D end,
const int elevation,
const int height, int width,
const Material material)
: Wall{start, end, elevation, height},
width{width}, material{material}
{
if (elevation < 0 && material == Material::aerated_concrete)
throw invalid_argument("elevation");

if (width < 120 && material == Material::brick)
throw invalid_argument("width");
}

int main(void)
{
return 0;
}

3.2 工厂方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <memory>
#include <new>

struct Point2D
{
int x;
int y;
};

class Wall
{
protected:
Point2D start, end;
int elevation, height;
public:
Wall(Point2D start, Point2D end, int elevation, int height)
: start{start}, end{end}, elevation{elevation}, height {height} { }
};

enum class Material
{
brick,
aerated_concrete,
drywall
};

std::string Material_backpack[] = {"brick", "aerated_concrete", "drywall"};

class SolidWall : public Wall
{
int width;
Material material;
protected:
SolidWall(Point2D start, Point2D end, int elevation,
int height, int width, Material material)
: Wall{start, end, elevation, height}, width{width}, material{material} {}
public:
static SolidWall create_main(Point2D start, Point2D end,
int elevation, int height)
{
return SolidWall{start, end, elevation, height,
375, Material::aerated_concrete};
}

static std::unique_ptr<SolidWall> create_partition(Point2D start,
Point2D end,
int elevation, int height)
{
/*
return std::unique_ptr<SolidWall>(new SolidWall(start, end, elevation,
height, 120, Material::brick));

*/
return std::make_unique<SolidWall>(SolidWall(start, end, elevation,
height, 120, Material::brick));

}

std::string name, position, date_of_birth;
friend std::ostream& operator<<(std::ostream& os, const SolidWall& obj)
{
return os
<< "start: " << "(" << obj.start.x << ")" << " " << "(" << obj.start.y << ")" << std::endl
<< "end: " << "(" << obj.end.x << ")" << " " << "(" << obj.end.y << ")" << std::endl
<< "elevation: " << obj.elevation << std::endl
<< "height: " << obj.height << std::endl
<< "width: " << obj.width << std::endl
<< "material:" << Material_backpack[static_cast<int>(obj.material)] << std::endl;
// << "material: " << obj.material << std::endl;
}
};
/*
SolidWall::SolidWall(const Point2D start, const Point2D end,
const int elevation,
const int height, int width,
const Material material)
: Wall{start, end, elevation, height},
width{width}, material{material}
{
if (elevation < 0 && material == Material::aerated_concrete)
throw invalid_argument("elevation");

if (width < 120 && material == Material::brick)
throw invalid_argument("width");
}
*/
int main(void)
{
const auto main_wall = SolidWall::create_main({0, 0}, {0, 3000},
2700, 3000);

std::cout << main_wall << std::endl;

return 0;
}

3.3 工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include <iostream>
#include <memory>
#include <new>
#include <vector>
#include <cmath>

class Vector2D {
public:
// 向量的 x 和 y 分量
double x, y;

// 构造函数
Vector2D(double x = 0.0, double y = 0.0) : x(x), y(y) {}

// 不等于操作符
friend bool operator!=(const Vector2D& v, const Vector2D& w) {
return (w.x != v.x) || (w.y != v.y);
}

// 等于操作符
friend bool operator==(const Vector2D& v, const Vector2D& w) {
return (w.x == v.x) && (w.y == v.y);
}

// 加法操作符
Vector2D operator+(const Vector2D& v) const {
return Vector2D(x + v.x, y + v.y);
}

// 减法操作符
Vector2D operator-(const Vector2D& v) const {
return Vector2D(x - v.x, y - v.y);
}

// 数乘操作符
Vector2D operator*(double s) const {
return Vector2D(x * s, y * s);
}

// 向量长度
double norm() const {
return std::hypot(x, y);
}

// 单位化向量
Vector2D normalize() const {
double len = norm();
return Vector2D(x / len, y / len);
}

// 点积操作符
double operator*(const Vector2D& v) const {
return x * v.x + y * v.y;
}

// 叉积操作符
Vector2D cross(const Vector2D& v) const {
return Vector2D(y * v.x - x * v.y, x * v.y - y * v.x);
}

// 投影操作符
Vector2D projectOnto(const Vector2D& normal) const {
return *this - normal * (*this * normal);
}

// 计算垂直向量
Vector2D perpendicular() const {
return Vector2D(-y, x); // 返回与当前向量垂直的向量
}
};

class Wall
{
protected:
Vector2D start, end;
double elevation, height;
public:
Wall(Vector2D start, Vector2D end, int elevation, int height)
: start{start}, end{end}, elevation{elevation}, height {height} { }
};

enum class Material
{
brick,
aerated_concrete,
drywall
};

std::string Material_backpack[] = {"brick", "aerated_concrete", "drywall"};

class SolidWall : public Wall
{
double width;
Material material;
protected:
SolidWall(Vector2D start, Vector2D end, int elevation,
int height, int width, Material material)
: Wall{start, end, elevation, height}, width{width}, material{material} {}
public:
friend class WallFactory;

//friend
bool intersects(SolidWall& wall)
{

// 检查墙壁的起点和终点是否有重合的部分
if (start == wall.start || start == wall.end || end == wall.start || end == wall.end)
return true;

// 计算两个墙壁的方向向量
Vector2D direction1 = end - start;
Vector2D direction2 = wall.end - wall.start;

// 计算两个方向向量的叉积
Vector2D crossProduct = direction1.cross(direction2);

// 如果叉积的模为 0,则两个墙壁平行或共线,不相交
if (crossProduct.norm() == 0)
return false;

// 计算墙壁的法线向量
Vector2D normal = direction1.perpendicular();

// 对于每个墙壁上的点,检查它是否在另一个墙壁的同侧
for (Vector2D point = start; point!= end; point = point + direction1)
{
Vector2D vectorToPoint = point - wall.start;
Vector2D projection = vectorToPoint.projectOnto(normal);
// 如果投影的长度大于等于墙壁的宽度,说明两个墙壁在该点相交
if (projection.norm() >= width && projection.norm() >= wall.width)
return true;
}

return false;
}

friend std::ostream& operator<<(std::ostream& os, const SolidWall& obj)
{
return os
<< "start: " << "(" << obj.start.x << ")" << " " << "(" << obj.start.y << ")" << std::endl
<< "end: " << "(" << obj.end.x << ")" << " " << "(" << obj.end.y << ")" << std::endl
<< "elevation: " << obj.elevation << std::endl
<< "height: " << obj.height << std::endl
<< "width: " << obj.width << std::endl
<< "material:" << Material_backpack[static_cast<int>(obj.material)] << std::endl;
}
};

class WallFactory
{
static std::vector<std::weak_ptr<SolidWall>> walls;
public:
static std::shared_ptr<SolidWall> create_main(Vector2D start,
Vector2D end, int elevation, int height)
{
if (elevation < 0) return {};
return std::make_shared<SolidWall>(SolidWall(start, end, elevation, height,
375, Material::aerated_concrete));
}

static std::shared_ptr<SolidWall> create_partition(Vector2D start,
Vector2D end,
int elevation, int height)
{
const auto this_wall =
new SolidWall{start, end, elevation, height, 120,
Material::brick};

// ensure we don't intersect other walls

for (const auto wall : walls)
{
if (auto p = wall.lock())
{
if (this_wall->intersects(*p))
{
delete this_wall;
return {};
}
}
}

std::shared_ptr<SolidWall> ptr(this_wall);
walls.push_back(ptr);
return ptr;
}
};

std::vector<std::weak_ptr<SolidWall>> WallFactory::walls;

int main(void)
{
// std::vector<std::weak_ptr<SolidWall>> WallFactory::walls;

const auto partition = WallFactory::create_partition(
{2000, 0}, {2000, 4000}, 0, 2700);
// std::cout << *partition << std::endl;
return 0;
}

3.4工厂方法和多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <memory>
#include <new>
#include <vector>
#include <cmath>

class Vector2D {
public:
// 向量的 x 和 y 分量
double x, y;

// 构造函数
Vector2D(double x = 0.0, double y = 0.0) : x(x), y(y) {}
};

class Wall
{
protected:
Vector2D start, end;
int elevation, height;
public:
friend class WallFactory;
Wall(Vector2D start, Vector2D end, int elevation, int height)
: start{start}, end{end}, elevation{elevation}, height {height} { }
friend std::ostream& operator<<(std::ostream& os, const Wall& obj)
{
return os
<< "start: " << "(" << obj.start.x << ")" << " " << "(" << obj.start.y << ")" << std::endl
<< "end: " << "(" << obj.end.x << ")" << " " << "(" << obj.end.y << ")" << std::endl
<< "elevation: " << obj.elevation << std::endl
<< "height: " << obj.height << std::endl;
}
virtual ~Wall() = default;
};

enum class Material
{
brick,
aerated_concrete,
drywall
};

std::string Material_backpack[] = {"brick", "aerated_concrete", "drywall"};

class SolidWall : public Wall
{
int width;
Material material;
protected:
SolidWall(Vector2D start, Vector2D end, int elevation,
int height, int width, Material material)
: Wall{start, end, elevation, height}, width{width}, material{material} {}
public:
friend class WallFactory;

friend std::ostream& operator<<(std::ostream& os, const SolidWall& obj)
{
return os
<< "start: " << "(" << obj.start.x << ")" << " " << "(" << obj.start.y << ")" << std::endl
<< "end: " << "(" << obj.end.x << ")" << " " << "(" << obj.end.y << ")" << std::endl
<< "elevation: " << obj.elevation << std::endl
<< "height: " << obj.height << std::endl
<< "width: " << obj.width << std::endl
<< "material:" << Material_backpack[static_cast<int>(obj.material)] << std::endl;
}
};

enum class WallType
{
basic,
main,
partition
};

class WallFactory
{
// static std::vector<std::weak_ptr<SolidWall>> walls;
public:
static std::shared_ptr<SolidWall> create_main(Vector2D start,
Vector2D end, int elevation, int height)
{
if (elevation < 0) return {};
return std::make_shared<SolidWall>(SolidWall(start, end, elevation, height,
375, Material::aerated_concrete));
}


static std::shared_ptr<Wall> create_wall(WallType type, Vector2D start,
Vector2D end, int elevation, int height)
{
switch(type)
{
case WallType::main:
return std::make_shared<SolidWall>(SolidWall(start, end, elevation, height,
375, Material::aerated_concrete));
case WallType::partition:
return std::make_shared<SolidWall>(SolidWall(start, end, elevation, height,
120, Material::brick));
case WallType::basic:
return std::make_shared<Wall>(Wall(start, end, elevation, height));
}
}
};

int main(void)
{
//const auto M = WallFactory::create_main(
// {2000, 0}, {2000, 4000}, 0, 2700);

const auto also_partition = WallFactory::create_wall(WallType::partition, {0, 0}, {5000, 0}, 0, 4200);
//std::cout << *also_partition << std::endl;
if (also_partition)
std::cout << *std::dynamic_pointer_cast<SolidWall>(also_partition) << std::endl;
return 0;
}

3.5 嵌套工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <memory>
#include <new>
#include <vector>
#include <cmath>

class Vector2D {
public:
// 向量的 x 和 y 分量
double x, y;

// 构造函数
Vector2D(double x = 0.0, double y = 0.0) : x(x), y(y) {}
};

class Wall
{
private:
class BasicWallFactory
{
BasicWallFactory() = default;
public:
std::shared_ptr<Wall> create(const Vector2D start,
const Vector2D end,
const int elevation, const int height)
{
Wall* wall = new Wall(start, end, elevation, height);
return std::shared_ptr<Wall>(wall);
}
};
protected:
Vector2D start, end;
int elevation, height;
public:
static BasicWallFactory factory;

Wall(Vector2D start, Vector2D end, int elevation, int height)
: start{start}, end{end}, elevation{elevation}, height {height} { }
friend std::ostream& operator<<(std::ostream& os, const Wall& obj)
{
return os
<< "start: " << "(" << obj.start.x << ")" << " " << "(" << obj.start.y << ")" << std::endl
<< "end: " << "(" << obj.end.x << ")" << " " << "(" << obj.end.y << ")" << std::endl
<< "elevation: " << obj.elevation << std::endl
<< "height: " << obj.height << std::endl;
}
~Wall() = default;
};

int main(void)
{
auto basic = Wall::factory.create({0, 0}, {5000, 0}, 0, 3000);
std::cout << *basic << std::endl;

return 0;
}

3.6 抽象工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <memory>
#include <map>

struct HotDrink
{
virtual void prepare(int volume){};
};

struct Tea : HotDrink
{
void prepare(int volume) override
{
std::cout << "Take tea bag, boil water, pour " << volume
<< "ml, add some lemon" << std::endl;
}
};

struct Coffee : HotDrink
{
void prepare(int volume) override
{
std::cout << "Take coffee bag, boil water, pour " << volume
<< "ml, add some lemon" << std::endl;
}
};


class HotDrinkFactory {
public:
virtual std::unique_ptr<HotDrink> make() const = 0;
virtual ~HotDrinkFactory(){};
};


class TeaFactory : public HotDrinkFactory {
public:
std::unique_ptr<HotDrink> make() const override
{
return std::make_unique<Tea>();
}

virtual ~TeaFactory(){};
};

class CoffeeFactory : public HotDrinkFactory {
public:
std::unique_ptr<HotDrink> make() const override
{
return std::make_unique<Coffee>();
}
virtual ~CoffeeFactory() {};
};

class DrinkFactory
{
std::map<std::string, std::unique_ptr<HotDrinkFactory>> hot_factories;
public:
DrinkFactory()
{
hot_factories["coffee"] = std::make_unique<CoffeeFactory>();
hot_factories["tea"] = std::make_unique<TeaFactory>();
}

std::unique_ptr<HotDrink> make_drink(const std::string& name)
{
auto drink = hot_factories[name]->make();
drink->prepare(200);
return drink;
}
};

int main()
{
DrinkFactory f;
auto co = f.make_drink("coffee");

return 0;
}

3.7 函数式工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <memory>
#include <map>
#include <functional>

struct HotDrink
{
virtual void prepare(int volume){};
};

struct Tea : HotDrink
{
void prepare(int volume) override
{
std::cout << "Take tea bag, boil water, pour " << volume
<< "ml, add some lemon" << std::endl;
}
};

struct Coffee : HotDrink
{
void prepare(int volume) override
{
std::cout << "Take coffee bag, boil water, pour " << volume
<< "ml, add some lemon" << std::endl;
}
};


class HotDrinkFactory {
public:
virtual std::unique_ptr<HotDrink> make() const = 0;
virtual ~HotDrinkFactory(){};
};


class TeaFactory : public HotDrinkFactory {
public:
std::unique_ptr<HotDrink> make() const override
{
return std::make_unique<Tea>();
}

virtual ~TeaFactory(){};
};

class CoffeeFactory : public HotDrinkFactory {
public:
std::unique_ptr<HotDrink> make() const override
{
return std::make_unique<Coffee>();
}
virtual ~CoffeeFactory() {};
};

class DrinkWithVolumeFactory
{
std::map<std::string, std::function<std::unique_ptr<HotDrink>()>> factories;
public:
DrinkWithVolumeFactory()
{
factories["tea"] = [] {
auto tea = std::make_unique<Tea>();
tea->prepare(200);
return tea;
};
factories["coffee"] = [] {
auto coffee = std::make_unique<Coffee>();
coffee->prepare(200);
return coffee;
};
}

std::unique_ptr<HotDrink> make_drink(const std::string& name)
{
return factories[name]();
}
};

int main()
{
DrinkWithVolumeFactory f;
auto co = f.make_drink("coffee");

return 0;
}