单例模式,适配器模式,迭代器模式,工厂模式(C++实现)

news2024/9/24 11:20:31

设计模式就相当于编程中的“孙子兵法”,是经过很久的时间以及各路大神总结出来的多种实用,高效的业务设计中的套路;

单例模式

一个类只能创建一个对象的情况下的一种设计模式(eg:服务器只有一个),即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

核心实现思想: 私有构造函数,拷贝构造,赋值重载;

饿汉模式

不管你将来用不用,程序启动时就创建一个唯一的实例对象。

// 饿汉模式

 class Singleton
 {
 public:
 static Singleton* GetInstance()
 {
 	return &m_instance;
 }

 private:
     // 构造函数私有
     Singleton(){};

     // C++98 防拷贝
     Singleton(Singleton const&);
     Singleton& operator=(Singleton const&);

     // or

     // C++11 防拷贝
     Singleton(Singleton const&) = delete;
     Singleton& operator=(Singleton const&) = delete;

     static Singleton m_instance;
 };

 Singleton Singleton::m_instance; // 在程序入口之前,就完成单例对象的初始化,不管用不用;

优点:简单,线程安全(不需要配合锁)
缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。

懒汉模式

如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等 等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时 非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

// 懒汉模式
class Singleton
{
public:
	static Singleton* GetInstance() {
		// 注意这里一定要使用Double-Check的方式加锁,才能保证效率和线程安全
		if (nullptr == m_pInstance) {
			m_mtx.lock();
			if (nullptr == m_pInstance) {
				m_pInstance = new Singleton();
			}
			m_mtx.unlock();
		}
		return m_pInstance;
	}
    
private:
	// 构造函数私有
	Singleton() {};
    
	// 防拷贝
	Singleton(Singleton const&);
	Singleton& operator=(Singleton const&);
    
	static Singleton* m_pInstance; // 静态,单例对象指针
	static mutex m_mtx; //互斥锁
};

优点:延迟加载,程序启动更快;
缺点:原本非线程安全,加锁实现线程安全,但是锁的使用在多线程中性能消耗太大;

小结

  • 很多线程or业务规模不大(程序整体启动不会很慢),用饿汉模式;
  • 线程不多or业务规模大,程序整体启动会很缓慢的时候,用懒汉模式(延迟加载);

适配器模式

简介

  • 适配器模式,说白了就是由于目标接口与已有接口不一致,但是大致功能相似,那么只要对已有接口稍作处理(进行继承or组合的嵌套封装),就能 适配 目标接口的调用方式

举例

在这里插入图片描述

我们都知道每个国家的电器标准不同,那么如何在国外使用我们国内的双头标准交流电插头电器呢?

答案是配合一个交流电适配器使用!相当于对我们的双头标准交流电插头进行了一些处理,让它得意在别的国外接口上正常使用;

下面来一段抽象举例的代码,本段代码无实际业务意义,目的是让我们在代码层面理解适配器模式:

  1. 已有接口Target调用int参数类型;

  2. 新的接口调用string参数类型;

  3. 目的: 我们需要将调用string参数类型的接口Adaptee, 通过适配器Adaptor封装, 适配成调用int型参数的接口Target;

  4. 在这里插入图片描述
    Clinet直接调用的是Target接口,我们提供了Adeptee接口,参数类型不一样,我们给Adeptee封装了个适配器Adapter,使其适配Client对Target的调用方法进行调用;

#include <iostream>
#include <memory>
#include <string>

class Target//目标接口
{
public:
	virtual bool NewRequest(const int value)
	{
		std::cout << "Calling new request method!" << std::endl;
		return true;
	}

	virtual ~Target(){}
};

class Adaptee//需要套适配器封装的接口
{
public:
	bool OldRequest(const std::string& strValue)
	{
		std::cout << "Calling old request method!" << std::endl;
		return true;
	}
};

class Adaptor : public Target//适配器(继承方式)
{
private:
	std::shared_ptr<Adaptee> m_smartAdaptee;

public:
	Adaptor(std::shared_ptr<Adaptee> adaptee)//智能指针,好习惯
	{
		m_smartAdaptee = std::move(adaptee);
	}

	bool NewRequest(const int value)//
	{
		std::cout << "I'm new request method" << std::endl;
		std::string strValue = std::to_string(value);//适配器内部使用了to_stinrg 将int型参数适配成了string,传入需要适配的接口进行调用!
		m_smartAdaptee->OldRequest(strValue);

		return true;
	}
};

int main()
{
	std::shared_ptr<Target> target(new Adaptor(std::make_shared<Adaptee>()));
	target->NewRequest(10);
	return 0;
}

小结

  • 适配器模式一般用于软件开发后期旧的软件接口已被大量使用,但是新的软件接口功能相同但是接口有差异,无法直接使用,这时如果重新统一接口设计,需要消耗大量的资源(时间、人力、物力),简单的使用一个适配器作为连接新旧接口的中转站就成为首选

当然,业务中能严谨的统一接口更好,我们也就不需要出现问题再用适配器的形式解决问题了;(能预防为啥要等病发?)

迭代器模式

简介

提供一种顺序访问集合内元素的方法,但不暴露集合内部实现细节的设计模式,属于行为型设计模式.
迭代器模式将数据的存储和遍历相分离存储交给聚合类,遍历交给迭代器类,如果需要对新的集合进行顺序遍历只需要扩展新的相关迭代器类和相关聚合类

简单来说,设计一种结构,提供给各种类 类似stl中迭代器一样的 在不暴露类内部存储结构情况下的 顺序遍历集合内元素的能力;

相关组成示例

我们以存储元素为Student类元素,代码编写一个迭代器模式学习

//学生类
//集合中存储的元素类型
class Student
{
public:
	string _name;			//姓名
	string _stuNo;			//学号
	string _college;		//学院
public:
	Student(const string& name, const string& stuNo, const string& college)
		:_name(name)
		, _stuNo(stuNo)
		, _college(college)
	{}

	//展示学生信息的函数,用于测试
	void showInfo()
	{
		cout << "姓名: " << _name << "\t学号: " << _stuNo << "\t学院: " << _college << endl;
	}
};

抽象聚合类

提供一个创建迭代器对象的接口添加元素接口删除元素接口

//抽象聚合类(基类,纯虚函数,由于后续派生类的扩展)
class Aggregate
{
public:
	//添加学生信息
	virtual void addStudent(const Student& stu) = 0;
	//删除学生信息
	virtual void deleteStudent(const Student& stu) = 0;
	//创建迭代器
	virtual Iterator* createIterator() = 0;
};

具体聚合类

根据存储元素方式的不同重写创建迭代器接口返回自己对应的迭代器
重写添加元素和删除元素接口
具体聚合类和具体迭代器类是互相对应的,根据元素的存储方式,设计对应的遍历所用的迭代器;

//计算机学院聚合类
class ComputerAggregate : public Aggregate
{
private:
	vector<Student> _info;		//存储学生对象的集合(vector形式存储)

public:
	//添加学生信息
	virtual void addStudent(const Student& stu)
	{
		_info.emplace_back(stu);
	}

	//删除学生信息
	virtual void deleteStudent(const Student& stu)
	{
		auto it = _info.begin();
		while (it != _info.end())
		{
			if (it->_name == stu._name && it->_stuNo == stu._stuNo && it->_college == stu._college)
			{
				break;
			}
			++it;
		}
		_info.erase(it);
	}

	//创建具体迭代器函数
	virtual Iterator* createIterator()
	{
		return new ComputerIterator(_info);
	}
};

//体育学院聚合类
class SportAggregate : public Aggregate
{
private:
	list<Student> _info;		//存储学生对象的集合(list形式存储)
public:
	//添加学生信息
	virtual void addStudent(const Student& stu)
	{
		_info.push_back(stu);
	}
	//删除学生信息
	virtual void deleteStudent(const Student& stu)
	{
		auto it = _info.begin();
		while (it != _info.end())
		{
			if (it->_name == stu._name && it->_stuNo == stu._stuNo && it->_college == stu._college)
			{
				break;
			}
			++it;
		}
		_info.erase(it);
	}
	//创建具体迭代器函数
	virtual Iterator* createIterator()
	{
		return new SportIterator(_info);
	}
};

抽象迭代器类

该类提供可以查看集合中是否有下一个元素走到集合的下一个元素位置的接口

//抽象迭代器类(基类,纯虚函数,由于后续派生类的扩展)
class Iterator
{
public:
	//下一个位置是否有元素
	virtual bool hasNext() = 0;
	//返回当前元素,并且走到下一个位置
	virtual Student next() = 0;
};

具体迭代器类

为具体聚合类实现对应的迭代器接口(因为不同聚合类内部存储元素的方式可能不同,比如vector和list这两种存储方式)

//用计算机学院 和 体育学院 两种派生具体迭代器举例

//1.计算机学院迭代器(抽象迭代器 根据聚合类存储形式的不同,派生的具体对应迭代器类)
class ComputerIterator : public Iterator
{
private:
	vector<Student> _info;		//迭代器访问的数据集合
	int _curPos;				//当前访问的下标位置
public:
	ComputerIterator(const vector<Student>& info)
		:_info(info)
		, _curPos(0)
	{}

	//下一个位置是否有元素
	virtual bool hasNext()
	{
		return _curPos < _info.size();
	}
	//返回当前元素,并且走到下一个位置
	virtual Student next()
	{
		Student curStu = _info[_curPos++];
		return curStu;
	}
};



//2.体育学院迭代器(抽象迭代器 根据聚合类存储形式的不同,派生的具体对应迭代器类)
class SportIterator : public Iterator
{
private:
	list<Student> _info;		//迭代器访问的数据集合
public:
    SportIterator(const list<Student>& info)
		:_info(info)
	{}
    
	//下一个位置是否有元素
	virtual bool hasNext()
	{
		return !_info.empty();
	}
	//返回当前元素,pop用过的元素,并且走到下一个位置(pop的目的是,list不支持随机访问,每次拿当前元素是list.front()这样的形式)
	virtual Student next()
	{
		Student front = _info.front();
		_info.pop_front();
		return front;
	}	
};


测试代码

//计算机学院测试
void test_College()
{
	Aggregate* computerCollege = new ComputerAggregate();
	computerCollege->addStudent(Student("索隆", "11", "计算机"));
	computerCollege->addStudent(Student("红发香克斯", "12", "计算机"));
	computerCollege->addStudent(Student("路飞", "13", "计算机"));
	computerCollege->addStudent(Student("娜美", "14", "计算机"));
	computerCollege->addStudent(Student("山治", "15", "计算机"));

	Iterator* it = computerCollege->createIterator();
	cout << "*************   计算机学院   **************" << endl;
	while (it->hasNext())
	{
		it->next().showInfo();
	}
}

//体育学院测试
void test_Sport()
{
	Aggregate* sportCollege = new SportAggregate();
	sportCollege->addStudent(Student("白胡子", "0", "体育"));
	sportCollege->addStudent(Student("雷利", "1", "体育"));
	sportCollege->addStudent(Student("罗杰", "2", "体育"));
	sportCollege->addStudent(Student("凯多", "3", "体育"));
	sportCollege->addStudent(Student("黑胡子", "4", "体育"));
	sportCollege->addStudent(Student("BigMom", "5", "体育"));

	Iterator* it = sportCollege->createIterator();
	cout << "*************   体育学院   **************" << endl;
	while (it->hasNext())
	{
		it->next().showInfo();
	}
}

运行结果

在这里插入图片描述

小结

优点符合开闭原则(对 提供方 扩展开放,对 使用方 修改关闭),如果需要对新的元素集合进行遍历,只需要添加新的具体聚合类具体迭代器类

缺点:显而易见,需要添加新的具体聚合类具体迭代器类进行扩展,类的数量会增多;

工厂模式

简单工厂模式

简单工厂模式(Simple Factory Pattern)专门定义一个 工厂类 来负责创建其他类的实例,被创建的实例通常具有共同的父类(简单工厂类)

简单工厂模式,是一种实例化对象的方式,只要 传入 需要实例化对象的名字,就可以通过相应工厂对象名字->来制造所需要的对象;

在这里插入图片描述

typedef enum Type
{
    Apple,
    Huawei,
}PRODUCTTYPE;

//抽象产品类 TV(电视机类)
class Phone
{
public:
    virtual void Show() = 0;
    virtual ~Phone() {};//声明析构函数为虚函数,防止内存泄漏
};

//具体产品类 Apple Phone(苹果手机类)
class ApplePhone : public Phone
{
public:
    void Show()
    {
        cout << "I'm Apple phone " << endl;
    }
};
//具体产品类 Huawei Phone(华为手机类)
class  HuaweiPhone : public Phone
{
public:
    void Show()
    {
        cout << "I'm Huawei Phone" << endl;
    }
};


// 工厂类 PhoneFactory(手机工厂类)
class TVFactory
{
public:
    Phone* CreatePhone(PRODUCTTYPE type)
    {
        switch (type)//通过传进来的type参数,来确定创建哪个类的实例;
        {
        case Apple:
            return new ApplePhone();

        case Huawei:
            return new HuaweiPhone();
                
        default:
            return NULL;
        }
    }
};

int main()
{
     // 创建工厂类对象
    PhoneFactory* myPhoneFactory = new PhoneFactory();
    Phone* applePhone = myPhoneFactory->CreatePhone(Apple); //这里的传参确定了创建哪种产品
    if (applePhone != NULL)
        applePhone->Show();

}

特征: 只有唯一的一个工厂类,该工厂负责所有种类产品的生产,是整个简单工厂模式的核心,提供了工厂方法CreatePhone()该方法中包含一个字符串类型的参数,在内部业务逻辑中根据参数值得不同实例化不同的具体产品类,返回相依的对象。

优点: 使用逻辑简单,大量new各种产品的时候,同意改变参数传入唯一工厂即可;

缺点:这种单工厂模式中最大的缺点是当有新产品要加入系统时,必须要修改工厂类,加入必要的处理逻辑,违背了“开闭原则”。其次是只有一个工厂,导致逻辑复杂,维护性差;

实际应用: 在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式;

工厂方法模式

在工厂方法模式中,工厂父类负责定义创建产品对象的公告接口,而子工厂类负责生成具体的产品对象。目的是将产品的实例化操作延迟到子工厂类中完成通过子工厂类来确定究竟应该实例化哪一个具体产品类

在这里插入图片描述

/*抽象产品类 Phone(手机类)*/
class Phone
{
public:
    virtual void Show() = 0;
    virtual ~Phone();//声明析构函数为虚函数,防止内存泄漏
};

/*具体产品类 ApplePhone(苹果手机类)*/
class ApplePhone : public Phone
{
public:
    void Show()
    {
        cout << "I'm Apple Phone" << endl;
    }
};
/*具体产品类 HuaweiPhone(华为手机类)*/
class HuaweiPhone : public Phone
{
public:
    void Show()
    {
        cout << "I'm Huawei Phone" << endl;
    }
};
/*工厂类(电视机工厂类)*/
class PhoneFactory
{
public:
    virtual Phone* CreatePhone() = 0;
    virtual ~PhoneFactory() {};//析构函数声明为虚函数,防止内存泄漏
};

/*具体工厂类 ApplePhoneFactory(苹果手机工厂类)*/
class ApplePhoneFactory : public PhoneFactory
{
public:
    Phone* CreatePhone()
    {
        return new ApplePhone();
    }
};

/*具体工厂类 HuaweiPhoneFactory(华为手机工厂类)*/
class HuaweiPhoneFactory : public PhoneFactory
{
public:
    Phone* CreatePhone()
    {
        return new HuaweiPhone();
    }
};

int main(int argc, char* argv[])
{
    PhoneFactory* applephonefactory = new ApplePhoneFactory();//实例化工厂抽象类
    
    Phone* applePhone = applephonefactory->CreatePhone();//每种产品由每种子工厂创建
    applePhone->Show();
    
    PhoneFactory* huaweiphonefactory = new HuaweiPhoneFactory();
    
    Phone* huaweiPhone = huaweiphonefactory->CreatePhone();//每种产品由每种子工厂创建
    huaweiPhone->Show();

    return 0;
}

特征: 每种产品都有对应的专门生产这种产品的子工厂;

优点:系统的扩展性好,符合“开闭原则” 。系统加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品即可

缺点:在添加新产品时,需要编写新的具体产品类而且还要提供与之对应的具体子工厂类系统中类的个数将成对增加,一定程度上增加了系统的复杂度

实际应用: 在设计的初期,就考虑到产品在后期会进行扩展的情况下,可以使用工厂方法模式;

抽象工厂模式

抽象工厂模式是工厂方法模式的泛化版工厂方法模式是一种特殊的抽象工厂模式;

在工厂方法模式中,每个具体工厂只能生产一种具体的产品,如苹果手机厂只生产苹果手机,而抽象工厂方法模式中,一个具体的工厂可以生产多个具体产品(eg:苹果手机,苹果笔记本)
在这里插入图片描述

// 抽象产品类类 Phone(手机类)
class Phone
{
public:
    virtual void Show() = 0;
    virtual ~Phone() {};//析构函数声明为虚函数,防止内存泄漏
};

//具体产品类 HaierTelevision(苹果手机类)
class ApplePhone : public Phone
{
public:
    void Show()
    {
        cout << "I'm ApplePhone" << endl;
    }
};
//具体产品类 HuaweiPhone(华为手机类)
class HuaweiPhone : public Phone
{
public:
    void Show()
    {
        cout << "I'm HuaweiPhone" << endl;
    }
};

// 抽象产品类  ComPuter(笔记本类)
class ComPuter
{
public:
    virtual void Show() = 0;
    virtual ~ComPuter() {};//析构函数声明为虚函数,防止内存泄漏
};
//具体产品类 AppleComPuter(苹果笔记本类)
class AppleComPuter : public ComPuter
{
public:
    void Show()
    {
        cout << "I'm AppleComPuter" << endl;
    }
};
//具体产品类 HuaweiComPuter(华为笔记本类)
class HuaweiComPuter : public ComPuter
{
public:
    void Show()
    {
        cout << "I'm HuaweiComPuter" << endl;
    }
};

// 抽象工厂类 EFactory(电器工厂类)
class EFactory
{
public:
    virtual Phone* CreatePhone() = 0;
    virtual ComPuter* CreateComPuter() = 0;
    virtual ~EFactory() {};//析构函数声明为虚函数,防止内存泄漏
};
//具体工厂类 AppleFactory(苹果工厂类)
class AppleFactory : public EFactory
{
public:
    Phone* CreatePhone()
    {
        return new ApplePhone();
    }

    ComPuter* CreateComPuter()
    {
        return new AppleComPuter();
    }
};
//具体工厂类 HuaweiFactory(华为工厂类) 
class HuaweiFactory : public EFactory
{
public:
    Phone* CreatePhone()
    {
        return new ApplePhone();
    }

    ComPuter* CreateComPuter()
    {
        return new AppleComPuter();
    }
};

int main(int argc, char* argv[])
{
    EFactory* appleFactory = new AppleFactory();/*实例化工厂抽象基类*/
    Phone* applePhone = appleFactory->CreatePhone();/*实例化产品抽象类*/
    ComPuter* appleComPuter = appleFactory->CreateComPuter();

    applePhone->Show();
    appleComPuter->Show();

    EFactory* huaweiFactory = new HuaweiFactory();
    Phone* huaweiPhone = huaweiFactory->CreatePhone();
    ComPuter* huaweiComPuter = huaweiFactory->CreateComPuter();

    huaweiPhone->Show();
    huaweiComPuter->Show();
   
}

特征:在一个抽象工厂可以定义一组多种方法每一个方法对应一个产品种类

优点:1. 抽象工厂模式将产品族的依赖与约束关系放到抽象工厂中,便于管理。2. 切换产品族容易,只需要增加一个具体工厂实现,客户端选择另一个套餐就可以了

缺点: 1.比较繁琐: 抽象工厂模式类增加的速度很快**,有一个产品族就需要增加一个具体工厂实现**; 2.产品族难以扩展产品: 当产品族中增加一个产品时,抽象工厂接口中需要增加一个函数,对应的所有具体工厂实现都需要修改,修改放大严重。

实际应用:当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。比如apple的手机和电脑都属于apple产品族;

小结

简单工厂模式唯一工厂类一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。(方便操作,但是扩展性差)
工厂方法模式多个工厂类一个产品抽象类利用多态创建不同的产品对象,避免了大量的if-else判断。(方便扩展,但是子工厂的数量会增多,复杂度变高)
抽象工厂模式多个工厂类多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了子工厂类的数量。(相比于工厂方法模式,引入了族产品的概念,进而减少了子工厂类的数量;缺点如同工厂方法模式,产品族变多,子工厂类还是会变多,变复杂而操作繁琐)

参考文章

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

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

相关文章

【论文阅读】《知识图谱研究综述》;Knowledge Graph:概念及主要应用,主要特征、构建的主要技术、未来研究方向。

目录 1. 文章来源2. 简介3. 什么是知识图谱4. Knowledge Graph 主要特征5. Knowledge Graph 构建的主要技术6. Knowledge Graph 未来研究方向1. 文章来源 该paper来自于知网,请尊重原创,这里仅作为学习笔记~ 2. 简介 知识图谱将知识库以一种图谱的形式展现出来,使知识具有…

opencv-python常用函数解析及参数介绍(一)——图像读取及其通道与灰度

opencv-python中一些常用函数解析及参数介绍前言1.读图片读彩图读灰度图2.显示图片显示彩图显示灰度图灰度图与彩图的区别从彩图中分离单通道通道合并3.保存图片4.灰图的通道分离5.读取视频前言 本文将简单介绍opencv-python中的图像以及视频的读取&#xff0c;并且介绍灰度图…

Hello 2023

年初到年尾&#xff0c;感觉刚写完《Hello 2022》&#xff0c;就要迎接2023了。今天是2022最后一天&#xff0c;本来是元旦假期的第一天&#xff0c;奈何要来公司加班&#xff0c;抽个时间来回顾下 2022 吧。 2022 年和2021 一样也是里程碑的一年&#xff0c;完成了两件大事&a…

使用CSS提高网站性能的30种方法

根据httparchive.org的页面重量报告&#xff0c;CSS在平均70个请求和2MB的网页上占7个HTTP请求和70Kb的代码。这并不是网站性能糟糕的最坏原因&#xff08;我正看着你呢&#xff0c;JavaScript&#xff09;&#xff0c;但CSS面临着特定的挑战&#xff1a; CSS会阻止渲染&#x…

【C++进阶】多态

文章目录多态的概念多态的定义及实现抽象类多态的原理多继承和单继承关系中的虚表函数继承和多态常见的问题多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 …

我的2022年,一位双非生的平淡一年

没有白走的路&#xff0c;每一步都算数&#x1f388;&#x1f388;&#x1f388; 前言 一谈到年终总结&#xff0c;其实还是很多的遗憾&#xff0c;我和大部分人一样&#xff0c;走过这一年的路途&#xff0c;发现自己除去每年头发越来越少&#xff0c;脸色日渐不佳。好像没有什…

Web 和移动应用程序测试之间的区别

智能手机改变了人类与技术互动的方式。无论是旅行、健身、生活方式、视频游戏&#xff0c;甚至是服务&#xff0c;都只需触手可及(字面意思就是如此)。我们只需要看看越来越多的智能手机或平板电脑用户与桌面用户就可以掌握这一现实。 根据一项调查&#xff0c;从 2021 年 4 月…

Dubbo(尚硅谷)学习笔记3

这是我们正常启动&#xff1a; 现在我们去把zookeeper注册中心关掉。 此时我们的注册中心是用不了的。 但是我们的数据还有&#xff0c;也就是我们的消费者还是能调用我们的提供者中的方法。 那么我们现在来试一下dubbo直连&#xff0c;也就是没有注册中心&#xff0c;我们也可…

VideoRender和ImageRender中的一些c++知识点

1.inline C中的inline用法_路痴的旅行的博客-CSDN博客 1 引入inline关键字的原因在c/c中&#xff0c;为了解决一些频繁调用的小函数大量消耗栈空间&#xff08;栈内存&#xff09;的问题&#xff0c;特别的引入了inline修饰符&#xff0c;表示为内联函数&#xff0c;栈空间就是…

深入理解计算机系统_静态链接和动态链接以及静态库和动态库

这篇文章记录静态链接和动态链接以及静态库和动态库的原理。 1 静态链接和动态链接 链接其实就是连接的意思&#xff0c;将所有相关的东西连接起来。 1.1 静态链接 什么是静态链接&#xff1f;编译时候的链接就是静态链接&#xff0c;所以ld/collect2链接程序&#xff0c;也…

公司让我一个人干数据中台,是不是可以准备找下家了

大数据群里&#xff0c;有个哥们问了下面这样一个问题&#xff0c;让刚刚阳康返工的群友们笑的心跳加速&#xff0c;直接炸锅。 开工有惊喜 一个人搞一个数据中台&#xff01;这是啥神仙领导做出来的决策&#xff1f;是发烧的时候拍脑袋定的吗&#xff1f;热心的群友也都给出了…

vector类的使用

目录 ​一、vector类的组织形式 二、vector类的成员函数 1.默认成员函数 &#xff08;1&#xff09;构造函数、拷贝构造函数 &#xff08;2&#xff09;析构函数和赋值运算符重载 2.容量操作 3.迭代器&#xff08;iterator&#xff09; 4.元素访问 5.修改操作 一、vec…

web3调研:Dusk Network调研

在此声明&#xff0c;仅做分享&#xff0c;绝不存在倡导炒币行为 原文链接&#xff1a;Dusk 调研报告 web3产品调研系列 1、web3调研&#xff1a;Iron fish调研 2、web3调研&#xff1a;Dusk Network调研 目录web3产品调研系列一、背景概述二、项目介绍2.1 创始团队2.2 项目融…

【数据结构】三万字图文讲解带你手撕八大排序(附源码)

&#x1f451;作者主页&#xff1a;进击的安度因 &#x1f3e0;学习社区&#xff1a;进击的安度因&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 文章目录一、前言二、排序的概念和运用三、八大排序讲解及实现1、直接插入排序1.1 排序思路1.2 代…

Java重点源码回顾——ConcurrentHashMap1.7

1. 概述 HashMap在我们的日常生活中使用很多&#xff0c;但是它不是线程安全的。我们可以使用HashTable来代替&#xff0c;主要实现方式是在方法中加入synchronized&#xff0c;所以效率也比较低。因此&#xff0c;对于键值对&#xff0c;我们可以尝试使用ConcurrentHashMap来…

《Java 后端面试经》微服务篇

《Java 后端面试经》专栏文章索引&#xff1a; 《Java 后端面试经》Java 基础篇 《Java 后端面试经》Java EE 篇 《Java 后端面试经》数据库篇 《Java 后端面试经》多线程与并发编程篇 《Java 后端面试经》JVM 篇 《Java 后端面试经》操作系统篇 《Java 后端面试经》Linux 篇 《…

关于Linux 网络抓包的一些笔记整理

写在前面 遇到一个 ping 单通 的情况&#xff0c;需要抓包分析下&#xff0c;所以整理这部分笔记博文内容涉及&#xff1a; HTTP/TCP 抓包分析 DemoICMP 抓包分析 DemoNginx 抓包分析用户名密码 Demo 理解不足小伙伴帮忙指正 这世界的存在完全只是就它对一个其他事物的&#xf…

【自学Java】Java选择结构if

Java选择结构if Java语言if条件判断 在 Java 中&#xff0c;关键字 if 是用于测试某个条件&#xff08;布尔型或逻辑型&#xff09;的语句是否满足一定的条件&#xff0c;如果满足特定的条件&#xff0c;则会执行 if 后面的大括号 {} 括起来的代码块&#xff0c;如果没有代码…

hnu社交网络分析作业2

前言&#xff1a;前言&#xff1a;上的是林剑新老师的课程&#xff0c;还是比较有意思的&#xff0c;此博客用来记录作业的学习情况&#xff0c;答案为老师提供的 一、2 跳标签索引是一种在网络中进行距离查询时广泛使用的技术。算法 1 描述了一种在无向图中构造 2 跳标签索引…

Java 接口介绍和使用

1.什么是接口&#xff1f; 接口就是给出一些没有实现的方法&#xff0c;封装到一起&#xff0c;当某一个类要使用的时候再实现出来。 2.接口的语法 interface name{ attributes methods } 比如如下USB接口 public interface Usb {public void start();public void s…