0%

软件设计模式 - 创建型模式

软件设计模式 - 创建型模式

创建型模式分为:工厂方法,抽象工厂,生成器,原型,单例。

工厂方法模式(Factory Method)

工厂方法模式是一种在父类声明方法,在子类实例化该对象的方法。在C++中通常以虚函数形式来表示,在其他语言,例如Java中则是抽象函数来表示。

工厂方法模式中更加关注目标“产品”本身,一般使用统一的接口来实例化对象的属性。

例如一个图形绘制的场景应用,对于夫类,我们只关注高层次需求(图形的绘制),这里的对应为图形,结构如下:

Factory Method - Graphics

定义代码如下:

1
2
3
4
5
class Graphics {
// 抽象夫类
protected:
virtual void paint() = 0;
};

夫类(图形类)是一个抽象的高层次类,我们如果绘制不同的具体图形,可以这样定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Triangle : public Graphics {
// 绘制三角形的类
protected:
void paint() override {
// TODO: 绘制三角形
}
};

class Circle : public Graphics {
// 绘制圆形的类
protected:
void paint() override {
// TODO: 绘制圆形
}
};

这样以来,如果我们要绘制圆形,即可声明一个Circle类的对象,调用通用的paint()即可完成圆的图形绘制,其他各种不同的图形的绘制都是如此,从而大大降低了理解成本,我们只需关注“产品”即可(圆Circle)。

抽象工厂模式(Abstract Factory)

抽象工厂是一种无需指定具体要实例化的类的方法,它关注的是构造对象的不同“风格”,通常一个工厂可以构造大于一个的不同“产品”。

举例如下,仍然以上面的绘图为例,不过现在我们要绘制特殊风格的图形,它们有的是刷子,有的是铅笔,有的是蜡笔,或者是混色器,结构如下:

Abstract Factory - Graphics

这里定义了四种风格的图形绘制工厂,每种工厂使用通过的接口绘制不同的图形(可以构造三种不同的“产品”)。

代码定义如下:

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
class GraphicsFactory {
// 夫类
protected:
virtual void paintTriangle() = 0;
virtual void paintCircle() = 0;
virtual void paintSquare() = 0;
};

class BrushFactory {
// 刷子绘制工厂
protected:
void paintTriangle() override {
// TODO: 绘制三角形
}
void paintCircle() override {
// TODO: 绘制圆形
}
void paintSquare() override {
// TODO: 绘制方块
}
};

class PencilFactory {
// 铅笔绘制工厂
protected:
void paintTriangle() override {
// TODO: 绘制三角形
}
void paintCircle() override {
// TODO: 绘制圆形
}
void paintSquare() override {
// TODO: 绘制方块
}
};

class PastelFactory {
// 蜡笔绘制工厂
protected:
void paintTriangle() override {
// TODO: 绘制三角形
}
void paintCircle() override {
// TODO: 绘制圆形
}
void paintSquare() override {
// TODO: 绘制方块
}
};

class BlendFactory {
// 混色器绘制工厂
protected:
void paintTriangle() override {
// TODO: 绘制三角形
}
void paintCircle() override {
// TODO: 绘制圆形
}
void paintSquare() override {
// TODO: 绘制方块
}
};

这样以来,我们要铅笔风格地绘制三角形,则无需在关注三角形类,其他类似。

1
2
3
4
5
6
PencilFactory pFactory;
pFactory.paintTriangle(); // 铅笔绘制三角形
pFactory.paintCircle(); // 铅笔绘制圆形
BrushFactory bFactory;
bFactory.paintCircle(); // 刷子绘制圆形
bFactory.paintSquare(); // 刷子绘制方块

生成器模式(Builder)

生成器模式是一种分步创建复杂对象的方法,它允许我们灵活定制化地创建对象的各个组成部分。

生成器的构造模式是繁复地调用各个接口进行特定的初始化工作,用以设置对象的属性变量,初始化完了之后,再调用一个生成函数(build()),产生目标对象。

以绘图为例:

Builder - Graphics

这里定义了三种绘制风格,使用生成器时,只需初始化特定的风格图形,最后调用生成接口(paint()),即可绘制出目标图形。

代码如下:

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
class Builder {
Builder& triangleBrush() {
// TODO: 添加刷子绘制三角形
return *this;
}
Builder& circleBrush() {
// TODO: 添加刷子绘制圆形
return *this;
}
Builder& squareBrush() {
// TODO: 添加刷子绘制方块
return *this;
}

Builder& trianglePencil() {
// TODO: 添加铅笔绘制三角形
return *this;
}
Builder& circlePencil() {
// TODO: 添加铅笔绘制圆形
return *this;
}
Builder& squarePencil() {
// TODO: 添加铅笔绘制方块
return *this;
}

Builder& trianglePastel() {
// TODO: 添加蜡笔绘制三角形
return *this;
}
Builder& circlePastel() {
// TODO: 添加蜡笔绘制圆形
return *this;
}
Builder& squarePastel() {
// TODO: 添加蜡笔绘制方块
return *this;
}

void paint() {
// TODO: 生成函数
}
};

如果需要绘制复杂图形,使用生成器模式,可以这样:

1
2
3
4
5
Builder builder;
builder.circlePastel() // 初始化圆形
.squareBrush() // 初始化方块
.trianglePencil() // 初始化三角形
.paint() // 生成

原型模式(Prototype)

一般来说,对象是通过类的定义来获取的,但是如果我们不知道类,只是想通过对象来克隆一个新的对象,并延用对象的一些属性,这种方式就是原型模式。

注意到,对象的克隆可以屏蔽类的复杂细节问题,对象的克隆可以是公有的属性方法或变量,也可以是保护的或私有的属性方法和变量,这样克隆才可以把原来的对象属性最大可能复制出去。

Prototype - Graphics

实例代码如下:

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
class ShapeGraphics {
// 形状
public:
ShapeGraphics() : mX(0), mY(0), mColor(0) {}
ShapeGraphics(int x, int y, int cr)
: mX(x), mY(y), mColor(cr)
{}
ShapeGraphics(const ShapeGraphics& shape) {
this->mX = shape.mX;
this->mY = shape.mY;
this->mColor = shape.mColor;
}
virtual ShapeGraphics* clone() = 0;
private:
int mX, mY, mColor;
};

class CircleGraphics : public ShapeGraphics {
// 圆形
public:
CircleGraphics(const CircleGraphics& source)
: ShapeGraphics(source)
{
this.mRadius = source.mRadius;
}
ShapeGraphics* clone() {
return new CircleGraphics(*this);
}
private:
int mRadius;
};

class TriangleGraphics : public ShapeGraphics {
// 三角形
public:
TriangleGraphics(const TriangleGraphics& source)
: ShapeGraphics(source)
{
this->mA = source.mA;
this->mB = source.mB;
this->mC = source.mC;
}
ShapeGraphics* clone() {
return new TriangleGraphics(*this);
}
private:
int mA, mB, mC;
};

class SquareGraphics : public ShapeGraphics {
// 方块
public:
SquareGraphics(const SquareGraphics& source)
: ShapeGraphics(source)
{
this->mWidth = source.mWidth;
this->mHeight = source.mHeight;
}
ShapeGraphics* clone() {
return new SquareGraphics(*this);
}
private:
int mWidth, mHeight;
};

使用原型模式进行构造对象,代码用法如下:

1
2
3
4
5
6
7
8
9
10
11
class CustomShape : public ShapeGraphics {
CustomShape() : ShapeGraphics(10, 10, 0xff00) {}
ShapeGraphics* clone() {
return new CustomShape(*this);
}
};

CustomShape shape; // 坐标(10,10),颜色 0xff00
auto newshape = shape.clone(); // 克隆形状
SquareGraphics square(*newshape); // 构造一个基于newshape克隆体属性的对象
auto newsquare = square.clone(); // 新的克隆体方块,拥有square的属性

单例模式(Singleton)

单例是一种特殊的构造模式,它构造的对象在运行时只存在一个全局实例。

单例通常用于中心控制,集中配置的地方,这样满足信息一致性,调控一致性等问题。

实例代码如下:

1
2
3
4
5
6
7
8
9
10
11
class Singleton {
// 单例
public:
static Singleton& getInstance() {
// 声明类的静态变量
static Singleton inst;
return inst;
}
private:
Singleton() {}
};

上面定义了一个单例类,它是无法用类实例化的,而是通过静态变量和函数来达到对象获取和声明的功能。

使用方法如下:

1
auto inst = Singleton::getInstance(); // 获取单例

欢迎关注我的其它发布渠道