设计模式实现之state模式

news2024/11/20 19:43:58

状态模式的定义:Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.(当一个对象在状态改变时允许其改变行为,这个对象看起来像其改变了其类)。

一个对象可以在声明周期内修改自己的状态,但是却不能在生命周期内修改自己所属的类。运用状态模式,可以得到一个优雅的折衷。

状态模式的核心是封装,状态的变化引起了行为俄变更,从外部看起来就像是这个对象对应的类发生了改变一样,状态模式的通用类图如下图所示:

state:抽象状态角色,为接口或者抽象类,负责对象操作接口的定义,并且封装环境角色以实现状态切换。

concretestate:具体状态角色,每一个具体状态必须完成两个职责,本状态的行为管理以及趋向状态管理,通俗的讲,就是本状态下要做的事情,以及本状态如何过渡到其它状态。

context:定义客户端需要的接口,并且负责具体状态的切换,是使用状态的一方。

Client:用户程序,main函数等等,可以看作是舞台,场景类。

 本用例状态模式UML类图:

状态模式代码实现:

#include <thread>
#include <memory>
#include <mutex>
#include <iostream>

class wrapper
{
public:
    wrapper(int x, int y) {
	this->obj1 = x;
	this->obj2 = y;
	//sta = new state1(1);
        sta = std::make_shared<state1>(1);
	std::cout << __func__ << __LINE__ << std::endl;
    }

    ~wrapper(void) {
	//delete sta;
	std::cout << __func__ <<"  "<< __LINE__ << std::endl;
    }

    void member1() {
        while(1) {
	    m.lock();
	    r_m.lock();
            std::cout << "i am member1 " << "obj1 = " << this->obj1 << " obj2 = " << this->obj2 << " id " << std::this_thread::get_id() << std::endl;
	    r_m.unlock();
	    m.unlock();
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }

    void member2(const char *arg1, unsigned arg2) {
        while(1) {
	    m.lock();
	    r_m.lock();
            std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
	    sta->show_state(*this);
	    r_m.unlock();
	    m.unlock();
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }

    std::thread member1thread() {
	std::thread th1;
        th1 = std::thread(&wrapper::member1, this);
	return th1;
    }

    std::thread member2thread(const char *arg1, unsigned arg2) {
        return std::thread(&wrapper::member2, this, arg1, arg2);
    }

    int test_member_function(void)
    {
	return this->obj1 + this->obj2;
    }

    void state_verbose(void)
    {
	sta->show_state(*this);
    }

    class state
    {
      public:
        virtual void show_state(wrapper &w) = 0;
    };
    
    void set_state(std::shared_ptr<wrapper::state> s)
    {
	sta = s;
    }

    class state1: public state
    {
      public:
        state1(int st)
	{
	    test1 = st;
	}
        void show_state(wrapper &w)
        {
    	    std::cout << "now in state 1" << std::endl;
            std::shared_ptr<wrapper::state> s = std::make_shared<state2>(2);
            w.set_state(s);
	    w.state_verbose();
        }
    
      private:
        int test1;
    };
    
    class state2: public state
    {
      public:
        state2(int st)
	{
	    test2 = st;
	}

        void show_state(wrapper &w)
        {
    	    std::cout << "now in state 2" << std::endl;
            std::shared_ptr<wrapper::state> s = std::make_shared<state3>(3);
            w.set_state(s);
	    w.state_verbose();
        }
    
      private:
        int test2;
    };
    
    class state3: public state
    {
      public:
        state3(int st)
	{
	    test3 = st;
	}

        void show_state(wrapper &w)
        {
            std::cout << "now in state 3" << std::endl;
            std::shared_ptr<wrapper::state> s = std::make_shared<state1>(1);
            w.set_state(s);
	    //w.state_verbose();
        }
    
      private:
       int test3;
    };

private:
    int obj1;
    int obj2;
    std::mutex m;
    std::recursive_mutex r_m;
    //class state *sta;
    std::shared_ptr<wrapper::state> sta;
};

void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "thread " << n << " executing\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main(void)
{
    int ret;
    //wrapper *w = new wrapper(1, 2);
    //std::shared_ptr<wrapper> w = std::make_shared<wrapper>(1, 2);
    auto w = std::make_shared<wrapper>(1, 2);

    std::thread tw1 = w->member1thread();
    ret = w->test_member_function();
    std::thread tw2 = w->member2thread("helloworld", 6);

    std::thread t2(f1, 6); // pass by value

    std::cout << "after starting, tw1 joinable: " << tw1.joinable() << " id " << tw1.get_id() << std::endl;
    std::cout << "after starting, tw2 joinable: " << tw2.joinable() << " id " << tw2.get_id() << std::endl;
    std::cout << "after starting, t2 joinable:  " << t2.joinable()  << " id " << t2.get_id() << std::endl;

    std::thread tw3 = w->member2thread("hello", 100);
    tw3.detach();
    std::cout << "after starting, tw3 joinable: " << tw3.joinable() << std::endl;

    t2.join();
    tw1.join();
    tw2.join();

    return 0; 
}
$ g++ -std=c++11 -O0 -g3 model.cpp -lpthread

make_shared会调用构造函数:

make_shared析构

#include <thread>
#include <memory>
#include <mutex>
#include <iostream>
 
class wrapper
{
public:
    wrapper(int x, int y) {
	this->obj1 = x;
	this->obj2 = y;
	//sta = new state1(1);
        sta = std::make_shared<state1>(1);
	std::cout << __func__ <<"  "<<__LINE__ << std::endl;
    }
 
    ~wrapper(void) {
	//delete sta;
	std::cout << __func__ <<"  "<< __LINE__ << std::endl;
    }
 
    void member1(void) {
        while(1)
	{
	    m.lock();
	    r_m.lock();
            std::cout << "i am member1 " << "obj1 = " << this->obj1 << " obj2 = " << this->obj2 << " id " << std::this_thread::get_id() << std::endl;
	    r_m.unlock();
	    m.unlock();
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
 
    void member2(const char *arg1, unsigned arg2) {
        while(1)
	{
	    m.lock();
	    r_m.lock();
            std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
	    sta->show_state(*this);
	    r_m.unlock();
	    m.unlock();
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
 
    std::thread member1thread(void) {
	std::thread th1;
        th1 = std::thread(&wrapper::member1, this);
	return th1;
    }
 
    std::thread member2thread(const char *arg1, unsigned arg2) {
        return std::thread(&wrapper::member2, this, arg1, arg2);
    }
 
    int test_member_function(void)
    {
	return this->obj1 + this->obj2;
    }
 
    void state_verbose(void)
    {
	sta->show_state(*this);
    }
 
    class state
    {
      public:
        virtual void show_state(wrapper &w) = 0;
    };
    
    void set_state(std::shared_ptr<wrapper::state> s)
    {
	sta = s;
    }
 
    class state1: public state
    {
      public:
        state1(int st)
	{
	    test1 = st;
	    std::cout << __func__ <<"  "<<__LINE__ << std::endl;
	}
        ~state1(void) {
	    std::cout << __func__ <<"  "<<__LINE__ << std::endl;
	}

        void show_state(wrapper &w)
        {
    	    std::cout << "now in state 1" << std::endl;
            std::shared_ptr<wrapper::state> s = std::make_shared<state2>(2);
            w.set_state(s);
	    w.state_verbose();
        }
    
      private:
        int test1;
    };
    
    class state2: public state
    {
      public:
        state2(int st)
	{
	    test2 = st;
	    std::cout << __func__ <<"  "<<__LINE__ << std::endl;
	}

        ~state2(void) {
	    std::cout << __func__ <<"  "<<__LINE__ << std::endl;
	}
 
        void show_state(wrapper &w)
        {
    	    std::cout << "now in state 2" << std::endl;
            std::shared_ptr<wrapper::state> s = std::make_shared<state3>(3);
            w.set_state(s);
	    w.state_verbose();
        }
    
      private:
        int test2;
    };
    
    class state3: public state
    {
      public:
        state3(int st) {
	    test3 = st;
	    std::cout << __func__ <<"  "<<__LINE__ << std::endl;
	}

        ~state3(void) {
	    std::cout << __func__ <<"  "<<__LINE__ << std::endl;
	}
 
        void show_state(wrapper &w)
        {
            std::cout << "now in state 3" << std::endl;
            std::shared_ptr<wrapper::state> s = std::make_shared<state1>(1);
            w.set_state(s);
	    //w.state_verbose();
        }
    
      private:
       int test3;
    };
 
private:
    int obj1;
    int obj2;
    std::mutex m;
    std::recursive_mutex r_m;
    //class state *sta;
    std::shared_ptr<wrapper::state> sta;
};
 
void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "thread " << n << " executing\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
 
int main(void)
{
    int ret;
    //wrapper *w = new wrapper(1, 2);
    //std::shared_ptr<wrapper> w = std::make_shared<wrapper>(1, 2);
    auto w = std::make_shared<wrapper>(1, 2);
 
    std::thread tw1 = w->member1thread();
    ret = w->test_member_function();
    std::thread tw2 = w->member2thread("helloworld", 6);
 
    std::thread t2(f1, 6); // pass by value
 
    std::cout << "after starting, tw1 joinable: " << tw1.joinable() << " id " << tw1.get_id() << std::endl;
    std::cout << "after starting, tw2 joinable: " << tw2.joinable() << " id " << tw2.get_id() << std::endl;
    std::cout << "after starting, t2 joinable:  " << t2.joinable()  << " id " << t2.get_id() << std::endl;
 
    std::thread tw3 = w->member2thread("hello", 100);
    tw3.detach();
    std::cout << "after starting, tw3 joinable: " << tw3.joinable() << std::endl;
 
    t2.join();
    tw1.join();
    tw2.join();
 
    return 0; 
}

智能指针

智能指针是一种RAll(资源获取即初始化)机制,用于在使用完动态分配的内存后,自动释放内存。防止内存泄漏,C++11标准引入了两种智能指针,std::unique_ptr和std::shared_ptr。

std::unique_ptr是独占指针,只能有一个智能指针拥有资源,不能复制和共享,当unique_ptr被销毁时,它所管理的资源也会被自动释放,使用std::move将unique_ptr的所有权转移给另一个unique_ptr.

std::shared_ptr,可以被多个智能指针共享,每个共享指针都维护一个引用记数,当引用记数为0时,自动释放资源,使用std::make_shared创建shared_ptr.

智能指针的实现原理可以分为两个主要部分,资源管理和拷贝控制。

资源管理:智能指针中需要管理指向动态分配内存的原始指针,通常是通过在构造函数中分配内存,在析构函数中释放内存来实现的。智能指针还需要提供一个可以访问被管理的对象的方法,通常是通过重载解引用运算符(*)和箭头运算符(->)来实现的。

拷贝控制:

智能指针需要对拷贝,赋值等操作进行控制,以确保资源被正确管理,常见的做法是使用引用计数来记录共享的指针数量,并且在拷贝或赋值时增加或减少引用计数,当引用计数减少到0时,智能指针会自动销毁所管理的对象。

不同类型的智能指针实现方式有所不同,例如std::unique_ptr使用独占语义,禁止复制和共享,因此没有引用计数的实现。而std::shared_ptr使用共享语义,需要引用计数来实现多个智能指针共享同一份资源。

参考文章

RALL 与 智能指针-CSDN博客


结束

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/454515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KVM Bridge 配置

目录 Bridge方式原理 网桥方式配置步骤 1、编辑修改网络设备脚本文件&#xff0c;增加网桥设备br0 2、编辑修改网络设备脚本文件&#xff0c;修改网卡设备ens33 3、重启宿主机查看配置 虚拟机配置 Bridge方式原理 如上图&#xff0c;网桥的基本原理就是创建一个网桥并将…

IOC使用Spring实现附实例详解

目录 一、相关导读 1. Maven系列专栏文章 2. Mybatis系列专栏文章 3. Spring系列专栏文章 二、前言 Spring简介 Spring体系结构 三、Spring实现IOC 1. 创建Maven工程&#xff0c;引入对应依赖 2. 创建实体类&#xff0c;Dao接口及实现类 3. 编写xml配置文件 4. 测试…

【翻译一下官方文档】之uniapp基础内容

目录 表单控件绑定 v-model v-model结合表单 easycom组件规范 传值 prop emit 表单控件绑定 v-model 你可以用 v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇&#xff0c;但 v-mo…

如何高效提高倾斜摄影三维模型顶层合并的技术方法分析

如何高效提高倾斜摄影三维模型顶层合并的技术方法分析 1、倾斜摄影三维模型顶层合并 1.1倾斜摄影三维模型是一种基于倾斜摄影技术&#xff0c;通过多个角度拍摄同一区域的影像&#xff0c;利用计算机图像处理和三维重建技术生成的三维地理信息数据。由于一个大区域可能需要多块…

智能家居代码架构---简单工厂模式

(11条消息) 智能家居 (10) ——人脸识别祥云平台编程使用(编译libcurl库支持SSL&#xff0c;安装SSL依赖库libssl、libcrypto)openssl 依赖库行稳方能走远的博客-CSDN博客 看上面这个博客的往期文章 代码设计经验的总结&#xff0c;稳定&#xff0c;拓展性更强。一系列编程思…

倾斜摄影三维模型格式转换OSGB 到3Dtitles 实现的常用技术方法

倾斜摄影三维模型格式转换OSGB 到3Dtitles 实现的常用技术方法 倾斜摄影三维模型是一种用于建立真实世界三维场景的技术&#xff0c;常用于城市规划、土地管理、文化遗产保护等领域。在倾斜摄影模型中&#xff0c;OSGB格式和3Dtiles格式都是常见的数据格式。其中&#xff0c;OS…

IJKPLAYER源码分析-主结构

前言 本文主要分析IJKPLAYER源码软解主流程&#xff0c;硬解将另起一篇分析。所用IJKPLAYER版本号&#xff1a; #define IJKPLAYER_VERSION "f0.7.17-28-gd7040f97" 主结构 IJKPLAYER播放器的解协议、解复用、解码、音视频同步与显示播放&#xff0c;以及主要线程等…

智能家居项目整合(网络控制线程、语音控制线程,火灾报警线程)

mainPro.c&#xff08;主函数&#xff09; #include <stdio.h> #include <string.h> #include "contrlEquipments.h" #include "inputCommand.h" #include <pthread.h> #include <unistd.h>struct Equipment *findEquipByName(ch…

人工智能在医疗保健中的应用与创新

引言 随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;逐渐在各个领域展现出巨大的潜力&#xff0c;特别是在医疗保健行业。人工智能技术的引入为医疗保健领域带来了创新的诊断和治疗方法&#xff0c;提高了病患的生活质量和医疗保健效率。本文将探讨人工智…

倾斜摄影三维模型轻量化过程中遇到的常见问题分析,如何处理这些问题?

倾斜摄影三维模型轻量化过程中遇到的常见问题分析&#xff0c;如何处理这些问题&#xff1f; 在倾斜摄影超大场景的三维模型轻量化过程中&#xff0c;常见的问题包括&#xff1a; 1、精度损失。为了减小数据文件大小&#xff0c;轻量化处理可能会破坏原始数据的精度&#xff0…

数字未来:世界正走向新的“破茧时刻”

著名科学史专家亚历山大柯瓦雷&#xff0c;在《从封闭世界到无限宇宙》展示了一段非常神奇的历史现象&#xff1a;人类从笃信自己生活在一个封闭空间&#xff0c;到认识浩瀚无垠的宇宙&#xff0c;其实并没有耗费很长时间。自1543年哥白尼发布《天体运行论》&#xff0c;到牛顿…

基于深度学习和生理信号的疾病筛查:个体内和个体间研究的价值与应用

一、引言 随着深度学习技术的飞速发展&#xff0c;基于生理信号的疾病筛查和诊断方法在医学领域得到了广泛应用。这些方法通常利用个体内和个体间的生理信号数据&#xff0c;通过训练深度学习模型实现疾病的自动识别和预测。本文将讨论个体内和个体间研究在这一领域的价值和应…

Windows下virtualbox相关软件安装设置全过程

一、下载 virtual box 程序 virtual box扩展程序-Oracle_VM_VirtualBox_Extension_Pack-7.0.8.vbox-extpack Virtualbox GuestAdditions 程序-解决分辨率&#xff0c;主机虚拟机之间共享文件、剪贴板等问题 http://download.virtualbox.org/virtualbox/7.0.8/ 或者 virtual b…

倾斜摄影三维模型转换3DTILTES格式遇到的常见问题

倾斜摄影三维模型转换3DTILTES格式遇到的常见问题 将倾斜摄影三维模型从OSGB格式转换为3DTILES格式时&#xff0c;常见的问题包括&#xff1a; 1、3D Tiles生成时间较长&#xff1a;由于3D Tiles是一种高效的地理数据存储格式&#xff0c;能够支持海量的空间数据呈现和查询&am…

【LeetCode: 5. 最长回文子串 | 暴力递归=>记忆化搜索=>动态规划 => 中心扩展法】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

可以一学的代码优化小技巧:减少if-else冗余

前言 if-else 语句对于程序员来说&#xff0c;是非常非常熟悉的一个判断语句&#xff0c;我们在日常开发和学习中都经常看见它&#xff0c;if-else语句主要用于需要做出选择的地方进行判断&#xff0c;这里就不再赘述if-else语法和特点了。 ​ 我们在写代码&#xff08;如图下…

vue---组件逻辑复用方法:Mixin/HOC/Renderless组件

目录 1、Mixin 2、HOC 3、Renderless组件 下文通过表单校验来分别讲解Mixin/HOC/Renderless组件这三种方式。 1、Mixin 通过mixin将一个公用的validate函数同步到每一个组件中去 mixin使用详细介绍见&#xff1a;vue---mixin混入_maidu_xbd的博客-CSDN博客一个混入对象可…

优化Dynamics 365建议

传统上&#xff0c;旧版 Web 客户端需要某些扩展&#xff08;如功能区规则&#xff09;同步返回&#xff0c;这意味着开发人员在从远程源请求数据时被迫使用同步请求。在统一接口中&#xff0c;我们已采取措施确保支持异步通信。例如&#xff1a; 统一接口支持异步功能区规则评…

p67 内网安全-域横向 smbwmi 明文或 hash 传递

数据来源 知识点1&#xff1a; Windows2012以上版本默认关闭wdigest&#xff0c;攻击者无法从内存中获取明文密码 Windows2012以下版本如安装KB2871997补丁&#xff0c;同样也会导致无法获取明文密码 针对以上情况&#xff0c;我们提供了4种方式解决此类问题 利用哈希hash传递&…

Spring Security详细使用

认证流程 1.集中式认证流程 &#xff08;1&#xff09;用户认证 使用UsernamePasswordAuthenticationFilter过滤器中attemptAuthentication方法实现认证功能&#xff0c;该过滤器父类中successfulAuthentication方法实现认证成功后的操作 &#xff08;2&#xff09;身份校验…