设计模式概念学习

2023-11-18


以下为学习时对各种设计模式的简单理解,还没有深入学习和实际应用,推荐1个 很棒的网站学习设计模式,每个模式都有遇到的痛点和解决的方法,还有2~3个应用场景,各种语言的代码示例,简明准确的UML类图,精美可爱的配图,推荐大家去看。

创建类型

单例模式

饿汉

构建时就创建

懒汉

  1. 单线程-访问到的时候才创建
  2. 多线程-低效率
    做法:加锁->若未创建则创建->获取资源->解锁
    缺点:效率低,每次访问之前都要加锁,资源创建之后不能被同时被多个线程访问
  3. 多线程-双重判断
    做法:判断资源未存在->加锁->二次判断资源未存在->创建资源->解锁->获取资源
    原因:先判断资源是否存在,只有第1次判断到资源不存在才需要加锁,当资源创建之后就不用再加锁了,多线程在大部分情况下可同时访问,提高资源访问效率;在加锁之后需要再次判断资源是否存在,可能在第1次判断和拿到锁的时间间隙中资源已经被其他线程访问和创建了,因此需要二次判断。

openbmc项目实际应用

在bmcweb/include/sessions.hpp中,有1个类用来管理web session的类SessionStore。其创建方式就是单例模式,且是第一次使用到这个对象才会创建这个对象:

class SessionStore
{
  public:
    static SessionStore& getInstance()
    {
        static SessionStore sessionStore;
        return sessionStore;
    }
    ...
};

其他类需要用到此类方法时,都需通过getInstance()方法来获得SessionStore类唯一的对象sessionStore,如有1个用户登录web之后,需要新增1个web session,则需要通过getInstance()方法,将新的web session的信息保留在SessionStore唯一的对象中:

    // User is authenticated - create session
    std::shared_ptr<persistent_data::UserSession> session =
        persistent_data::SessionStore::getInstance().generateUserSession(
            username, req.ipAddress, clientId,
            persistent_data::PersistenceType::TIMEOUT, isConfigureSelfOnly);

项目中为什么使用单例模式呢?

  1. 作为全局管理对象:SessionStore作为管理类,起到的是全局统领的作用,只需要1个对象就够了,多个对象反而使管理变得混乱
  2. 节约资源:SessionStore中保存着所有web session的信息,若可创建多个对象,则会引起相同web session拷贝,session发生变化还要使用一些同步机制保证不同SessionStore对象的同步。
  3. 统一文件的访问:在关闭BMC前可能连接着一些web session,关闭前需要将这些数据保存到起来,重启后要重新获取,单例保证只有1个对象对文件进行读写,避免重复读写。

工厂方法

当多种产品都继承于同1个基类,如美的空调和海尔空调都继承空调类,则可使用工厂方法。让多个工厂类继承于同1个工厂基类,对应去生产不同产品。

简单工厂方法

参考链接
多种产品继承同1个基类,可创建1个工厂类,根据不同的参数,以调用不同产品类的构造函数,来创建出不同的产品

openbmc项目实际应用

phosphor-pid-control是风扇控制模块,根据当前温度传感器/风扇转速/调速参数,使用PID算法来设置风扇目标转速。此模块中的主要类图如下:

  1. Controller:控制器,为纯虚类,作用是通过inputProc获取输入值,通过process和获得的输入值以计算输出值,通过outputProc让输出值起作用。
  2. PIDController:PID控制器,将输入值和目标值作为PID算法的参数,以获取输出值。
  3. StepwiseController:简单的温度控制器,维护1个阶梯式的温度-转速的表格,每个温度范围对应1个目标转速。输入值为多个传感器温度的最大值,输出值为最大温度对应的目标转速,会将目标转速交给FanController处理。
  4. ThermalController:温度控制器,采用PID算法,将所有温度传感器获得的最大温度作为输入值,但不设目标值,根据PID算法计算最终的目标转速,会将目标转速交给FanController处理。
  5. FanController:风扇控制器,采用PID算法,将所有温度控制器获得的目标转速的最大值作为目标值,将风扇当前值作为输入值,根据PID算法计算最终的目标转速,并将此值写入风扇背板的CPLD寄存器中,最终控制风扇转速。
  6. zone:将物理区域抽象成1个类,每个区域都有一至多个硬件温度传感器和风扇,一至多个虚拟温度控制器和风扇控制,控制风扇转速以确保每个区域的硬件在适宜温度内。
Controller
+inputProc() : double
+outputProc(value)
+process()
ThermalController
+createThermalPid(...) : ThermalController
StepwiseController
+createStepwiseController(...) : StepwiseController
FanController
+createFanPid(...) : FanController
PIDController
+setptProc() : double
Zone
-Controller[] _fans
-Controller[] _thermals
+addFanPID()
+addThermalPID()

在phosphor-pid-control/pid/builder.cpp中的buildZones函数,用来创建zone对象,根据json文件中的控制器类型的配置值来决定创建的控制器类型。创建zone的函数其实就可以视为1个简单工厂,创建控制器对象时,获取的参数均是用户在json文件中的配置。

std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>>
    buildZones(...)
{
		...
        // For each PID create a Controller and a Sensor.
        for (const auto& [name, info] : pidConfig)
        {
        	...
            if (info.type == "fan")
            {
            	...
                auto pid = FanController::createFanPid(zone.get(), name, inputs,
                                                       info.pidInfo);
				zone->addFanPID(std::move(pid));
            	...
            }
            else if (isThermalType(info.type))
            {
            	...
                auto pid = ThermalController::createThermalPid(
                    zone.get(), name, inputs, info.setpoint, info.pidInfo,
                    getThermalType(info.type));
                zone->addThermalPID(std::move(pid));
            	...
            }
            else if (info.type == "stepwise")
            {
            	...
                auto stepwise = StepwiseController::createStepwiseController(
                    zone.get(), name, inputs, info.stepwiseInfo);
                zone->addThermalPID(std::move(stepwise));
               ...
            }
    }
}

创建具体控制器对象方法的createXXXController其实是每个控制器类的静态成员函数。

static std::unique_ptr<Controller> StepwiseController::createStepwiseController(
    ZoneInterface* owner, const std::string& id,
    const std::vector<std::string>& inputs, const ec::StepwiseInfo& initial)
{
    // StepwiseController requires at least 1 input
    if (inputs.empty())
    {
        throw ControllerBuildException("Stepwise controller missing inputs");
    }

    auto thermal = std::make_unique<StepwiseController>(id, inputs, owner);
    thermal->setStepwiseInfo(initial);

    return thermal;
}

为什么这个场景像简单工厂模式:

  1. 系统耦合度较低:用户想创建控制器对象时,只需要根据规范,在json文件中配置控制器的属性如下:type"fan"则会创建1个风扇控制器,不用关注任何代码层面的细节,而且所有控制器。根本就不是了啦!
"pids": [
    {
        "name": "fan1-5",
        "type": "fan",
        "inputs": ["fan1", "fan5"],
        "setpoint": 90.0,
    }
]

抽象工厂

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式概念学习 的相关文章

随机推荐

  • struts验证框架

    关于validation xml 在validator xml中使用了validation rules xml的验证规则注意一定要加其已经定义好的出错消息考到你的资源包里去 否则出错的时候 显示错误对话框里面却什么错误消息都没有 不允许发生
  • MySQL自动重新连接

    最近部署一个系统 后台用线程池来处理请求 而每个线程有一个mysql连接 当系统运行一阶段后 有些请求会出现操作 Internal error 而操作一次可能又会成功 经过多方调试 发现是MySQL连接超时 如果使用了长连接而长期没有对数据
  • Qt程序Release版出现 类似 QEventLoop: Cannot be used without QApplication 问题的终极解决方案

    Qt程序Release版出现 类似 QEventLoop Cannot be used without QApplication 问题的终极解决方案 参考文章 1 Qt程序Release版出现 类似 QEventLoop Cannot be
  • 初学者学习安装Vmware正版软件

    目录 一 获取下载安装 二 安装图文步骤 三 可能出现问题 2分钟无脑 快速安装Vmware 一 获取下载安装 首先说明 官网下载需要登入账号 最新版可以下载试用版 不需要账号 下述为官网的下载路径图示 仅供参考 注意 目前下载都需要账号了
  • Linux系统Could not connect to '192.168.128.XXX' (port 22): Connection failed.

    网上查找了方法 都是 查看防火墙 service iptables status 关闭防火墙 service iptables stop 打开防火墙 service iptables start 打开sshd service sshd st
  • zigbee串口打印无法显示或乱码解决方法

    zigbee串口打印问题 在终端节点向协调器发数据时 在数据流中伴有该节点的网络地址 而有时通过PC端无法打印出来 1 可能是串口软件的问题 用过好几个串口软件 有时会出现停止 或乱码行为 在经过多次换用软件 发现 SecureCRT 这个
  • uni-app watch事件监听三种用法

    1 普通监听 无法监听到第一次绑定的变化
  • stm32----用状态机判断单双击

    一 什么是状态机 状态机 State Machine 是一种用于描述系统状态和状态之间转换关系的数学模型 说白了就是做出某个动作之后变成什么样的状态 比如stm32中的按键控制开关灯 假设灯一开始是关的 当我们按下按键之后 灯亮了 这相当于
  • REST API 设计最佳实践:如何正确使用 HTTP 状态码?

    总的来说 HTTP协议出现以来Web服务也就存在了 但是 自从云计算出现后 才成为实现客户端与服务和数据交互的普遍方法 作为一名开发者 我很幸运能够在工作中使用一些仍然存在的SOAP服务 但是 我主要接触的是REST 这是一种基于资源的AP
  • dev express for asp.net 如何更换主题

    1 如下图点击菜单 2 选择主题然后按 Update Project
  • Python——协程(Coroutine),异步IO

    目录 生成器 Generator yield表达式的使用 生产者和消费者模型 编辑 yield from表达式 协程 Coroutine asyncio coroutine async await 总结 由于GIL的存在 导致Python多
  • Java FileReader

    Java FileReader Java FileReader Java FileReader class is part of java io package Java FileReader类是java io软件包的一部分 The Fil
  • Android自动化测试,5个必备的测试框架

    Appium Appium是一个开源的移动测试工具 支持iOS和Android 它可以用来测试任何类型的移动应用 原生 网络和混合 作为一个跨平台的工具 你可以在不同的平台上运行相同的测试 为了实现跨平台的功能 Appium使用了供应商提供
  • python 抖音采集_python爬取抖音视频的实例详解

    import requests import json import re import os from pprint import pprint as pp import queue class DouYin header accept
  • 全书简介和作者寄语

    巨硬的NumPy 巨硬的NumPy 教程包括两部分 从小白到入门 和 从入门到熟练 从小白到入门 旨在帮助没有基础的同学快速掌握 numpy 的常用功能 保证日常绝大多数场景的使用 从入门到熟练 目的是帮助有进一步需要的同学对 numpy
  • (六)Kubernetes - 手动部署(二进制方式安装)

    Kubernetes 手动部署 5 1 部署Nginx Keepalived高可用负载均衡器 1 1 安装软件包 Master1 Master2 1 2 Nginx配置文件 主备相同 1 3 keepalived配置文件 Master1 1
  • mysql jpa 不要自动建表,如何让Hibernate在与JPA一起使用时自动在数据库中创建表?...

    I am new to JPA And for now I am trying to understand standard examples I was reading online and saw a few stackoverflow
  • vue面试题汇总

    HTML篇 CSS篇 JS篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全 含答案超详细 HTML JS CSS汇总篇 持续更新 前端面试题汇总大全二 含答案超详细 Vue TypeScript React 微信小
  • pytorch---之item()

    torch Tensor item 坑 注意只能是一个值 适合返回loss acc
  • 设计模式概念学习

    文章目录 创建类型 单例模式 饿汉 懒汉 openbmc项目实际应用 工厂方法 简单工厂方法 openbmc项目实际应用 抽象工厂 以下为学习时对各种设计模式的简单理解 还没有深入学习和实际应用 推荐1个 很棒的网站学习设计模式 每个模式都