qidao123.com技术社区-IT企服评测·应用市场

标题: 设计模式之工厂模式(二):实际案例 [打印本页]

作者: 民工心事    时间: 5 天前
标题: 设计模式之工厂模式(二):实际案例
  设计模式之工厂模式(一)
          在阅读Qt网络部分源码时候,发现在某处运用了工厂模式,而且编程技巧也用的好,于是就想分享出来,供各人参考,理解的不对的地方请多多指点。
        以下是我整理出来的类图:

关键阐明:
1.Q_GLOBAL_STATIC(QSocketEngineHandlerList, socketHandlers)

   Qt实现单例模式:Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS_qt 单例宏-CSDN博客
  Q_GLOBAL_STATIC宏定义了一个全局变量,这个全局变量是定义在qabstractsocketengine.cpp中,它的定义如下:
  1. class QSocketEngineHandlerList : public QList<QSocketEngineHandler*>
  2. {
  3. public:
  4.     QMutex mutex;
  5. };
  6. Q_GLOBAL_STATIC(QSocketEngineHandlerList, socketHandlers)
复制代码
在cpp中定义,其它地方是访问不到这个全局变量,潜伏了实现,封装性比较好。
2.QAbstractSocketEngine和QHttpSocketEngine

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

这个类类似工厂模式中的工厂,它的定义如下:
  1. class Q_AUTOTEST_EXPORT QSocketEngineHandler
  2. {
  3. protected:
  4.     QSocketEngineHandler();
  5.     virtual ~QSocketEngineHandler();
  6.     virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType,
  7.                                                       const QNetworkProxy &, QObject *parent) = 0;
  8.     virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent) = 0;
  9. private:
  10.     friend class QAbstractSocketEngine;
  11. };
复制代码
  1. QSocketEngineHandler::QSocketEngineHandler()
  2. {
  3.     if (!socketHandlers())
  4.         return;
  5.     QMutexLocker locker(&socketHandlers()->mutex);
  6.     socketHandlers()->prepend(this);
  7. }
  8. QSocketEngineHandler::~QSocketEngineHandler()
  9. {
  10.     if (!socketHandlers())
  11.         return;
  12.     QMutexLocker locker(&socketHandlers()->mutex);
  13.     socketHandlers()->removeAll(this);
  14. }
复制代码
从上面的代码可以看出,在QSocketEngineHandler的构造函数和析构函数分别去注册和移除工厂,让继续QSocketEngineHandler的类也不消暴露socketHandlers,这个地方也是写的比较奇妙的地方。
4.QHttpSocketEngineHandler

具体的工厂类,负责生产QHttpSocketEngine,代码如下:
  1. class Q_AUTOTEST_EXPORT QHttpSocketEngineHandler : public QSocketEngineHandler
  2. {
  3. public:
  4.     virtual QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType,
  5.                                                       const QNetworkProxy &, QObject *parent) override;
  6.     virtual QAbstractSocketEngine *createSocketEngine(qintptr socketDescripter, QObject *parent) override;
  7. };
复制代码
  1. QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(QAbstractSocket::SocketType socketType,
  2.                                                                     const QNetworkProxy &proxy,
  3.                                                                     QObject *parent)
  4. {
  5.     if (socketType != QAbstractSocket::TcpSocket)
  6.         return 0;
  7.     // proxy type must have been resolved by now
  8.     if (proxy.type() != QNetworkProxy::HttpProxy)
  9.         return 0;
  10.     // we only accept active sockets
  11.     if (!qobject_cast<QAbstractSocket *>(parent))
  12.         return 0;
  13.     QHttpSocketEngine *engine = new QHttpSocketEngine(parent);
  14.     engine->setProxy(proxy);
  15.     return engine;
  16. }
  17. QAbstractSocketEngine *QHttpSocketEngineHandler::createSocketEngine(qintptr, QObject *)
  18. {
  19.     return 0;
  20. }
复制代码
5.createSocketEngine()

在QAbstractSocketEngine类有两个静态函数,就是生产对象的入口:
  1. class Q_AUTOTEST_EXPORT QAbstractSocketEngine : public QObject
  2. {
  3.     Q_OBJECT
  4. public:
  5.     static QAbstractSocketEngine *createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &, QObject *parent);
  6.     static QAbstractSocketEngine *createSocketEngine(qintptr socketDescriptor, QObject *parent);
  7.     QAbstractSocketEngine(QObject *parent = 0);
  8.     ...
  9. };
复制代码
  1. QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(QAbstractSocket::SocketType socketType, const QNetworkProxy &proxy, QObject *parent)
  2. {
  3. #ifndef QT_NO_NETWORKPROXY
  4.     // proxy type must have been resolved by now
  5.     if (proxy.type() == QNetworkProxy::DefaultProxy)
  6.         return 0;
  7. #endif
  8.     QMutexLocker locker(&socketHandlers()->mutex);
  9.     for (int i = 0; i < socketHandlers()->size(); i++) {
  10.         if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketType, proxy, parent))
  11.             return ret;
  12.     }
  13. #ifndef QT_NO_NETWORKPROXY
  14.     // only NoProxy can have reached here
  15.     if (proxy.type() != QNetworkProxy::NoProxy)
  16.         return 0;
  17. #endif
  18.     return new QNativeSocketEngine(parent);
  19. }
  20. QAbstractSocketEngine *QAbstractSocketEngine::createSocketEngine(qintptr socketDescripter, QObject *parent)
  21. {
  22.     QMutexLocker locker(&socketHandlers()->mutex);
  23.     for (int i = 0; i < socketHandlers()->size(); i++) {
  24.         if (QAbstractSocketEngine *ret = socketHandlers()->at(i)->createSocketEngine(socketDescripter, parent))
  25.             return ret;
  26.     }
  27.     return new QNativeSocketEngine(parent);
  28. }
复制代码
在函数createSocketEngine中依次循环调用socketHandlers()来创建QAbstractSocketEngine,这里的范例过滤是在具体的创建函数中,比如QHttpSocketEngineHandler::createSocketEngine。
6.总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4