设计模式之工厂模式(二):实际案例

发布于:2025-05-14 ⋅ 阅读:(7) ⋅ 点赞:(0)

  设计模式之工厂模式(一)

        在阅读Qt网络部分源码时候,发现在某处运用了工厂模式,而且编程技巧也用的好,于是就想分享出来,供大家参考,理解的不对的地方请多多指点。

        以下是我整理出来的类图:

关键说明:

1.Q_GLOBAL_STATIC(QSocketEngineHandlerList, socketHandlers)

Qt实现单例模式:Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS_qt 单例宏-CSDN博客

Q_GLOBAL_STATIC宏定义了一个全局变量,这个全局变量是定义在qabstractsocketengine.cpp中,它的定义如下:

class QSocketEngineHandlerList : public QList<QSocketEngineHandler*>
{
public:
    QMutex mutex;
};

Q_GLOBAL_STATIC(QSocketEngineHandlerList, socketHandlers)

在cpp中定义,其它地方是访问不到这个全局变量,隐藏了实现,封装性比较好。

2.QAbstractSocketEngine和QHttpSocketEngine

在工厂模式中这个类就相当于是需要生产的对象,它是一个接口类,一般都是通过继承它来实现具体的功能。本例中QHttpSocketEngine就是实际的具有某个功能的类。

3.QSocketEngineHandler

这个类类似工厂模式中的工厂,它的定义如下:

class Q_AUTOTEST_EXPORT QSocketEngineHandler
{
protected:
    QSocketEngineHandler();
    virtual ~QSocketEngineHandler();
    virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType,
                                                      const QNetworkProxy &, QObject *parent) = 0;
    virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent) = 0;

private:
    friend class QAbstractSocketEngine;
};
QSocketEngineHandler::QSocketEngineHandler()
{
    if (!socketHandlers())
        return;
    QMutexLocker locker(&socketHandlers()->mutex);
    socketHandlers()->prepend(this);
}

QSocketEngineHandler::~QSocketEngineHandler()
{
    if (!socketHandlers())
        return;
    QMutexLocker locker(&socketHandlers()->mutex);
    socketHandlers()->removeAll(this);
}

从上面的代码可以看出,在QSocketEngineHandler的构造函数和析构函数分别去注册和移除工厂,让继承QSocketEngineHandler的类也不用暴露socketHandlers,这个地方也是写的比较巧妙的地方。

4.QHttpSocketEngineHandler

具体的工厂类,负责生产QHttpSocketEngine,代码如下:

class Q_AUTOTEST_EXPORT QHttpSocketEngineHandler : public QSocketEngineHandler
{
public:
    virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType,
                                                      const QNetworkProxy &, QObject *parent) override;
    virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescripter, QObject *parent) override;
};
QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(QAbstractSocket::SocketType socketType,
                                                                    const QNetworkProxy &proxy,
                                                                    QObject *parent)
{
    if (socketType != QAbstractSocket::TcpSocket)
        return 0;

    // proxy type must have been resolved by now
    if (proxy.type() != QNetworkProxy::HttpProxy)
        return 0;

    // we only accept active sockets
    if (!qobject_cast<QAbstractSocket *>(parent))
        return 0;

    QHttpSocketEngine *engine = new QHttpSocketEngine(parent);
    engine->setProxy(proxy);
    return engine;
}

QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(qintptr, QObject *)
{
    return 0;
}

5.createSocketEngine()

在QAbstractSocketEngine类有两个静态函数,就是生产对象的入口:

class Q_AUTOTEST_EXPORT QAbstractSocketEngine : public QObject
{
    Q_OBJECT
public:

    static QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent);
    static QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent);

    QAbstractSocketEngine(QObject *parent = 0);

    ...
};
QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &proxy, QObject *parent)
{
#ifndef QT_NO_NETWORKPROXY
    // proxy type must have been resolved by now
    if (proxy.type() == QNetworkProxy::DefaultProxy)
        return 0;
#endif

    QMutexLocker locker(&socketHandlers()->mutex);
    for (int i = 0; i < socketHandlers()->size(); i++) {
        if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketType, proxy, parent))
            return ret;
    }

#ifndef QT_NO_NETWORKPROXY
    // only NoProxy can have reached here
    if (proxy.type() != QNetworkProxy::NoProxy)
        return 0;
#endif

    return new QNativeSocketEngine(parent);
}

QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(qintptr socketDescripter, QObject *parent)
{
    QMutexLocker locker(&socketHandlers()->mutex);
    for (int i = 0; i < socketHandlers()->size(); i++) {
        if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketDescripter, parent))
            return ret;
    }
    return new QNativeSocketEngine(parent);
}

在函数createSocketEngine中依次循环调用socketHandlers()来创建QAbstractSocketEngine,这里的类型过滤是在具体的创建函数中,比如QHttpSocketEngineHandler::createSocketEngine。

6.总结

        虽然工厂模式并不复杂,但是要在实际项目中灵活运用,也不是一件容易的事,希望我的分享会对你更好的理解工厂模式。


网站公告

今日签到

点亮在社区的每一天
去签到