C++ 设计模式----“对象性能“模式

news2024/11/14 10:33:53

“对象性能”模式

  • 面向对象很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。

  • 典型模式

  • Singleto

  • Flyweighta

Singleton 单件模式

**动机(Motivation)**💡:

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确选、以及良好的效率。

**问题思考(Consider)**🤔:

如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
这应该是类设计者的责任,而不是使用者的责任。
使用单例模式,需要保证这个类的实例有且仅有一个。因此,必须把一个类可以实例化多个对象的路堵死。

以下文字来自这个博主的文章内容摘选:
作者: 苏丙榅
链接 : https://subingwen.cn/design-patterns/singleton/
来源: 爱编程的大丙

关于一个类多对象操作的函数有以下几个:
1、构造函数:创建一个新的对象
2、拷贝构造函数:根据已有对象拷贝出一个新的对象
3、拷贝赋值操作符重载函数:两个对象之间的赋值
堵死实例化多个对象的路:
1、构造函数私有化,在类内部只调用一次,这个是可控的。
   由于使用者在类外部不能使用构造函数,所以在类内部创建的这个唯一的对象必须是静态的,这样就可以通过类名来访问了,为了不破坏类的封装,我们都会把这个静态对象的访问权限设置为私有的。
   在类中只有它的静态成员函数才能访问其静态成员变量,所以可以给这个单例类提供一个静态函数用于得到这个静态的单例对象。
2、拷贝构造函数私有化或者禁用(使用 = delete)
3、拷贝赋值操作符重载函数私有化或者禁用(从单例的语义上讲这个函数已经毫无意义,所以在类中不再提供这样一个函数,故将它也让一并处理以下。)

定义一个单例模式的类的实例代码:

//定义一个单例模式的类
class Singleton {
public:
	// =delete 代表函数禁用,也可以将其访问权限设置为私有
	Singleton(const Singleton& obj) = delete;
	Singleton& operator = (const Singleton& obj) = delete;
	static Singleton* getInstance();
private:
	Singleton() = default;
	static Singleton* m_obj;
};

饿汉模式

class PrintQueue {
public:
	// = delete 代表函数禁用,也可以将其访问权限设置为私有
	PrintQueue(const PrintQueue& obj) = delete;
	PrintQueue& operator = (const PrintQueue& obj) = delete;
	static PrintQueue* getInstance() {
		return m_printQ;
	}
private:
	PrintQueue() = default;
    //注意事项:类的静态成员变量在使用之前必须在类的外部进行初始化才能使用。
	static PrintQueue* m_printQ;
};

//静态成员初始化放到类外部处理
//定义这个单例类的时候,已经创建出了PrintQueue静态的单例对象。使用者通过getInstance()获取这个单例对象的时候,它已经准备好了
PrintQueue* PrintQueue::m_printQ = new PrintQueue;

int main() {
	PrintQueue* obj = PrintQueue::getInstance();
}

懒汉模式

缺点:在单线程情况下调用getInstance()函数获取单例对象的时候,是没有问题的。但是多线程的情况下,用getInstance()去访问单例对象会出现问。在多线程中,在getInstance内部每个线程都会new出一个实例对象。无法保证任务队列类的实例对象只有一个,会出现多个的情况。
class PrintQueue {
public:
	// = delete 代表函数禁用,也可以将其访问权限设置为私有
	PrintQueue(const PrintQueue& obj) = delete;
	PrintQueue& operator = (const PrintQueue& obj) = delete;
	static PrintQueue* getInstance() {
		if(m_printQ == nullptr){
			m_printQ = new PrintQueue;
		}
		return m_printQ;
	}
private:
	PrintQueue() = default;
	static PrintQueue* m_printQ;
};
PrintQueue* PrintQueue:: m_printQ = nullptr;

线程安全问题

双重检查锁定

class PrintQueue
{
public:
	// = delete 代表函数禁用, 也可以将其访问权限设置为私有
	PrintQueue(const PrintQueue& obj) = delete;
	PrintQueue& operator=(const PrintQueue& obj) = delete;
	static PrintQueue* getInstance()
	{
		if (m_printQ == nullptr)
		{
			m_mutex.lock();
			if (m_printQ == nullptr)
			{
				m_printQ = new PrintQueue;
			}
			m_mutex.unlock();
		}
		return m_printQ;
	}
private:
	PrintQueue() = default;
	static PrintQueue* m_printQ;
	static mutex m_mutex;
};
PrintQueue* PrintQueue::m_printQ = nullptr;
mutex PrintQueue::m_mutex;

在C++11中引入了原子变量atomic,通过原子变量可以实现一种更安全的懒汉模式的单例,代码如下;

class PrintQueue {
public:
	// = delete 代表函数禁用,也可以将其访问权限设置为私有
	PrintQueue(const PrintQueue& obj) = delete;
	PrintQueue& operator=(const PrintQueue& obj) = delete;
	static PrintQueue* getInstance() {
		PrintQueue* queue = m_printQ.load();
		if (queue == nullptr) {
			// m_mutex.lock(); //加锁;方式1
			lock_guard<mutex> locker(m_mutex); //加锁:方式2
			queue = m_printQ.load();
			if (queue == nullptr) {
				queue = new PrintQueue;
				m_printQ.store(queue);
			}
			//m_mutex.unlock();
		}
		return queue;
	}

	void print() {
		cout << "I'm heheda!!!" << endl;
	}
private:
	PrintQueue() = default;
	static atomic<PrintQueue*>m_printQ;
	static mutex m_mutex;
};
atomic<PrintQueue*> PrintQueue::m_printQ;
mutex PrintQueue::m_printQ;

int main() {
	PrintQueue* queue = PrintQueue::getInstance();
	queue->print();
	return 0;
}

静态局部对象

//静态局部对象
//在实现懒汉模式的单例的时候,相较于双重检查锁定模式有
//一种更简单的实现方法并且不会出现线程安全问题,那就是
//使用静态局部对象
class PrintQueue {
public:
	// = delete 代表函数禁用,也可以将其访问权限设置为私有
	PrintQueue(const PrintQueue& obj) = delete;
	PrintQueue operator = (const PrintQueue& obj) = delete;
	static PrintQueue* getInstance() {
		static PrintQueue printQ;
		return &printQ;
	}
	void print() {
		cout << "I'm heheda!!!" << endl;
	}
private:
	PrintQueue() = default;
};

int main() {
	PrintQueue* queue = PrintQueue::getInstance();
	queue->print();
	return 0;
}

总结以下懒汉模式和饿汉模式的区别:

懒汉模式的缺点:在创建实例对象的时候会有安全问题,但这样可以减少内存的浪费。

饿汉模式的缺点:在我们不需要这个实例对象的时候,它已经被创建出来,占用了一块内存。对于现在的计算机而言,内存容量都是足够大的,这个缺陷可以被无视。

写一个打印任务队列

#include<iostream>
#include<queue>
#include<mutex>
#include<thread>
using namespace std;

class PrintQueue {
public:
    // = delete 代表函数禁用,也可以将其访问权限设置为私有
    PrintQueue(const PrintQueue& obj) = delete;
    PrintQueue& operator = (const PrintQueue& obj) = delete;
    static PrintQueue* getInstance() {
        return &m_obj;
    }
    //任务队列是否为空
    bool isEmpty() {
        lock_guard<mutex> locker(m_mutex);
        bool flag = m_printQ.empty();
        return flag;
    }   
    //添加任务
    void addPrintTask(int data) {
        lock_guard<mutex> locker(m_mutex);
        m_printQ.push(data);
    }
    //取出一个任务
    int takePrintTask() {
        lock_guard<mutex> locker(m_mutex);
        if (!m_printQ.empty()) {
            return m_printQ.front();
        }
        return -1;
    }
    //删除一个任务
    bool popPrintTask() {
        lock_guard<mutex>locker(m_mutex);
        if (!m_printQ.empty()) {
            m_printQ.pop();
            return true;
        }
        return false;
    }
private:
    PrintQueue() = default;
    static PrintQueue m_obj;
    queue<int> m_printQ;
    mutex m_mutex;
};
PrintQueue PrintQueue::m_obj;
int main() {
    thread t1([]() {
        PrintQueue* printQ = PrintQueue::getInstance();
        for (int i = 0; i < 10;i++) {
            printQ->addPrintTask(i + 10);
            cout << "+++push printTask:" << i + 10 << ",threadID:"
                << this_thread::get_id() << endl;
            this_thread::sleep_for(chrono::milliseconds(500));
        }
    });
    thread t2([]() {
        PrintQueue* printQ = PrintQueue::getInstance();
        this_thread::sleep_for(chrono::milliseconds(100));
        while(!printQ->isEmpty()) {
            int data = printQ->takePrintTask();
            cout << "---pop printTask:" << data<< ",threadID:"
                << this_thread::get_id() << endl;
            printQ->popPrintTask();
            this_thread::sleep_for(chrono::seconds(1));
        }
    });
    t1.join();
    t2.join();
}

Singleton.cpp

#include <iostream>
class Singleton
{
public:
    Singleton(Singleton const&) = delete;
    Singleton& operator=(Singleton const&) = delete;
    static Singleton* get()
    {
        if (!instance)
        {
            instance = new Singleton();
        }
        return instance;
    }

    static void restart()
    {
        if (instance)
        {
            delete instance;
        }
    }

    void tell()
    {
        std::cout << "This is Singleton." << std::endl;
    }

private:
    Singleton() {}
    static Singleton* instance;
};

Singleton* Singleton::instance = nullptr;


int main()
{
    Singleton::get()->tell();
    Singleton::restart();

    return 0;
}

结构(Structure)

在这里插入图片描述

模式定义

保证一个类仅有一个实例,并提供一个该实例的全局访问点。

----《设计模式》GoF

要点总结

Singleton模式中的实例构造器可以设置为protected以允许子类派生。

Singleton模式一般不要支持拷贝构造函数和Clone接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。

如何实现多线程环境下安全的Singleton?注意对双检查锁的正确实现。

享元模式

**动机(Motivation)**💡:

在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价----主要指内存需求方面的代价。

**问题思考(Consider)**🤔:

如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?

C++执行代码:

Flyweight1.cpp

#include <iostream>
using namespace std;
#include <map>
#include <vector>

//设计年级
//享元基类
class Grade {
public:
	Grade(string name) :m_name(name) {}
	virtual void playGame() = 0;
	virtual void watch() = 0;
	virtual void Introduce() = 0;
	virtual ~Grade() {};
private:
	string m_name;
};

class primarySchoolGrade : public Grade {
public:
	using Grade::Grade;
	void Introduce()override {
		cout << "我是小学生" << endl;
	}
	void playGame()override {
		cout << "喜欢玩的游戏:玩俄罗斯方块" << endl;
	}
	void watch()override {
		cout << "喜欢玩的动画:看喜羊羊与灰太狼" << endl;
	}
};

class JuniorHighSchoolGrade : public Grade {
public:
	using Grade::Grade;
	void Introduce()override {
		cout << "我是初中生" << endl;
	}
	void playGame()override {
		cout << "喜欢玩的游戏:玩王者荣耀" << endl;
	}
	void watch()override {
		cout << "喜欢玩的动画:看火影忍者" << endl;
	}
};

class HighSchoolGrade : public Grade {
public:
	using Grade::Grade;
	void Introduce()override {
		cout << "我是高中生" << endl;
	}
	void playGame()override {
		cout << "喜欢玩的游戏:玩穿越火线" << endl;
	}
	void watch()override {
		cout << "喜欢玩的动画:看鬼灭之刃" << endl;
	}
};

class AbstractGradeFactory
{
public:
	virtual Grade* Create_Grade(string name) = 0;
	virtual ~AbstractGradeFactory() {}
};

class primarySchoolGradeFactory : public AbstractGradeFactory {
public:
	Grade* Create_Grade(string name) override {
		return new primarySchoolGrade(name);
	}
};

class JuniorHighSchoolGradeFactory : public AbstractGradeFactory {
public:
	Grade* Create_Grade(string name) override {
		return new JuniorHighSchoolGrade(name);
	}
};

class HighSchoolGradeFactory : public AbstractGradeFactory {
public:
	Grade* Create_Grade(string name) override {
		return new HighSchoolGrade(name);
	}
};
/*
class GradeFactory{
public:
	Grade* getSharedData(string gradeName,string name) {
		Grade* data = nullptr;
		//遍历容器
		for (auto item : pool) {
			if (item.first == name) {
				data = item.second;
				cout << "正在复用 <" << name << ">..." << endl;
				break;
			}
		}
		if (data == nullptr) {
			//第二种方法
			primarySchoolGrade* fac1 = new primarySchoolGrade(name);
			JuniorHighSchoolGrade* fac2 = new JuniorHighSchoolGrade(name);
			HighSchoolGrade* fac3 = new HighSchoolGrade(name);
			if (gradeName == "小学")
				data = fac1;
			else if(gradeName == "初中")
				data = fac2;
			else if(gradeName == "高中")
				data = fac3;
			cout << "正在创建 <" << name << ">..." << endl;
			pool.insert(make_pair(name, data));
		}
		return data;
	}
private:
	map<string, Grade*> pool;
};*/

class GradeFactory {
public:
	Grade* getSharedData(Grade* dataNew, string name) {
		Grade* data = nullptr;
		//遍历容器
		for (auto item : pool) {
			if (item.first == name) {
				data = item.second;
				cout << "正在复用 <" << name << ">..." << endl;
				break;
			}
		}
		if (data == nullptr) {
			data = dataNew;
			cout << "正在创建 <" << name << ">..." << endl;
			pool.insert(make_pair(name, data));
		}
		return data;
	}
private:
	map<string, Grade*> pool;
};

class selfIntroduce {
public:
	selfIntroduce(Grade* grade) :m_grade(grade) {}
	void say() {
		if (m_grade) {
			m_grade->Introduce();
			m_grade->playGame();
			m_grade->watch();
		}
		else {
			cout << "m_grade为Null" << endl;
		}
	}
private:
	int m_runSpeed = 0;
	Grade* m_grade = nullptr;
};

int main() {
	//小学生
	GradeFactory* factory1 = new GradeFactory;
	vector<selfIntroduce*> List1;
	vector<string>nameList = { "喜羊羊-1","喜羊羊-1","美羊羊-2","美羊羊-2","懒羊羊-1","沸羊羊-1" };
	//第一种方法 抽象工厂
	AbstractGradeFactory* fac1 = new primarySchoolGradeFactory;
	for (auto name : nameList) {
		int speed = 0;
		Grade* data = fac1->Create_Grade(name);
		//selfIntroduce* grade2 = new selfIntroduce(factory2->getSharedData("小学", name));
		selfIntroduce* grade1 = new selfIntroduce(factory1->getSharedData(data,name));
		speed += rand() % 100;
		grade1->say();
		cout << "====================================" << endl;
		List1.push_back(grade1);
	}
	delete factory1;
	delete fac1;

	//初中生
	GradeFactory* factory2 = new GradeFactory;
	vector<selfIntroduce*> List2;
	AbstractGradeFactory* fac2 = new JuniorHighSchoolGradeFactory;
	nameList = { "鸣人-1","鸣人-1","佐助-2","佐助-2","雏田-1","雏田-1" };
	for (auto name : nameList) {
		int speed = 0;
		Grade* data = fac2->Create_Grade(name);
		selfIntroduce* grade2 = new selfIntroduce(factory2->getSharedData(data, name));
		speed += rand() % 100;
		grade2->say();
		cout << "====================================" << endl;
		List2.push_back(grade2);
	}
	delete factory2;
	delete fac2;

	//高中生
	GradeFactory* factory3 = new GradeFactory;
	vector<selfIntroduce*> List3;
	AbstractGradeFactory* fac3 = new HighSchoolGradeFactory;
	nameList = { "小樱-1","小樱-1","知世-2","知世-2","小狼-1","小狼-1" };
	for (auto name : nameList) {
		int speed = 0;
		Grade* data = fac3->Create_Grade(name);
		selfIntroduce* grade3 = new selfIntroduce(factory3->getSharedData(data, name));
		speed += rand() % 100;
		grade3->say();
		cout << "====================================" << endl;
		List3.push_back(grade3);
	}
	delete factory3;
	delete fac3;
	return 0;
}

Flyweight2.cpp

#include <iostream>
#include <map>
class Flyweight
{
public:
    virtual ~Flyweight() {}
    virtual void operation() = 0;
};
class UnsharedConcreteFlyweight : public Flyweight
{
public:
    UnsharedConcreteFlyweight(const int intrinsic_state) :
        state(intrinsic_state) {}

    ~UnsharedConcreteFlyweight() {}

    void operation()
    {
        std::cout << "Unshared Flyweight with state " << state << std::endl;
    }
private:
    int state;
};

class ConcreteFlyweight : public Flyweight
{
public:
    ConcreteFlyweight(const int all_state) :
        state(all_state) {}

    ~ConcreteFlyweight() {}

    void operation()
    {
        std::cout << "Concrete Flyweight with state " << state << std::endl;
    }

private:
    int state;
};

class FlyweightFactory
{
public:
    ~FlyweightFactory()
    {
        for (auto it = flies.begin(); it != flies.end(); it++)
        {
            delete it->second;
        }
        flies.clear();
    }

    Flyweight* getFlyweight(const int key)
    {
        if (flies.find(key) != flies.end())
        {
            return flies[key];
        }
        Flyweight* fly = new ConcreteFlyweight(key);
        flies.insert(std::pair<int, Flyweight*>(key, fly));
        return fly;
    }

private:
    std::map<int, Flyweight*> flies;
};


int main()
{
    FlyweightFactory* factory = new FlyweightFactory;
    factory->getFlyweight(1)->operation();
    factory->getFlyweight(2)->operation();
    delete factory;
    return 0;
}

结构

在这里插入图片描述

模式定义

运用共享计数有效地支持大量细粒度的对象。

----《设计模式》GoF

要点总结

面向对象很好地解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。

Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。

对象的数量太大从而导致对象内存开销加大----什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。

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

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

相关文章

51单片机笔记

51单片机笔记 一、编程区域 1.1 用户应用程序区&#xff08;AP区&#xff09; 是指用户自己编写的程序区 1.2 ISP监控程序区&#xff1a; ISP区是指芯片出厂时就已经固化在单片机内部的一段程序&#xff0c;STC单片机可以进行ISP串行下载程序&#xff0c;这就是因为芯片在出…

在Blender和Zbrush中创建激光指示器,新手硬表面建模码住!

大家好&#xff0c;今天云渲染小编给大家带来的分享是硬表面建模&#xff0c;CG艺术家Lyubov使用Blender和Zbrush创建激光指示器的幕后花絮。 介绍 我叫 Lyubov&#xff0c;来自俄罗斯圣彼得堡&#xff0c;是一名 3D 建模的初学者。虽然学习还不到一年&#xff0c;但是我对它…

etcd安装

ETCD安装 windows版本 下载 下载地址https://github.com/etcd-io/etcd/releases 安装 其实也不用安装&#xff0c;下载解压后&#xff0c;得到如下 选中etcd.exe&#xff0c;右键→属性→兼容性→以管理员身份运行此程序勾上&#xff0c;当然&#xff0c;每次运行时候右键…

kettle作业循环实现

kettle作业循环实现 使用kettle作业中的JavaScript实现作业循环&#xff0c;这里是固定循环10次 JavaScript2 parent_job.setVariable("max",10); parent_job.setVariable("count",1); true;检验字段的值 JavaScript var current parent_job.getVari…

MySQL事务+存储引擎

文章目录 MySQL事务存储引擎1 事务1.1 事务的概念1.2 事务的ACID特点1.3 导致问题1.4 事务控制语句1.4.1 查看修改隔离级别1.4.2 使用set设置控制事务1.4.3 查看事务自动提交功能 2 存储引擎2.1 存储格式2.2 常用存储引擎2.3 查看表使用的存储引擎2.4 修改存储引擎2.5 InnoDB行…

证券市场基本概念

证券市场基本概念 一、 指数分类1.1 什么是指数1.2 指数分类 二 、交易所及板块2.1 交易所及板块2.2 股票代码规则 三 、指数、ETF、股票的关系3.1 指数和股票的关系3.2 指数和指数ETF的关系3.3 ETF概念 四、 股票行业分类4.1 申万行业分类4.2 股票与申万行业分类的关系 五 、指…

idea - 插件之 codeium(安装篇)

idea - 插件之 codeium 插件官网地址&#xff1a;https://codeium.com/ Idea 版本&#xff1a;2021.3.2 关于插件作用就不多做介绍&#xff0c;接下来开始正文。 由于目前有很多博客文章没有对 Idea 安装进行详细的讲解和遇到问题的处理讲解&#xff0c;所以我经过踩坑后&am…

【C++学习】C++的动态内存管理 | new和delete的底层 | 初识模板

目录 1. C的动态内存管理 2. new和delete的底层 3. 定位new 4. new和malloc 的区别总结 5. 模板 写在最后&#xff1a; 1. C的动态内存管理 上一篇文章已经大致介绍完new和delete的用法&#xff0c; 以及C和C语言两种动态内存管理方式的区别&#xff0c;这里简单总结一…

【MMCV python安装指南】

MMCV python安装指南 MMCV 介绍安装教程1.系统环境2.python版本3.torch版本4.mmcv版本 安装示例 MMCV 介绍 mmcv 是用于计算机视觉研究的基础 Python 库&#xff0c;支持 MMLAB 中的许多研究项目&#xff0c;例如 MMDetection https://github.com/open-mmlab/mmdetection MMAct…

arc163 C 思维构造

题意&#xff1a;https://atcoder.jp/contests/arc163/tasks/arc163_c 思路&#xff1a;本题构造主要就是围绕 初始放入2&#xff0c;3&#xff0c;6&#xff0c;然后一直将一个拆解直到满足大小。 /*keep on going and never give up*/ #include<cstdio> #include<…

【择校】肠子悔青,录取分数断层,超过第二名44分,超过最后一名146分!

一、学校及专业介绍 中南民族大学&#xff08;South-Central Minzu University&#xff09;坐落于湖北省武汉市&#xff0c;中华人民共和国国家民族事务委员会直属高校&#xff0c;位列湖北省“国内一流大学建设高校”、“少数民族高层次骨干人才计划”资格高校、全国深化创新创…

15. python从入门到精通——Pygame游戏编程

目录 游戏的原理 安装Pygame Pygame常用模块 Pygame的基本使用 实例:制作一个跳跃的小球游戏&#xff0c;如果碰到窗口边缘会改变小球移动方向 实现步骤&#xff1a; 运行效果&#xff1a; 小球图片&#xff1a; python代码&#xff1a; 开发Flappy Bird游戏 …

生成古风少女图片【InsCode Stable Diffusion美图活动一期】

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 写在前面 Stable Diffusion 模型在线使用地址&#xff1a; 工具介绍 一.如何使用S…

基于Java的酒店管理系统设计与实现(源码+文档+报告+任务书)

本系统采用Java语言进行开发&#xff0c;实现了跨平台的部署。使用了MySQL数据库进行数据存储&#xff0c;保证了数据的稳定性与可靠性。通过使用Spring框架&#xff0c;实现了对各个模块的解耦&#xff0c;使得系统更易于维护与升级。前端使用了Node.jsVue以提供易用、美观的用…

spring复习:(4)AbstractEnvironment

该类中指定了激活profile属性的名称(spring.profiles.active)&#xff0c;默认profile属性的名称(spring.profiles.default)&#xff0c;以及默认的profile的名字(default)。

springboot项目集成nacos配置中心踩坑

前提 在使用nacos的配置中心功能&#xff0c;发现在application.yml中配置地址后仍然读取不到配置中心地址&#xff0c;配置项和值都是正确的。但就是读不到&#xff0c;现在来分析下 配置项 spring:application:name: test-servicemain:allow-bean-definition-overriding: …

Ubuntu 20.04 LTS x86_64 SPEC CPU 2006 cpu2006-1.2.iso 测试笔记

环境 安装依赖项 sudo apt install gfortran 挂载iso sudo mkdir /mnt/cpu2006 sudo mount cpu2006-1.2.iso /mnt/cpu2006 安装 cd /mnt/cpu2006 sh install.sh -d /home/speccpu/cpu2006 SPEC CPU2006 InstallationTop of the CPU2006 tree is /mnt/cpu2006Installing F…

【Vue3】学习笔记-toRef

作用 创建一个ref对象&#xff0c;其value值指向另一个对象中的某个属性。 语法 const nametoRef(person,‘name’) 应用 要将响应式对象中的某个属性单独提供给外部使用时 #扩展 toRefs与toRef功能一直&#xff0c;但可以批量创建多个ref对象,语法&#xff1a;toRefs(per…

浅谈消防应急照明和疏散指示系统在变电站的设计与应用

【摘要】&#xff1a;随着对消防安全重视程度的不断提高&#xff0c;消防设计要求更加严格。针对变电站的应用场景&#xff0c;以民用和工业建筑为对象设计的消防应急照明和疏散指示系统不宜直接套用。文章从变电站实际应用角度出发&#xff0c;梳理和对比了现行设计规范&#…

机器人制作开源方案 | 智能立体仓储系统模型

1. 功能说明 本文示例将通过程序控制模拟立体仓储系统的运动效果--模拟立体仓储系统进行运输货物时各个结构的运动方式。立体仓储系统的运动有整体系统的水平移动、载货台的纵向移动、货叉的平动&#xff0c;所有的运动表现形式都是旋转运动转化为平动。 2. 结构说明 该立体仓储…