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

2017年6月5日

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

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

工厂方法模式(Factory Method)

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

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

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

Factory Method - Graphics

定义代码如下:

cpp
class Graphics {
    // 抽象夫类
protected:
    virtual void paint() = 0;
};

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

cpp
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

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

代码定义如下:

cpp
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: 绘制方块
    }
};

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

cpp
PencilFactory pFactory;
pFactory.paintTriangle(); // 铅笔绘制三角形
pFactory.paintCircle(); // 铅笔绘制圆形
BrushFactory bFactory;
bFactory.paintCircle(); // 刷子绘制圆形
bFactory.paintSquare(); // 刷子绘制方块

生成器模式(Builder)

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

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

以绘图为例:

Builder - Graphics

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

代码如下:

cpp
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: 生成函数
    }
};

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

cpp
Builder builder;
builder.circlePastel() // 初始化圆形
       .squareBrush() // 初始化方块
       .trianglePencil() // 初始化三角形
       .paint() // 生成

原型模式(Prototype)

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

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

Prototype - Graphics

实例代码如下:

cpp
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;
};

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

cpp
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)

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

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

实例代码如下:

cpp
class Singleton {
    // 单例
public:
    static Singleton& getInstance() {
        // 声明类的静态变量
        static Singleton inst;
        return inst;
    }
private:
    Singleton() {}
};

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

使用方法如下:

cpp
auto inst = Singleton::getInstance(); // 获取单例
© 2013 – 2025 陈祥