软件设计模式 - 创建型模式
创建型模式分为:工厂方法,抽象工厂,生成器,原型,单例。
工厂方法模式(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 { } };
class Circle : public Graphics { protected: void paint() override { } };
|
这样以来,如果我们要绘制圆形,即可声明一个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 { } void paintCircle() override { } void paintSquare() override { } };
class PencilFactory { protected: void paintTriangle() override { } void paintCircle() override { } void paintSquare() override { } };
class PastelFactory { protected: void paintTriangle() override { } void paintCircle() override { } void paintSquare() override { } };
class BlendFactory { protected: void paintTriangle() override { } void paintCircle() override { } void paintSquare() override { } };
|
这样以来,我们要铅笔风格地绘制三角形,则无需在关注三角形类,其他类似。
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() { return *this; } Builder& circleBrush() { return *this; } Builder& squareBrush() { return *this; }
Builder& trianglePencil() { return *this; } Builder& circlePencil() { return *this; } Builder& squarePencil() { return *this; }
Builder& trianglePastel() { return *this; } Builder& circlePastel() { return *this; } Builder& squarePastel() { return *this; }
void paint() { } };
|
如果需要绘制复杂图形,使用生成器模式,可以这样:
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; auto newshape = shape.clone(); SquareGraphics square(*newshape); auto newsquare = square.clone();
|
单例模式(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();
|