软件设计模式 - 创建型模式
软件设计模式 - 创建型模式
创建型模式分为:工厂方法,抽象工厂,生成器,原型,单例。
工厂方法模式(Factory Method)
工厂方法模式是一种在父类声明方法,在子类实例化该对象的方法。在C++中通常以虚函数形式来表示,在其他语言,例如Java中则是抽象函数来表示。
工厂方法模式中更加关注目标“产品”本身,一般使用统一的接口来实例化对象的属性。
例如一个图形绘制的场景应用,对于夫类,我们只关注高层次需求(图形的绘制),这里的对应为图形,结构如下:
定义代码如下:
class Graphics {
// 抽象夫类
protected:
virtual void paint() = 0;
};
夫类(图形类)是一个抽象的高层次类,我们如果绘制不同的具体图形,可以这样定义:
class Triangle : public Graphics {
// 绘制三角形的类
protected:
void paint() override {
// TODO: 绘制三角形
}
};
class Circle : public Graphics {
// 绘制圆形的类
protected:
void paint() override {
// TODO: 绘制圆形
}
};
这样以来,如果我们要绘制圆形,即可声明一个Circle
类的对象,调用通用的paint()
即可完成圆的图形绘制,其他各种不同的图形的绘制都是如此,从而大大降低了理解成本,我们只需关注“产品”即可(圆Circle
)。
抽象工厂模式(Abstract Factory)
抽象工厂是一种无需指定具体要实例化的类的方法,它关注的是构造对象的不同“风格”,通常一个工厂可以构造大于一个的不同“产品”。
举例如下,仍然以上面的绘图为例,不过现在我们要绘制特殊风格的图形,它们有的是刷子,有的是铅笔,有的是蜡笔,或者是混色器,结构如下:
这里定义了四种风格的图形绘制工厂,每种工厂使用通过的接口绘制不同的图形(可以构造三种不同的“产品”)。
代码定义如下:
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: 绘制方块
}
};
这样以来,我们要铅笔风格地绘制三角形,则无需在关注三角形类,其他类似。
PencilFactory pFactory;
pFactory.paintTriangle(); // 铅笔绘制三角形
pFactory.paintCircle(); // 铅笔绘制圆形
BrushFactory bFactory;
bFactory.paintCircle(); // 刷子绘制圆形
bFactory.paintSquare(); // 刷子绘制方块
生成器模式(Builder)
生成器模式是一种分步创建复杂对象的方法,它允许我们灵活定制化地创建对象的各个组成部分。
生成器的构造模式是繁复地调用各个接口进行特定的初始化工作,用以设置对象的属性变量,初始化完了之后,再调用一个生成函数(build()
),产生目标对象。
以绘图为例:
这里定义了三种绘制风格,使用生成器时,只需初始化特定的风格图形,最后调用生成接口(paint()
),即可绘制出目标图形。
代码如下:
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: 生成函数
}
};
如果需要绘制复杂图形,使用生成器模式,可以这样:
Builder builder;
builder.circlePastel() // 初始化圆形
.squareBrush() // 初始化方块
.trianglePencil() // 初始化三角形
.paint() // 生成
原型模式(Prototype)
一般来说,对象是通过类的定义来获取的,但是如果我们不知道类,只是想通过对象来克隆一个新的对象,并延用对象的一些属性,这种方式就是原型模式。
注意到,对象的克隆可以屏蔽类的复杂细节问题,对象的克隆可以是公有的属性方法或变量,也可以是保护的或私有的属性方法和变量,这样克隆才可以把原来的对象属性最大可能复制出去。
实例代码如下:
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;
};
使用原型模式进行构造对象,代码用法如下:
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)
单例是一种特殊的构造模式,它构造的对象在运行时只存在一个全局实例。
单例通常用于中心控制,集中配置的地方,这样满足信息一致性,调控一致性等问题。
实例代码如下:
class Singleton {
// 单例
public:
static Singleton& getInstance() {
// 声明类的静态变量
static Singleton inst;
return inst;
}
private:
Singleton() {}
};
上面定义了一个单例类,它是无法用类实例化的,而是通过静态变量和函数来达到对象获取和声明的功能。
使用方法如下:
auto inst = Singleton::getInstance(); // 获取单例