设计模式复习

news2024/10/7 12:24:20

单例模式

确保一个类最多只有一个实例,并提供一个全局访问点。

(某个类的对象有且仅有一个,单例的对象充当的是全局变量的角色,为什么在C++里面不直接使用全局变量,而是使用单例来代替全局变量,因为如果直接使用全局变量会破坏类的封装,全局变量没有被封装,他的访问权限是不受限制的,任何模块在任意位置都可以对全局变量进行读或者写的操作,如果在程序中大量使用全局变量,全局变量在一个位置被恶意篡改,在其他位置获取全局变量会产生影响,其他模块在工作的时候就得不到正确的值了,解决方案就是使用单例模式,全局变量被封装到一个类里面,并且被private修饰,就不会在类外被随意访问,在单例模式的类里面提供对私有成员的访问函数,对变量的读和写设定指定的规则,这样类里面的数据不是直接被访问的,而是间接被访问的,间接的通过单例模式的类提供的成员函数进行访问,这样既把数据进行了封装又可以保证数据的安全性)

创建一个单例模式的类

构造拷贝构造私有,提供静态公有的获取方法 

类外new来创建对象已经不行了,只能通过类名得到对象,所以对象是静态的

饿汉模式 :定义类的时候创建单例对象

还没有使用该单例对象,该单例对象就已经被加载到内存了,在对象过多时会造成内存浪费,在多线程模式下,饿汉模式没有线程安全问题

#include<iostream>
using namespace std;

//饿汉模式->定义类的时候创建单例对象
//定义一个单例模式的任务队列
class TaskQueue
{
public:
	static TaskQueue* getInstance()
	{
		return m_taskQ;
	}
	void pirntf() {
		cout << "sss" << endl;
	}

private:
	TaskQueue() = default;
	TaskQueue(const TaskQueue& t) = default;

	static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;

int main() {
	TaskQueue* taskQ = TaskQueue::getInstance();
	taskQ->pirntf();

	return 0;
}

懒汉模式:什么时候使用这个单例对象,在使用的时候再去创建对应的实例

解决了饿汉式内存浪费问题,但是线程不安全的,可以通过互斥量mutex.lock()和mutex.unlock()来解决 

#include<iostream>
using namespace std;

//定义一个单例模式的任务队列
class TaskQueue
{
public:
	static TaskQueue* getInstance()
	{
        if(m_taskQ == nullptr)
        {
            m_taskQ = new TaskQueue;
        }
		return m_taskQ;
	}
	void pirntf() {
		cout << "sss" << endl;
	}

private:
	TaskQueue() = default;
	TaskQueue(const TaskQueue& t) = default;

	static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = nullptr;

int main() {
	TaskQueue* taskQ = TaskQueue::getInstance();
	taskQ->pirntf();

	return 0;
}

类加载的时候,没有立刻实例化,第一次调用getInstance()的时候,才真的实例化.

如果要是代码一整场都没有调用getInstance,此时实例化的过程也就被省略掉了,

我们一般成懒汉模式为“懒加载”或者“延时加载”,“懒汉模式"比“饿汉模式"效率更高,有很大的可能是“实例用不到",此时就节省了实例化的开销。

饿汉模式,懒汉模式线程安全吗?
了解了线程安全之后,对于饿汉模式来说,多线程同时调用getInstance(),由于getInstance()里只做了一件事:读取instance实例的地址,也就是多个线程在同时读取同一个变量,并没有构成多个线程同时修改同一个变量这一情况,所以说饿汉模式是线程安全的。

而对于懒汉模式来说,多线程调用getInstance(),getInstance()做了四件事情~

1.读取 instance 的内容

2.判断 instance 是否为 null

3.如果 instance 为null,就 new实例 (这就会修改 intance 的值)

4.返回实例的地址

由于懒汉模式造成了多个线程同时修改同一个变量这一情况,所以说懒汉模式是线程不安全的。

懒汉模式-使用双重检查锁定解决线程安全问题 

比如说三个线程A B C 同时访问 ,第一次判空,到锁那阻塞,A先进去第二次判空创建对象 B C等A完事锁解开才能进去 第一次ABC是一个接一个进去,如果再来三个线程的话会直接判断非空,直接到return m_taskQ了,使程序的效率提升。

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

//定义一个单例模式的任务队列
class TaskQueue
{
public:
	static TaskQueue* getInstance()
	{
		if (m_taskQ == nullptr) {
			m_mutex.lock();
			if (m_taskQ == nullptr) {
				m_taskQ = new TaskQueue;
			}
			m_mutex.unlock();
		}
        return m_taskQ;
	}
	void pirntf() {
		cout << "sss" << endl;
	}

private:
	TaskQueue() = default;
	TaskQueue(const TaskQueue& t) = default;

	static TaskQueue* m_taskQ;
	static mutex m_mutex;
};
TaskQueue* TaskQueue::m_taskQ = nullptr;
mutex TaskQueue::m_mutex;

int main() {
	TaskQueue* taskQ = TaskQueue::getInstance();
	taskQ->pirntf();

	return 0;
}

工厂模式

主要是对对象的创建进行了一个封装,提供了一种创建对象的方式。

(1)在没有工厂的时代,如果客户需要一款宝马车,那么就需要客户去创建一款宝马车,然后拿来用。

(2)简单工厂模式:后来出现了工厂,用户不再需要去创建宝马车,由工厂进行创建,想要什么车,直接通过工厂创建就可以了。比如想要320i系列车,工厂就创建这个系列的车。

(3)工厂方法模式:为了满足客户,宝马车系列越来越多,如320i、523i等等系列,一个工厂无法创建所有的宝马系列,于是又单独分出来多个具体的工厂,每个具体工厂创建一种系列,即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象,你需要指定某个具体的工厂才能生产车出来。

(4)抽象工厂模式:随着客户要求越来越高,宝马车必须配置空调,于是这个工厂开始生产宝马车和需要的空调。最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车。

简单工厂模式

简单工厂模式的结构组成

1. 工厂类:工厂模式的核心类,会定义一个用于创建指定的具体实例对象的接口。

2. 抽象产品类:是具体产品类的继承的父类或实现的接口。

3. 具体产品类:工厂类所创建的对象就是此具体产品实例

#include<iostream>
using namespace std;

// 产品类的父亲 - 人造恶魔果实
class AbstractSmile
{
public:
	virtual void transform() = 0;
	virtual void ability() = 0;
	virtual ~AbstractSmile(){}
};

class SheepSmile :public AbstractSmile
{
public:
	void transform() override
	{
		cout << "变身-山羊形态。。" << endl;
	}
	void ability() override
	{
		cout << "将手臂变成羊角。。" << endl;
	}
};

class LionSmile :public AbstractSmile
{
public:
	void transform() override
	{
		cout << "变身-狮子人形态。。" << endl;
	}
	void ability() override
	{
		cout << "火遁。。" << endl;
	}
};

class BatSmile :public AbstractSmile
{
public:
	void transform() override
	{
		cout << "变身-蝙蝠人形态。。" << endl;
	}
	void ability() override
	{
		cout << "吸血。。" << endl;
	}
};

//定义工厂类
enum class Type:char{Sheep,Lion,Bat};
class SmileFactory
{
public:
	AbstractSmile* createSmile(Type type)
	{
		AbstractSmile* ptr = nullptr;
		switch (type)
		{
		case Type::Sheep:
			ptr = new SheepSmile;
			break;
		case Type::Lion:
			ptr = new LionSmile;
			break;
		case Type::Bat:
			ptr = new BatSmile;
			break;
		default:
			break;
		}
		return ptr;
	}
};

int main()
{
	SmileFactory* factroy = new SmileFactory;
	AbstractSmile* obj = factroy->createSmile(Type::Lion);
	obj->transform();
	obj->ability();
	return 0;
}

可以看到,简单工厂可以做到,让用户创建对象的时候只需要知道对象的名称(BMW、AUDI)就好,而不需要关心创建对象的细节(BMW是如何建造的、型号是什么等等细节)。

当然缺点也很明显:
每当我们想要扩展对象的时候(增加BENZ的对象)就需要在SimpleFactory类中添加代码,增加switch后面的case选项。这样一来,就需要修改源代码。灵活性非常的差!!!

那么,能不能做到添加对象的时候,不对现有代码进行修改呢?(也就是我们开发软件时候需要遵守的开-闭原则)

工厂模式

工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。

        但缺点在于,每增加一个产品都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

工厂方法模式的结构组成:

1. 抽象工厂类:工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。

2. 具体工厂类:继承于抽象工厂,实现创建对应具体产品对象的方式。

3. 抽象产品类:它是具体产品继承的父类(基类)。

4. 具体产品类:具体工厂所创建的对象,就是此类。

(自己理解就是,工厂模式相当于简单工厂模式,如果需要增加新产品,只需要增加新的产品类继承抽象产品类,再增加生产该类型产品的工厂继承抽象工厂类,只需要拓展代码而不需要更改原先的代码)

#include<iostream>
using namespace std;

// 产品类的父亲 - 人造恶魔果实
class AbstractSmile
{
public:
	virtual void transform() = 0;
	virtual void ability() = 0;
	virtual ~AbstractSmile(){}
};

class SheepSmile :public AbstractSmile
{
public:
	void transform() override
	{
		cout << "变身-山羊形态。。" << endl;
	}
	void ability() override
	{
		cout << "将手臂变成羊角。。" << endl;
	}
};

class LionSmile :public AbstractSmile
{
public:
	void transform() override
	{
		cout << "变身-狮子人形态。。" << endl;
	}
	void ability() override
	{
		cout << "火遁。。" << endl;
	}
};

class BatSmile :public AbstractSmile
{
public:
	void transform() override
	{
		cout << "变身-蝙蝠人形态。。" << endl;
	}
	void ability() override
	{
		cout << "吸血。。" << endl;
	}
};

//定义工厂类  - 父类
class AbstractFactory
{
public:
	virtual AbstractSmile* createSmile() = 0;
	virtual ~AbstractFactory(){}
};

// 生产山羊的恶魔果实
class SheepFactory:public AbstractFactory
{
public:
	AbstractSmile* createSmile()
	{
		return new SheepSmile;
	}
	~SheepFactory()
	{
		cout << "SheepFactory 被析构了。。" << endl;
	}
};

// 生产狮子的恶魔果实
class LionFactory :public AbstractFactory
{
public:
	AbstractSmile* createSmile()
	{
		return new LionSmile;
	}
	~LionFactory()
	{
		cout << "LionFactory 被析构了。。" << endl;
	}
};

// 生产蝙蝠的恶魔果实
class BatFactory :public AbstractFactory
{
public:
	AbstractSmile* createSmile()
	{
		return new BatSmile;
	}
	~BatFactory()
	{
		cout << "BatFactory 被析构了。。" << endl;
	}
};

int main()
{
	AbstractFactory* factroy = new LionFactory;
	AbstractSmile* obj = factroy->createSmile();
	obj->transform();
	obj->ability();

	delete obj;
	delete factroy;
	return 0;
}

抽象工厂模式

抽象工厂模式的结构组成(和工厂方法模式一样):

1. 抽象工厂类:工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。

2. 具体工厂类:继承于抽象工厂,实现创建对应具体产品对象的方式。

3. 抽象产品类:它是具体产品继承的父类(基类)。

4. 具体产品类:具体工厂所创建的对象,就是此类。

抽象工厂模式的特点:

提供一个接口,可以创建多个产品族中的产品对象。比如船工厂,可以创建基础款船,升级款船

#include<iostream>
using namespace std;

//船体
class shipBody
{
public:
	virtual string getBody() = 0;
	virtual ~shipBody(){}
};

//木头船体
class WoodBody :public shipBody
{
public:
	string getBody() override
	{
		return "使用<木头>制作船体";
	}
};

//钢铁船体
class IronBody :public shipBody
{
public:
	string getBody() override
	{
		return "使用<钢铁>制作船体";
	}
};


//引擎
class Engine
{
public:
	virtual string getEngine() = 0;
	virtual ~Engine(){}
};

class Human :public Engine
{
public:
	string getEngine()
	{
		return "船体动力方式是<手动>";
	}
};

class Diesel :public Engine
{
public:
	string getEngine()
	{
		return "船体动力方式是<内燃机>";
	}
};


//船
class Ship
{
public:
	Ship(shipBody*body,Engine* engine):
		m_body(body),m_engine(engine){}
	~Ship()
	{
		delete m_body;
		delete m_engine;
	}
	string getProperty()
	{
		string Info = m_body->getBody() + m_engine->getEngine();
		return Info;
	}

private:
	shipBody* m_body;
	Engine* m_engine;
};

//工厂类 - 抽象
class AbstractFactory
{
public:
	virtual Ship* createShip() = 0;
	virtual ~AbstractFactory(){}
};

class BasicFactory :public AbstractFactory
{
public:
	Ship* createShip() override
	{
		Ship* ship = new Ship(new WoodBody, new Human);
		cout << "<基础形>海贼船已经打造完毕" << endl;
		return ship;
	}
};

class StandardFactory :public AbstractFactory
{
public:
	Ship* createShip() override
	{
		Ship* ship = new Ship(new IronBody, new Diesel);
		cout << "<标准形>海贼船已经打造完毕" << endl;
		return ship;
	}
};

int main()
{
	//下单标准型海贼船
	AbstractFactory* factory = new StandardFactory;
	Ship* ship = factory->createShip();
	cout<<ship->getProperty();
	delete ship;
	delete factory;
	return 0;
}

抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象

工厂模式只能生产一个产品。例如:产品要么香蕉、要么苹果,但抽象工厂可以一下生产一个产品族,如水果、动物、蔬菜等

#include<iostream>
using namespace std;


class AbstractFactory;

//抽象产品族Tea,茶可以是都匀毛尖、铁观音、普洱等品种。
class Tea{
public:
	virtual void getName() = 0;
};

//抽象产品族Fruit
class Fruit{
public:
	virtual void getName() = 0;
};

//抽象工厂,声明具体可以生产的产品族
class AbstractFactory{
public:
	virtual Tea* CreateTea() = 0;//生产产品族Tea
	virtual Fruit* CreateFruit() = 0 ;//生产产品族Fruit
};

//水果族的具体水果
class AppleFruit:public Fruit{
public:
	void getName(){
	    cout<<"I'm Apple"<<endl;
	}
};
class BananaFruit:public Fruit{
public:
	void getName(){
	    cout<<"I'm Banana"<<endl;
	}
};

//茶族的具体茶
class DuyunTea:public Tea{
public:
	void getName(){
	    cout<<"I'm maojianTea"<<endl;
	}
};
class PuerhTea:public Tea{
public:
	void getName(){
	    cout<<"I'm PuerhTea"<<endl;
	}
};

//具体工厂,都匀工厂
class DunyunFactory:public AbstractFactory{
public:
	Tea* CreateTea(){
		return new DuyunTea;
	}
	Fruit* CreateFruit(){
		return new BananaFruit();
	}
};
//具体工厂,云南工厂
class YunnanFactory:public AbstractFactory{
public:
	Tea* CreateTea(){
		return new PuerhTea;
	}
	Fruit* CreateFruit(){
		return new AppleFruit();
	}
};
int main(){

	AbstractFactory* factory = nullptr;
	Fruit *fruit = nullptr;
	Tea   *tea = nullptr;

	//都匀工厂
	factory = new DunyunFactory;
	tea = factory->CreateTea();
	tea->getName();
	delete tea;
	fruit = factory->CreateFruit();
	fruit->getName();
	delete fruit;

	delete factory;

	//云南工厂
	factory = new YunnanFactory;
	tea = factory->CreateTea();
	tea->getName();
	delete tea;
	fruit = factory->CreateFruit();
	fruit->getName();
	delete fruit;

	delete factory;
	return 0;
}

以上只是我的学习过程,真正写的牛逼还清晰的还是下边这个 。。。。。

C++ 深入浅出工厂模式(初识篇) - 知乎 (zhihu.com)

中介者模式 

中介者模式可以减少对象之间混乱无序的依赖关系,从而使其耦合松散,限制对象之间的直接交互,迫使他们通过一个中介者对象进行合作。

如果编写一个类,这个类的功能强大,但是和其他的类的耦合度非常高,我们在使用这个类的时候就会考虑很多情况,所以感觉复用这个类比较吃力的时候,就可以使用中介者模式,把这个耦合度高的类进行拆分,分离之后就会得到一个中介者类,通过中介者类对其他的类进行服务。

生活中最常见的例子就是租房中介是一种中介,如果我们想要租房可以通过中介和房东沟通,这时候其实并不需要知道对方是谁,也并不需要面对面,类似于电话、QQ、微信等等都是中介,能大大降低了沟通的复杂性。还有飞机塔台。。。 

优点:

  • 降低了对象之间的耦合性,增加了它们的独立性和可维护性。
  • 减少了对象间的直接通信,简化了对象之间的关系,降低了系统的复杂性。

缺点:

  • 中介者对象会成为系统的核心,并承担大量的职责,如果这些职责变得过于复杂,就会导致中介者对象变得过于庞大和难以维护。
  • 可能会降低整体系统的效率,因为所有的通信都需要经过中介者对象。

应用场景:

  • 当对象之间的关系过于复杂,而且它们之间的依赖关系难以理解和管理时,可以考虑使用中介者模式,将这些依赖管理起来。
  • 当一个对象需要和多个其他对象进行互动,并且这些对象之间存在复杂的互动关系时,可以考虑使用中介者模式,将它们之间的交互都集中到一个中介者对象中。
  • 当修改一个对象会涉及到许多其他对象时,可以使用中介者模式来避免修改所有对象,只需要更新中介者即可。
  • 当一组对象在协作过程中会产生大量相互关联的代码时,可以使用中介者模式来将其抽象出来,更好地隐藏其复杂性。

中介者模式包含以下主要角色。

  1. 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  2. 具体中介者(Concrete Mediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  3. 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  4. 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

 类似于网络类,tcp udp继承网络类。中介者类与网络类有对应的指针关联

观察者模式

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

在观察者模式中有如下角色:

Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

观察者模式这种发布-订阅的形式我们可以拿微信公众号来举例,假设微信用户就是观察者,微信公众号是被观察者,有多个的微信用户关注了程序猿这个公众号,当这个公众号更新时就会通知这些订阅的微信用户。好了我们来看看用代码如何实现:

 

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

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

相关文章

07 按键控制 LED

按键简介 按键开关是一种电子开关&#xff0c;属于电子元器件类。常见的按键开关有两种&#xff0c;第一种是轻触式按键开关&#xff08;简称轻触开关&#xff09;&#xff0c;使用时以向开关的操作方向施加压力使内部电路闭合接通&#xff0c;当撤销压力时开关断开&#xff0…

html的表单标签(上):form标签和input标签

表单标签 表单是让用户输入信息的重要途径。 用表单标签来完成与服务器的一次交互&#xff0c;比如你登录QQ账号时的场景。 表单分成两个部分&#xff1a; 表单域&#xff1a;包含表单元素的区域&#xff0c;用form标签来表示。表单控件&#xff1a;输入框&#xff0c;提交按…

48 slab 的实现

前言 这里说的是 内核中分配小对象的一种内存分配方式 slab 呵呵 经典程度不必多说了, 内核使用的大多数数据结构 基本上是基于 slab 进行内存分配的 这里 我们来看一下 slab 如何分配对象 几个分配层级, c->free_list, c->page, c->partial, new_slab 1. 先…

【HarmonyOS】【DevEco ohpm ERROR: NOTFOUND package “@ohos/hypium“如何解决

参考 &#xff1a;&#xff08;无效&#xff09; 华为开发者论坛 DevEco创建项目时的错误解决_6 月 优质更文活动_路北路陈_InfoQ写作社区 解决&#xff1a; HormonyOS-DevEco Studio新建空项目ERROR解决_oh_modules\ohos\hypium-CSDN博客 将 .ohpm文件夹中的hypium文件夹复…

Openharmony - HDF驱动小示例和测试程序

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 1. 创建KHDF示例驱动1.1. 创建KHDF项目1.2. HDF驱动程序实现1.2.1. 驱动入口1.2.2. 实现Dispatch方法1.2.3. 硬件业务初始化与释放1.2…

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第10章 项目进度管理(六)

博主2023年11月通过了信息系统项目管理的考试&#xff0c;考试过程中发现考试的内容全部是教材中的内容&#xff0c;非常符合我学习的思路&#xff0c;因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家&#xff0c;希望更多的人能够通过考试&a…

Flink Catalog 解读与同步 Hudi 表元数据的最佳实践

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

python-Scrapy框架入门1111111111111

此网站爬取江南大学官网新闻信息 https://news.jiangnan.edu.cn/yw.htm Scrapy安装 mac | Linux : pip install scrapy windows: pip install wheelpip install pywin32安装Twisted &#xff1a; pip install Twisted_iocpsupport-1.0.2-cp310-cp310-win_amd64.whl (该文件去…

使用Nginx或者Fiddler快速代理调试

1 背景问题 在分析业务系统程序问题时,存在服务系统环境是其它部门或者其它小组搭建或运维的,并且现在微服务时代,服务多且复杂,在个人机器上搭建起如此环境,要么费事费力,要么不具备充足条件。 急需有一种方法或者工具可以快速辅助调试定位分析问题。本文下面介绍代理方…

算法沉淀——多源 BFS(leetcode真题剖析)

算法沉淀——多源 BFS&#xff08;leetcode真题剖析&#xff09; 01.矩阵02.飞地的数量03.地图中的最高点04.地图分析 多源 BFS 是指从多个源点同时进行广度优先搜索的算法。在传统的 BFS 中&#xff0c;我们通常从一个起始点开始&#xff0c;逐层遍历所有的相邻节点。而在多…

IDEA-常用插件

1、Mybatis Log Free 当我们使用mybatis log在控制台输出sql 内容&#xff0c;输出内容将语句与参数分开打印&#xff0c;还需要手动将参数替换到指定位置。 使用对应插件后&#xff0c;自动将输出内容组装成完整的可直接执行的SQL 在插件市场 查看对应名称&#xff0c;并安装。…

KMPC++(Acwing)

代码&#xff1a; #include <iostream>using namespace std;const int N 100010, M 1000010;int n, m; int ne[N]; char s[M], p[N];int main() {cin >> n >> p 1 >> m >> s 1;for (int i 2, j 0; i < n; i ){while (j && p[…

Academic Inquiry|投稿状态分享(ACS,Wiley,RSC,Elsevier,MDPI,Springer Nature出版社)

作为科研人员&#xff0c;我们经常会面临着向学术期刊投稿的问题。一般来说&#xff0c;期刊的投稿状态会在官方网站上进行公示&#xff0c;我们可以通过期刊的官方网站或者投稿系统查询到我们投稿的论文的状态&#xff0c;对于不同的期刊在投稿系统中会有不同的显示。 说明&am…

APP广告变现有哪些途径?哪种变现效果好?

无论哪种类型的APP都可以通过接入广告实现商业化变现&#xff0c;作为互联网广告载体的APP&#xff0c;比线下传统广告位更具有优势&#xff0c;不受地域限制&#xff0c;可以让广告的覆盖面更广。通过丰富的广告形式&#xff0c;精准的目标用户的画像&#xff0c;可以更好实现…

lazada、速卖通卖家如何掌握自养号测评技巧打造高评价产品?

做跨境电商卖家都知道&#xff0c;国外的买家购物比较理性&#xff0c;也喜欢货比三家&#xff0c;所以店铺想要留住客户&#xff0c;就需要一些优质的产品来吸引他们。产品评价是卖家获取买家信任的重要途径&#xff0c;评价越高的产品&#xff0c;销量也就越好。 尤其是 Shop…

ClickHouse监控及备份

第1章 ClickHouse监控概述 第2章 Prometheus&Grafana的安装 第3章 ClickHouse配置 第4章 Grafana集成Prometheus 第5章 备份及恢复

佳能2580的下载手册

凡是和电子产品有关的产品其内部都开始不断地进行内卷&#xff0c;在不断地内卷背后&#xff0c;意味着科技更新和换代&#xff0c;自己也入手了一台佳能2580的打印机&#xff0c;一台相对比较老式的打印机&#xff0c;以此不断地自己想要进行打印的需要。 下载的基础步骤&…

应急响应实战笔记02日志分析篇(5)

第5篇:MySQL日志分析 常见的数据库攻击包括弱口令、SQL注入、提升权限、窃取备份等。对数据库日志进行分析&#xff0c;可以发现攻击行为&#xff0c;进一步还原攻击场景及追溯攻击源。 0x01 Mysql日志分析 general query log能记录成功连接和每次执行的查询&#xff0c;我们…

【算法】基础算法002之滑动窗口(二)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 5.水果成篮&#xff…

jq 图片懒加载 + Vue-Lazyload

jq原生 图片 懒加载 <!DOCTYPE html> <html lang"zh-cn"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compati…