当前位置: 首页 > news >正文

CTK框架(六):服务工厂

目录

1.前言

2.实现方式

3.具体实现

4.注意事项


1.前言

        CTK框架(四): 插件编写-CSDN博客

        在之前讲过,写好的服务类PluginAImpl必须注册到服务中心,别的插件才能使用。

void PluginAActivator::start(ctkPluginContext* context)
{PluginAImpl* pluginAImpl = new PluginAImpl(context);context->registerService<PluginAService>(pluginAImpl);m_s.reset(pluginAImpl);
}

这种写法就是插件启动就把服务PluginAImpl注册到服务中心,不管这个服务其它地方使用还是不使用。如果没有地方使用它,这个服务就处理空闲状态,浪费系统资源。那么有没有什么其它办法使用它的时候才创建呢?有,那就是服务工厂。

        服务工厂其实就是懒汉式使用服务,需要的时候才去创建它。它的优点还有:

        1)延迟初始化:CTK服务工厂支持服务的延迟初始化,即在实际需要服务时才创建服务对象,这有助于减少应用程序启动时的资源消耗和提高性能。

        2)插件化支持:在插件化架构中,CTK服务工厂能够根据插件的元数据或请求参数为不同的插件提供不同的服务实例,增强了系统的灵活性和可扩展性。

        3)服务管理:通过服务工厂,开发人员可以更方便地注册、获取和释放服务,简化了服务的管理过程。

2.实现方式

1.定义服务接口:首先定义一个或多个服务接口,这些接口包含了服务需要实现的方法。

2.实现服务接口:为每种服务实现创建具体的类,这些类实现了服务接口中定义的方法。

3.创建服务工厂:实现ctkServiceFactory接口,在接口实现中根据插件的元数据或请求参数返回相应的服务实例。

4.注册服务工厂:在插件的激活类中,将服务工厂注册为服务,以便在需要时可以通过服务注册中心获取服务实例。

3.具体实现

以打印为例,提供三种服务,分别是:直接打印、打印后加3个点、加上时间戳打印

①接口类

PluginAService.h

#ifndef PLUGINASERVICE_H
#define PLUGINASERVICE_H
#include <QtPlugin>class PluginAService
{
public:virtual ~PluginAService() {}virtual void A_Func() = 0;
};#define PluginAService_iid "org.commontk.service.demos.PluginAService"
Q_DECLARE_INTERFACE(PluginAService, PluginAService_iid)
//此宏将当前这个接口类声明为接口,后面的一长串就是这个接口的唯一标识。#endif // PLUGINASERVICE_H

②直接打印实现类

PluginAImpl.h

#ifndef PLUGINAIMPL_H
#define PLUGINAIMPL_H#include "PluginAService.h"
#include <QObject>class ctkPluginContext;class PluginAImpl : public QObject, public PluginAService
{Q_OBJECTQ_INTERFACES(PluginAService)/*此宏与Q_DECLARE_INTERFACE宏配合使用。Q_DECLARE_INTERFACE:声明一个接口类Q_INTERFACES:当一个类继承这个接口类,表明需要实现这个接口类*/
public:PluginAImpl(ctkPluginContext* context);void A_Func() Q_DECL_OVERRIDE;
};#endif // PLUGINAIMPL_H

PluginAImpl.cpp

#include "PluginAImpl.h"
#include <QtDebug>PluginAImpl::PluginAImpl(ctkPluginContext* context)
{}void PluginAImpl::A_Func()
{qDebug() << "A_Func()";
}

③打印后加3个点实现类

PluginAImplD.h

#ifndef PLUGINAIMPLD_H
#define PLUGINAIMPLD_H#include "PluginAService.h"
#include <QObject>class ctkPluginContext;class PluginAImplD : public QObject, public PluginAService
{Q_OBJECTQ_INTERFACES(PluginAService)/*此宏与Q_DECLARE_INTERFACE宏配合使用。Q_DECLARE_INTERFACE:声明一个接口类Q_INTERFACES:当一个类继承这个接口类,表明需要实现这个接口类*/
public:PluginAImplD(ctkPluginContext* context);void A_Func() Q_DECL_OVERRIDE;
};#endif // PLUGINAIMPLD_H

PluginAImplD.cpp

#include "PluginAImplD.h"
#include <QtDebug>PluginAImplD::PluginAImplD(ctkPluginContext* context)
{}void PluginAImplD::A_Func()
{qDebug() << "A_Func() ...";
}

④加上时间戳打印实现类

PluginAImplT.h

#ifndef PLUGINAIMPLT_H
#define PLUGINAIMPLT_H#include "PluginAService.h"
#include <QObject>class ctkPluginContext;class PluginAImplT : public QObject, public PluginAService
{Q_OBJECTQ_INTERFACES(PluginAService)/*此宏与Q_DECLARE_INTERFACE宏配合使用。Q_DECLARE_INTERFACE:声明一个接口类Q_INTERFACES:当一个类继承这个接口类,表明需要实现这个接口类*/
public:PluginAImplT(ctkPluginContext* context);void A_Func() Q_DECL_OVERRIDE;
};#endif // PLUGINAIMPLT_H

PluginAImplT.cpp

#include "PluginAImplT.h"
#include <QtDebug>
#include <QTime>PluginAImplT::PluginAImplT(ctkPluginContext* context)
{}void PluginAImplT::A_Func()
{qDebug() << QTime::currentTime().toString("HH:mm:ss    ") << "A_Func()";
}

⑤服务工厂类

servicefactory.h

#ifndef SERVICEFACTORY_H
#define SERVICEFACTORY_H
#include <QObject>
#include "PluginAImpl.h"
#include "PluginAImplD.h"
#include "PluginAImplT.h"
#include "ctkServiceFactory.h"class ServiceFactory : public QObject, public ctkServiceFactory
{Q_OBJECTQ_INTERFACES(ctkServiceFactory)
public:ServiceFactory();QObject* getService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration) override;void ungetService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration,QObject* service) override;
};#endif // SERVICEFACTORY_H

servicefactory.cpp

#include "servicefactory.h"
#include "ctkPlugin.h"
#include "ctkPluginConstants.h"
#include <QDebug>
ServiceFactory::ServiceFactory()
{}QObject *ServiceFactory::getService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration)
{Q_UNUSED(registration)QHash<QString,QString> headers = plugin->getHeaders();ctkVersion version = ctkVersion::parseVersion(headers.value(ctkPluginConstants::PLUGIN_VERSION));QString name = headers.value(ctkPluginConstants::PLUGIN_NAME);QString symbolicName = headers.value(ctkPluginConstants::PLUGIN_SYMBOLICNAME);Q_UNUSED(version) //暂时没使用到Q_UNUSED(name)QObject* obj;if(symbolicName == "PluginAImpl"){obj = new PluginAImpl;}else if(symbolicName == "PluginAImplD"){obj  = new PluginAImplD;}else{obj  = new PluginAImplT;}return obj;
}void ServiceFactory::ungetService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration, QObject *service)
{Q_UNUSED(plugin)Q_UNUSED(registration)Q_UNUSED(service)
}

⑥激活类

PluginAActivator.h

#ifndef PLUGINAACTIVATOR_H
#define PLUGINAACTIVATOR_H
#include <QObject>
#include "ctkPluginActivator.h"
#include "servicefactory.h"class PluginAActivator : public QObject, public ctkPluginActivator
{Q_OBJECTQ_INTERFACES(ctkPluginActivator)Q_PLUGIN_METADATA(IID "PLUGINA")//向Qt的插件框架声明,希望将xxx插件放入到框架中。
public:void start(ctkPluginContext* context);void stop(ctkPluginContext* context);private:QSharedPointer<ServiceFactory> m_s;
};
#endif // PLUGINAACTIVATOR_H

PluginAActivator.cpp

#include "PluginAActivator.h"
#include <QDebug>void PluginAActivator::start(ctkPluginContext* context)
{ServiceFactory* s = new ServiceFactory;context->registerService<PluginAService>(s);factory.reset(s);
}void PluginAActivator::stop(ctkPluginContext* context)
{Q_UNUSED(context)//Q_UNUSED,如果一个函数的有些参数没有用到、某些变量只声明不使用,但是又不想编译器、编辑器报警报,其他没有什么实际性作用
}

调用的方式,服务工厂和非服务工厂都是一样的,就不在这里赘述了。

4.注意事项

1)服务稳定性:由于服务是动态获取的,因此在使用服务时需要注意服务的稳定性,避免因服务不可用而导致的错误。

2)性能考虑:虽然延迟初始化可以提高性能,但在某些场景下,如果服务频繁被请求且初始化时间较长,可能会对性能产生影响。

3)安全性:在提供服务时,需要考虑服务的安全性,确保服务不会被恶意调用或滥用。

        综上所述,CTK服务工厂是CTK框架中一个非常有用的功能,它为开发者提供了一种灵活、高效的服务管理工具,有助于构建更加模块化、可扩展和可维护的应用程序。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 本地搭建 Whisper 语音识别模型
  • 万能无线航模模拟器加密狗说明书
  • 图像与文本并存,多模态检索如何带来新的搜索革命
  • Linux:目录及文件管理
  • Parsec问题解决方案
  • 猜测、实现 B 站在看人数
  • WinCC V7.5与S7-1200 PLC 通信
  • Linux学习-Ansible(一)
  • 自建,前端sdk库(react-utils-dev-sdk)
  • C++入门项目:Linux下C++轻量级Web服务器 跑通|运行|测试(小白进)
  • android kotlin基础复习 enum
  • 【C++】_list常用方法解析及模拟实现
  • 高级java每日一道面试题-2024年9月05日-数据库篇-谈一下聚集索引和非聚集索引?
  • SQL server 删除重复行
  • 〖open-mmlab: MMDetection〗解析文件:mmdet/models/detectors/two_stage.py
  • $translatePartialLoader加载失败及解决方式
  • “大数据应用场景”之隔壁老王(连载四)
  • 4. 路由到控制器 - Laravel从零开始教程
  • angular组件开发
  • Babel配置的不完全指南
  • docker-consul
  • Java多态
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • JS实现简单的MVC模式开发小游戏
  • LeetCode18.四数之和 JavaScript
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Promise初体验
  • windows下mongoDB的环境配置
  • 京东美团研发面经
  • 开源地图数据可视化库——mapnik
  • 使用parted解决大于2T的磁盘分区
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 小试R空间处理新库sf
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 正则表达式
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • 我们雇佣了一只大猴子...
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • # 达梦数据库知识点
  • #预处理和函数的对比以及条件编译
  • (160)时序收敛--->(10)时序收敛十
  • (2)Java 简介
  • (6) 深入探索Python-Pandas库的核心数据结构:DataFrame全面解析
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (done) 两个矩阵 “相似” 是什么意思?
  • (js)循环条件满足时终止循环
  • (第二周)效能测试
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (三)Kafka 监控之 Streams 监控(Streams Monitoring)和其他
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424