??設計模式之工廠模式(一)
????????在閱讀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 nowif (proxy.type() != QNetworkProxy::HttpProxy)return 0;// we only accept active socketsif (!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 nowif (proxy.type() == QNetworkProxy::DefaultProxy)return 0;
#endifQMutexLocker 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 hereif (proxy.type() != QNetworkProxy::NoProxy)return 0;
#endifreturn 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.總結
? ? ? ? 雖然工廠模式并不復雜,但是要在實際項目中靈活運用,也不是一件容易的事,希望我的分享會對你更好的理解工廠模式。