c++设计模式

设计模式

目标:面向对象系统的分析和设计实际上追求的就是两点:高内聚合低耦合

定义:一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结(可靠的模板代码)

核心思想:隔代变化,封装变化

分类:
创建型模式:创建对象的同时隐藏创建逻辑的方式
工厂设计模式:

简单工厂模式(抽象产品,工厂类生产不同的具体产品)
角色:抽象产品类、具体产品、工厂类
缺点:内聚性较差(不符合开闭原则):增加新的产品会改动工厂类
优点:一个工厂生产不同的产品

#include<iostream>//简单工厂
using namespace std;

class car//抽象产品
{
public:
	virtual void show() = 0;
};
class BMW :public car//具体产品:宝马
{
public:
	void show()
	{
		cout << "BMW" << endl;
	}
};
class BENZ :public car//具体产品:奔驰
{
public:
	void show()
	{
		cout << "BENZ" << endl;
	}
};
class AUDI :public car//具体产品:奥迪
{
public:
	void show()
	{
		cout << "AUND" << endl;
	}
};
class Factory//工厂
{
public:
	car* createBMW()
	{
		return new BMW;
	}
	car* createBENZ()
	{
		return new BENZ;
	}
	car* createAUDI()
	{
		return new AUDI;
	}
};
int main()
{
	car* c = NULL;
	Factory* f = new Factory;
	c = f->createBMW();
	c->show();

	c = f->createBENZ();
	c->show();

	c = f->createAUDI();
	c->show();
	return 0;
}

工厂模式(同时抽象工厂和产品,增加新产品和新工厂都不需要改动原有的类)
定义:将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定;
角色:抽象产品类、具体产品类、抽象工厂类、具体工厂类、模式中包含的角色及其职责

#include<iostream>//工厂模式
using namespace std;

class car//抽象产品
{
public:
	virtual void show() = 0;
};
class BMW :public car//具体产品:宝马
{
public:
	void show()
	{
		cout << "BMW" << endl;
	}
};
class BENZ :public car//具体产品:奔驰
{
public:
	void show()
	{
		cout << "BENZ" << endl;
	}
};
class AUDI :public car//具体产品:奥迪
{
public:
	void show()
	{
		cout << "AUND" << endl;
	}
};
class Factory//抽象工厂
{
public:
	virtual car* create() = 0;
};
class BMWFactory:public Factory//具体工厂
{
public:
	car* create()
	{
		return new BMW;
	}
};
class AUDIactory :public Factory//具体工厂
{
public:
	car* create()
	{
		return new AUDI;
	}
};
class BENZFactory :public Factory//具体工厂
{
public:
	car* create()
	{
		return new BENZ;
	}
};
int main()
{
	car* c = NULL;
	Factory* f = new BMWFactory;
	c = f->create();
	c->show();

	return 0;
}

抽象工厂模式(生产不同产品族的同一类产品,缺点是增加新产品一定会改动代码)
定义:为创建一组相关或者相互依赖的对象提供的一个接口,而不需要指定它们的具体类。
角色:与工厂模式一样
缺点:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

#include<iostream>//抽象工厂
using namespace std;

class fruit
{
public:
	virtual void show() = 0;
};

class Northpear :public fruit
{
	void show()
	{
		cout << "Northpear" << endl;
	}
};
class Northapple :public fruit
{
	void show()
	{
		cout << "Northapple" << endl;
	}
};
class Southapple :public fruit
{
	void show()
	{
		cout << "Southapple" << endl;
	}
};
class Southpear :public fruit
{
	void show()
	{
		cout << "Southpear" << endl;
	}
};
class Factory
{
public:
	virtual fruit* createpear() = 0;
	virtual fruit* createapple() = 0;
};

class NorthFactory :public Factory
{
public:
	fruit* createapple()
	{
		return new Northapple;
	}
	fruit* createpear()
	{
		return new Northpear;
	}
};

class SouthFactory :public Factory
{
public:
	fruit* createapple()
	{
		return new Southapple;
	}
	fruit* createpear()
	{
		return new Southpear;
	}
};

void create(Factory* f)
{
	fruit* fr = NULL;
	fr = f->createapple();
	fr->show();
	delete fr;

	fr = f->createpear();
	fr->show();
	delete fr;
}
int main()
{
	Factory* f = new NorthFactory;
	create(f);
	delete f;

	f = new SouthFactory;
	create(f);
	delete f;

	return 0;
}

单例模式(7种实现方法)
一个类只允许创建一个对象
步骤:
1)构造函数私有化
2) 提供一个全局的静态方法(全局访问点)
3) 在类中定义一个静态指针,指向本类的变量的静态变量指针
分类:
1、懒汉式:对象是在调用接口时构造

#include<iostream>//懒汉式:对象是在调用接口时构造
using namespace std;

class singleton
{
public:
	static singleton* getinstance()//提供给外部的接口
	{
		objcount++;
		if (minstance == NULL)
		{
			minstance = new singleton;
		}
		return minstance;
	}

	static int getobjcount()
	{
		return objcount;
	}
	static void release()
	{
		objcount--;
		if (objcount == 0 && minstance != NULL)
		{
			delete minstance;
			minstance = NULL;
		}
	}
private:
	static singleton* minstance;
	static int objcount;
private:
	singleton() { cout << "构造函数被调用" << endl; }//构造函数私有化
};

singleton* singleton::minstance = NULL;
int singleton::objcount = 0;

int main()
{
	singleton* s1 = singleton::getinstance();
	singleton* s2 = singleton::getinstance();
	singleton* s3 = singleton::getinstance();
	cout << singleton::getobjcount() << endl;
	return 0;
}

2、饿汉式:在初始化时就进行对象构造

#include<iostream>//饿汉式:在初始化时就进行对象构造
using namespace std;

class singleton
{
public:
	static singleton* getinstance()//提供给外部的接口
	{
		objcount++;
		
		return minstance;
	}

	static int getobjcount()
	{
		return objcount;
	}
	static void release()
	{
		objcount--;
		if (objcount == 0 && minstance != NULL)
		{
			delete minstance;
			minstance = NULL;
		}
	}
private:
	static singleton* minstance;
	static int objcount;
private:
	singleton() { cout << "构造函数被调用" << endl; }//构造函数私有化
};

singleton* singleton::minstance = new singleton;
int singleton::objcount = 0;

int main()
{
	singleton* s1 = singleton::getinstance();
	singleton* s2 = singleton::getinstance();
	singleton* s3 = singleton::getinstance();
	cout << singleton::getobjcount() << endl;
	return 0;
}

多线程编程时的单例实现:
(1、懒汉式多线程中可能多次创建对象,线程不安全
2、饿汉式线程安全,因为一开始就初始化,可能会产生垃圾值)
懒汉式线程不安全,延迟初始化,严格意义上不是单例模式

饿汉式线程安全,比较常用,但容易产生垃圾,因为一开始就初始化

#include<iostream>//懒汉式:对象是在调用接口时构造

#include<pthread.h>
using namespace std;

class singleton
{
public:
	static singleton* getinstance()//提供给外部的接口
	{
		objcount++;
		if (minstance == NULL)
		{
			minstance = new singleton;
		}
		return minstance;
	}

	static int getobjcount()
	{
		return objcount;
	}
	static void release()
	{
		objcount--;
		if (objcount == 0 && minstance != NULL)
		{
			delete minstance;
			minstance = NULL;
		}
	}
private:
	static singleton* minstance;
	static int objcount;
private:
	singleton() { cout << "构造函数被调用" << endl; }//构造函数私有化
};

singleton* singleton::minstance = NULL;
int singleton::objcount = 0;

void* create(void* arg)
{
	singleton* s = singleton::getinstance();
	cout << s << endl;
}
int main()
{
	int ret;
	pthread_t pid[10];
	for (int i = 0; i < 10; i++)
	{
		ret = pthread_create(&pid[i], NULL, create, NULL);
	}
	void* status;
	for (int i = 0; i < 10; i++)
	{
		pthread_join(pid[i], &status);
	}
	singleton::release();
	return 0;
}

解决方式:智能指针,锁(影响性能),还可以使用局部静态变量

#include<iostream>//懒汉式:对象是在调用接口时构造

#include<pthread.h>
using namespace std;

pthread_mutex_t mutex;
class singleton
{
public:
	static singleton* getinstance()//提供给外部的接口
	{
		objcount++;
		if (minstance == NULL)
		{
			minstance = new singleton;
		}
		return minstance;
	}

	static int getobjcount()
	{
		return objcount;
	}
	static void release()
	{
		objcount--;
		if (objcount == 0 && minstance != NULL)
		{
			delete minstance;
			minstance = NULL;
		}
	}
private:
	static singleton* minstance;
	static int objcount;
private:
	singleton() { cout << "构造函数被调用" << endl; }//构造函数私有化
};

singleton* singleton::minstance = NULL;
int singleton::objcount = 0;

void* create(void* arg)
{
	pthread_mutex_lock(&mutex);
	singleton* s = singleton::getinstance();
	cout << s << endl;
	pthread_mutex_unlock(&mutex);
}
int main()
{
	int ret;
	pthread_t pid[10];
	pthread_mutex_init(&mutex, NULL);
	for (int i = 0; i < 10; i++)
	{
		ret = pthread_create(&pid[i], NULL, create, NULL);
	}
	void* status;
	for (int i = 0; i < 10; i++)
	{
		pthread_join(pid[i], &status);
	}
	singleton::release();
	pthread_mutex_destroy(&mutex);
	return 0;
}

建造者模式
定义:
是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部结构细节的情况下,可以更精细的控制对象的构造流程

作用:
为了将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离开来

角色:
产品角色、抽象建造者、具体建造者、指挥者

优点:封装性好,创建和使用分离。扩展性好,建造类之间独立,一定程度上解耦

缺点:产生多余的Builder对象。产生内部发生变化,建造者都要修改,成本较大

与工厂模式区别:
1)建造者更注重方法的调用顺序
2)建造者可以创建复杂的产品由各种复杂的部件组成,工厂模式创建的都是一个样
3)工厂模式只关注产品被建造出来,建造者模式关心组成的细节

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

class Car
{
public:
	void setengine(string engine) { m_engine = engine; }
	void setwheel(string wheel) { m_wheel = wheel; }
	void setbody(string body) { m_body = body; }
	void display() { cout << m_engine << "," << m_wheel << "," << m_body << endl; };
private:
	string m_engine;//引擎
	string m_wheel;//轮胎
	string m_body;//车身
};
//建造者模式的抽象类:组装的流程
class Assemble
{
public:
	virtual void assembleengin() = 0;//引擎的选择
	virtual void assemblewheel() = 0;//轮胎的选择
	virtual void assemblebody() = 0;//车身选择
	virtual Car* getcar() = 0;//组装的车子
};

//A型车组装
class AssembleA :public Assemble
{
public:
	AssembleA() { carA = new Car(); }
	void assembleengin() { carA->setengine("engineA"); }
	void assemblewheel() { carA->setwheel("wheelA"); }
	void assemblebody() { carA->setbody("bodyA"); }

	Car* getcar() { return carA; }
private:
	Car* carA;
};

//B型车组装
class AssembleB :public Assemble
{
public:
	AssembleB() { carB = new Car(); }
	void assembleengin() { carB->setengine("engineB"); }
	void assemblewheel() { carB->setwheel("wheelB"); }
	void assemblebody() { carB->setbody("bodyB"); }

	Car* getcar() { return carB; }
private:
	Car* carB;
};

//生产汽车的工厂类
class Factory
{
public:
	Factory(Assemble* assemble) { m_assemble = assemble; }
	void assemblecar()
	{
		m_assemble->assembleengin();
		m_assemble->assemblewheel();
		m_assemble->assemblebody();
	}
	Car* getcar() { return m_assemble->getcar(); }
private:
	Assemble* m_assemble;
};
int main()
{
	Assemble* m_assemble = new AssembleB();//定下建造的车是什么类型:造车流程说明书
	Factory* f = new Factory(m_assemble);//把说明书给工厂
	f->assemblecar();
	f->getcar()->display();
	delete f;

	Assemble* m = new AssembleA();
	f = new Factory(m);
	f->assemblecar();//建造汽车
	f->getcar()->display();
	return 0;
}

原型模式(克隆模式)
定义:原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

#include<iostream>//原型模式
#include<string>
using namespace std;

class Person
{
public:
	Person(){}
	Person(string n):name(n){}
	string getname()
	{
		return name;
	}
	virtual void show() = 0;
	virtual Person* clone() = 0;//克隆函数
protected:
	string name;
};

class Student :public Person
{
public:
	Student() {}
	Student(string n, int i) :Person(n)
	{
		id = i;
	}
	void show()
	{
		cout << name << "," << id << endl;
	}
	Person* clone()//克隆:将对象和数值全部复制
	{
		Student* tmp = new Student;
		*tmp = *this;
		return tmp;
	}

private:
	int id;
};
int main()
{
	Person* s1 = new Student("张三", 1);
	s1->show();

	Person* s2 = s1->clone();
	s2->show();
	return 0;
}
#include<iostream>//原型模式
#include<string>
using namespace std;

class Person
{
public:
	Person(){}
	Person(string n):name(n){}
	string getname()
	{
		return name;
	}
	virtual void setid(int i) = 0;
	virtual void show() = 0;
	virtual Person* clone() = 0;//克隆函数
protected:
	string name;
};

class Student :public Person
{
public:
	Student() {}
	Student(string n, int i) :Person(n)
	{
		id = i;
	}
	void show()
	{
		cout << name << "," << id << endl;
	}
	void setid(int i)
	{
		id = i;
	}
	Person* clone()//克隆:将对象和数值全部复制
	{
		Student* tmp = new Student;
		*tmp = *this;
		return tmp;
	}

private:
	int id;
};
int main()
{
	Person* s1 = new Student("张三", 1);
	s1->show();

	Person* s2 = s1->clone();
	s2->show();

	s1->setid(2);
	s1->show();
	s2->show();

	return 0;
}

结构型模式:从程序的结构上解决模块之间的耦合问题
适配器模式(对象适配器模式、类适配器模式)
定义:
将一个类的接口转换成客户希望的另一个接口这样使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
区别:
对象适配器构造的时候将具体需要适配的适配对象传入,这样便可以根据传入不同的对象,从而对该对象进行适配。
类适配器却无法选择对象,他是整个类进行适配。也就是把所有的三相插口全部转换成两相的,而不是针对某一个。
实例(STL中stack)

#include<iostream>//类适配器模式
using namespace std;

class USB
{
public:
	virtual void isusb()
	{
		cout << "USB接口" << endl;
	}
};
class typec
{
public:
	void istypec()
	{
		cout << "typec接口" << endl;
	}
};
class Adapter :public USB, public typec
{
	void isusb()
	{
		istypec();
	}
};
int main()
{
	USB* usb = new Adapter();
	usb->isusb();

	return 0;
}
#include<iostream>//对象适配器模式
using namespace std;

class USB
{
public:
	virtual void isusb()
	{
		cout << "USB接口" << endl;
	}
};
class typec
{
public:
	void istypec()
	{
		cout << "typec接口" << endl;
	}
};
class Adapter :public USB
{
	void isusb()
	{
		p->istypec();
	}
private:
	typec* p = new typec;
};
int main()
{
	USB* usb = new Adapter();
	usb->isusb();

	return 0;
}
#include<iostream>//对象适配器模式
using namespace std;

class USB
{
public:
	virtual void isusb()
	{
		cout << "USB接口" << endl;
	}
};
class typec
{
public:
	void istypec()
	{
		cout << "typec接口" << endl;
	}
};
class Adapter :public USB
{
public:
	void isusb()
	{
		p->istypec();
	}
private:
	typec* p = new typec;
};
int main()
{
	USB* usb = new Adapter();
	usb->isusb();

	return 0;
}

外观模式
定义:
提供了一个统一的接口,用来访问子系统的一群接口,外观定义了一个高层接口,让子系统更容易使用

作用:
简化你的类的接口,将一系列的复杂的过程封装到内部,对外只提供最简单的接口

角色:
外观角色、子系统角色

优点:
减少系统的相互依赖,所有的依赖都是对外观类的依赖,与子系统无关
对用户隐藏了子系统的具体实现,减少用户对子系统的耦合,这样即使具体的子系统发生了变化,用户也不会感知到
加强了安全性,子系统中的方法如果不在外观类中开通,就无法访问到子系统中的方法

缺点:
不符合开发封闭性原则,如果业务出现变更,则可能要直接修改外观类

#include<iostream>//智能家居系统
using namespace std;

class lightsystem//灯光系统
{
public:
	void on()
	{
		cout << "开灯" << endl;
	}
	void off()
	{
		cout << "关灯" << endl;
	}
};

class moviesystem //电影系统
{
public:
	void on()
	{
		cout << "开电影" << endl;
	}
	void off()
	{
		cout << "关电影" << endl;
	}
};

class soundersystem
{
public:
	void on()
	{
		cout << "开音响" << endl;
	}
	void off()
	{
		cout << "关音响" << endl;
	}
};

class musicsystem
{
public:
	void on()
	{
		cout << "开音乐" << endl;
	}
	void off()
	{
		cout << "关音乐" << endl;
	}
};

class homesystem //家居系统
{
public:
	void openKTV()//KTV模式
	{
		light.off();
		sounder.on();
		music.on();
		cout << "KTV模式已启动!" << endl;
	}
	void openmovie()//观影模式
	{
		light.off();
		sounder.on();
		movie.on();
		cout << "观影模式已启动!" << endl;
	}
private:
	lightsystem light;
	moviesystem movie;
	musicsystem music;
	soundersystem sounder;
};
int main()
{
	homesystem home;
	home.openKTV();

	home.openmovie();
	return 0;
}

代理模式
定义:
为其它对象提供一种代理,以控制对这个对象的访问

作用:中介

角色:抽象角色、代理角色、真实角色

优点:
1)代理模式能将代理对象与真实对象被调用的目标对象分离降低了系统的耦合度,扩展性好
2)保护目标对象
3)增强目标对象

缺点:
1)代理模式会造成系统设计中类的数目的增加
2)在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
3)增加了系统的复杂度

适用场景:智能指针

#include<iostream>
using namespace std;

class Person
{
public:
	virtual void renthouse() = 0;
};
class renter :public Person//租客
{
public:
	void renthouse()
	{
		cout << "想要租一栋房子!" << endl;
	}
};

class intermediary :public Person//代理
{
public:
	intermediary(Person *p):m_person(p){}
	void renthouse()
	{
		m_person->renthouse();
		cout << "我是中介,我帮你找房子!" << endl;
	}
private:
	Person* m_person;
};
int main()
{
	Person* p = new renter;//创建一个租客
	Person* intermediary1 = new intermediary(p);//找代理帮忙租房子
	intermediary1->renthouse();//中介去租房子
	return 0;
}

包装模式/装饰模式
定义:以透明动态的方式来动态扩展对象的功能,也是继承关系的一种代替方案

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

class car
{
public:
	virtual void showinfo() = 0;
};

class BMW:public car//宝马类
{
public:
	BMW(){}
	BMW(string n)
	{
		name = n;
	}
	void showinfo()
	{
		cout << name << endl;
	}
private:
	string name;
};

class BENZ:public car//奔驰类
{
public:
	BENZ() {}
	BENZ(string n)
	{
		name = n;
	}
	void showinfo()
	{
		cout << name << endl;
	}
private:
	string name;
};

class Function :public car//抽象的装饰类
{
public:
	void Decorate(car *c)
	{
		this->c = c;
	}
	void showinfo()
	{
		if (c != NULL)
			c->showinfo();
	}
protected:
	car* c;
};

class Navigator :public Function//导航功能
{
public:
	void showinfo()
	{
		cout << "导航";
		Function::showinfo();
	}
};

class SelfDrive :public Function//自动驾驶
{
public:
	void showinfo()
	{
		cout << "自动驾驶";
		Function::showinfo();
	}
};

class VoiceControl :public Function//语音控制功能
{
public:
	void showinfo()
	{
		cout << "语音控制";
		Function::showinfo();
	}
};
int main()
{
	car* bmw = new BMW("宝马X1");
	Navigator* na = new Navigator();
	SelfDrive* sd = new SelfDrive();
	na->Decorate(bmw);//装上导航
	sd->Decorate(na);//自动驾驶
	sd->showinfo();
	
	car* benz = new BENZ("奔驰迈凯伦");
	SelfDrive* sd1 = new SelfDrive();
	VoiceControl* vc = new VoiceControl();

	sd1->Decorate(benz);
	vc->Decorate(sd1);
	vc->showinfo();

	return 0;
}

总结:
适配器模式:将接口A使用B接口的功能
装饰模式:将接口A进行功能添加
代理模式:用代理对象进行处理

桥接模式
定义:将抽象部分与它的实现部分分离,使它们都可以独立的变化

作用:一维扩展用继承/组合,多维扩展用桥接

角色:抽象部分、优化的抽象部分、实现部分、实现部分的具体实现

优点:
抽象和实现的分离
优秀的扩展功能
实现细节对客户透明
缺点:
增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者对抽象进行设计和编程
要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性

装饰模式VS桥接模式
共性:
都是对其原有的类功能进行扩展,减少了子类的数量
区别:
装饰模式:将多出来的功能单独的放到一个独立的类decorate里面
桥接模式:将原有类的一种属性抽象出来,形成一个独立的等级结构

#include<iostream>
using namespace std;

class color//抽象颜色类
{
public:
	virtual void paint(const string& pentype, const string& name) = 0;
};
class red :public color//具体红色类
{
public:
	void paint(const string& pentype, const string& name)
	{
		cout << pentype << "红色的" << name << endl;
	}
};

class green :public color
{
	void paint(const string& pentype, const string& name)
	{
		cout << pentype << "绿色的" << name << endl;
	}
};

class pen
{
public:
	virtual void draw(const string& name) = 0;
	void setcolor(color* c)
	{
		this->c = c;
	}
protected:
	color* c;
};

class pencil :public pen//具体铅笔类
{
public:
	void draw(const string& name)
	{
		string pentype = "铅笔绘制";
		this->c->paint(pentype, name);
	}
};

class smallpen :public pen  //具体小号毛笔类
{
public:
	void draw(const string& name)
	{
		string pentype = "小号毛笔绘制";
		this->c->paint(pentype, name);
	}
};

int main()
{
	color* c = new red();
	pen* p = new pencil();

	p->setcolor(c);
	p->draw("太阳");
	delete c;
	delete p;

	c = new green();
	p = new smallpen();
	p->setcolor(c);
	p->draw("大树");
	delete c;
	delete p;

	return 0;
}

享元模式
(1、考虑系统性能的设计模式,享元模式可以有效的节省空间
2、享元工厂提供一个享元池,用户需要对象的时候从享元池中获取,如果不存在,放回一个新的对象
3、外部状态会随着环境改变而改变(棋子的位置),内部状态是不会改变的(棋子的颜色),因此放在对象的内部)
定义:
是对象池的一种实现。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能

作用:
缓存共享对象,降低内存消耗

优点:
可以极大的减少内存中对象的数量,使得相同对象或相似对象在内存 中只保留一份,降低内存占用,增强程序的性能;
外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享;

缺点:
使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化;

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

enum piececolor{black,white};

class piecepos//棋子的位置
{
public:
	piecepos(int a,int b):x(a),y(b){}
public:
	int x;
	int y;
};

class piece//棋子类
{
public:
	piece(piececolor color):m_color(color){}
	~piece(){}
	virtual void draw() = 0;
protected:
	piececolor m_color;//棋子的颜色
};

class blackpiece :public piece //黑子类
{
public:
	blackpiece(piececolor color):piece(color){}
	void draw() { cout << "绘制一颗黑色棋子" << endl; }
};

class whitepiece :public piece //白子类
{
public:
	whitepiece(piececolor color) :piece(color) {}
	void draw() { cout << "绘制一颗白色棋子" << endl; }
};

class pieceboard //棋盘类
{
public:
	pieceboard(string black, string white) :m_blackname(black), m_whitename(white)
	{
		m_black = NULL;
		m_white = NULL;
	}
	~pieceboard()
	{
		delete m_black;
		delete m_white;
	}

	void setpiece(piececolor color, piecepos pos)
	{
		if (color == black)
		{
			if (m_black == NULL)
			{
				m_black = new blackpiece(color);
			}
			cout << m_blackname << "在位置(" << pos.x << "," << pos.y << ")";
			m_black->draw();
		}
		else
		{
			if (m_white == NULL)
			{
				m_white = new whitepiece(color);
			}
			cout << m_whitename << "在位置(" << pos.x << "," << pos.y << ")";
			m_white->draw();
		}
	}
private:
	vector<piecepos>m_pos;//存放棋子的位置
	piece* m_black;  //黑棋
	piece* m_white; //白棋
	string m_blackname;
	string m_whitename;
};
int main()
{
	pieceboard p("A", "B");
	p.setpiece(black, piecepos(4, 4));
	p.setpiece(white, piecepos(4, 16));
	p.setpiece(black, piecepos(16,4));
	p.setpiece(white, piecepos(16,16));
	return 0;
}

组合模式
行为型模式
模板方法模式
(1、在一个类中形式化的去定义算法,子类实现细节的处理
2、有效的实现了代码的复用性
3、每个不同的实现都要定义一个新的类,类的个数增加,设计更加的抽象)

定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中

作用:使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

角色:抽象类、具体子类

#include<iostream>
using namespace std;

class Testpaper
{
public:
	void dotestpaper()
	{
		studentname();
		testtitleone();
		testtitletwo();
	}
	void testtitleone()
	{
		cout << "1+1=?" << endl;
		answerone();
	}
	void testtitletwo()
	{
		cout << "黄色加蓝色是" << endl;
		answertwo();
	}
	virtual void studentname() = 0;
	virtual void answerone() = 0;
	virtual void answertwo() = 0;
};

class no1student :public Testpaper
{
public:
	void studentname()
	{
		cout << "姓名:小红" << endl;
	}
	void answerone()
	{
		cout << "答:2" << endl << endl;
	}
	void answertwo()
	{
		cout << "答:绿色" << endl << endl;
	}
};

class no2student :public Testpaper
{
public:
	void studentname()
	{
		cout << "姓名:小明" << endl;
	}
	void answerone()
	{
		cout << "答:3" << endl << endl;
	}
	void answertwo()
	{
		cout << "答:黑色" << endl << endl;
	}
};
int main()
{
	no1student p1;
	p1.dotestpaper();

	no2student p2;
	p2.dotestpaper();

	return 0;
}

策略模式
(1、定义了一系列算法的方法,所有的算法都是为了完成同一个工作
2、每一个算法都有自己单独的类,方便接口的调试(封装线的体现)
3、参考简单工厂的缺点)
定义:定义了一系列算法,并将每一个算法封装起来,而且使它们还可以相互替换(父类经常变化用策略模式)

作用:让算法独立于使用它的客户而独立变化

角色:抽象策略角色、具体策略角色、环境角色

优点:
1)使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护
2)策略模式让你可以动态的改变对象的行为,动态修改策略

缺点:
1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2)类过多—策略模式造成很多的策略类,每个具体策略类都会产生一个新类

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

class sort //抽象排序类
{
public:
	virtual vector<int> Sort(vector<int>arr) = 0;
};

class bubblesort :public sort //冒泡排序类
{
public:
	vector<int>Sort(vector<int>arr)
	{
		int len = arr.size();
		for (int i = 0; i < len; i++)
		{
			for (int j = 0; j < len-i-1; j++)
			{
				if (arr[j] > arr[j+1])
				{
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
		cout << "冒泡排序" << endl;
		return arr;
	}
};

class selectsort :public sort //选择排序
{
public:
	vector<int>Sort(vector<int>arr)
	{
		int len = arr.size();
		for (int i = 0; i < len; i++)
		{
			int temp = arr[i];
			int min = i;
			for (int j = i + 1; j < len; j++)
			{
				if (arr[j] < temp)
				{
					temp = arr[j];
					min = j;
				}
			}
				int tmp = arr[i];
				arr[i] = arr[min];
				arr[min] = tmp;
		}
		cout << "选择排序" << endl;
		return arr;
	}
};

class insertsort :public sort //插入排序
{
public:
	vector<int>Sort(vector<int>arr)
	{
		int len = arr.size();
		for (int i = 0; i < len; i++)
		{
			int j;
			int temp = arr[i];
			for (int j = i; j > 0; j--)
			{
				if (arr[j - 1] > temp)
				{
					arr[j] = arr[j - 1];
				}
				else
				{
					break;
				}
			}
				arr[j] = temp;
		}
		cout << "插入排序" << endl;
		return arr;
	}
};

class handler//排序算法处理类
{
public:
	vector<int>Sort(vector<int>arr)
	{
		return s->Sort(arr);
	}
	void setsortobj(sort* s)
	{
		this->s = s;
	}
private:
	sort* s;
};
int main()
{
	vector<int>arr = { 1,4,2,6,5,67,46 };
	vector<int>result;

	handler h;
	h.setsortobj(new selectsort());
	result = h.Sort(arr);

	cout << "原来的数组:";
	for (auto i : arr)
	{
		cout << i << " ";
	}
	cout << endl;
	cout << "排序好的数组:";
	for (auto  i:result)
	{
		cout << i << " ";
	}
	cout << endl << endl;;

	h.setsortobj(new bubblesort());
	result = h.Sort(arr);

	cout << "原来的数组:";
	for (auto i : arr)
	{
		cout << i << " ";
	}
	cout << endl;
	cout << "排序好的数组:";
	for (auto i : result)
	{
		cout << i << " ";
	}
	cout << endl;
	return 0;
}

观察者模式
(1、创建两个基类,一个是观察者基本,一个是被观察者基类
2、观察者基类里:update函数:接收被观察者更新的消息
3、被观察者基类里:1、添加订阅者函数
2、删除订阅者函数 3、调用观察者update函数(精华所在))
定义:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,在它的状态发生变化时,会通知所有的观察者

角色:抽象主题角色、具体主题角色、抽象观察者角色、具体观察者角色

#include<iostream>
#include<set>
#include<string>
using namespace std;

class observe_base//观察者基类
{
public:
    virtual const string get_name()const = 0;//显示名字
    virtual void update(const string& worlds) = 0;//显示更新
    virtual bool operator==(const observe_base* outer)const = 0;
};

class Target_base //被观察者基类
{
public:
    virtual void add_one_follower(observe_base* outer) = 0;//添加订阅者
    virtual void rm_one_follower(observe_base* outer) = 0;//删除订阅者
    virtual void set_string(const string& words) = 0;//更新发布内容

};

class Target_teacher :public Target_base //被观察者:老师
{
public:
    void add_one_follower(observe_base* outer)
    {
        followers.insert(outer);
        cout << outer->get_name() << "成功订阅!" << endl;
    }
    void rm_one_follower(observe_base* outer)
    {
        for (auto it = followers.begin(); it != followers.end(); it++)
        {
            if (**it == outer)
            {
                followers.erase(it);
                cout << outer->get_name() << "删除成功!" << endl;
                break;
            }
        }
    }
    void set_string(const string& words)
    {
        this->words = words;
        cout << "老师发布新的内容:" << this->words << endl;
        for (auto it = followers.begin(); it != followers.end(); it++)
        {
            (*it)->update(this->words);//通知订阅者新的消息
        }
    }
private:
    set<observe_base*>followers;//观察者集合
    string words;//被观察者发布的内容

};

class observe_student :public observe_base //观察者:学生
{
public:
    observe_student(const string& name) :name(name) {}
    void update(const string& words)
    {
        this->news = words;
        cout << "我是" << name << ",老师告诉我:" << news << endl;
    }
    const string get_name()const
    {
        return this->name;
    }
    bool operator==(const observe_base* outer)const
    {
        return outer->get_name() == this->name;
    }
private:
    string name;
    string news;
};

int main()
{
    Target_base* teacher_liu = new Target_teacher();//刘老师

    observe_student* liming = new observe_student("李明");//学生李明
    observe_student* zhangsan = new observe_student("张三");//学生张三

    //老师添加两个学生观察者
    teacher_liu->add_one_follower(liming);
    teacher_liu->add_one_follower(zhangsan);

    teacher_liu->set_string("明天早上交作业!");

    return 0;
}

责任链模式
(1、责任链模式本身不会创建责任链,是由系统的其它部分进行创建的
2、责任链模式有效的降低了请求的发送端和接收端之间的耦合
3、责任链模式可以是一条线,也可以是一个环,可以使一棵树
4、责任链一定要能够处理所有请求,配置要得当)
定义:将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链,当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止

作用:客户只需要将请求发送到责任链上即可,无需关心请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者解耦了

角色:抽象处理者角色、具体处理者角色、客户类角色

优点:
解耦:球球发起者和请求响应者进行解耦,链的创建由使用者(客户端)创建
动态组合:可以运行时动态组合链,根据需求增加或者减少处理节点
易修改:处理节点独立变化,只处理自己关心的工作,修改方便
易扩展:如果有新的处理需求,创建新的处理节点,然后使用者重新建链,是符合开闭原则的

缺点:
执行未处理:没有明确接收者,或者配置不当,会出现请求没有处理
执行的路径长:一次任务的处理需要多个节点的传递,性能辉降低,调试不方便
执行的死循环:建链不当导致环形链表,死循环

适用场景:一个请求有多个处理对象

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

class request
{
public:
	int m_num;
};

class Manager //抽象领导类
{
public:
	Manager(string name):m_name(name){}
	void setsuccess(Manager* tmp) { manager = tmp; }
	virtual void getrequest(request* r) = 0;
protected:
	Manager* manager;
	string m_name;
};

class commonManager :public Manager //普通经理
{
public:
	commonManager(string name):Manager(name){}
	void getrequest(request* r)
	{
		if (r->m_num >= 0 && r->m_num < 1000)
		{
			cout << m_name << "同意了请求加薪" << r->m_num << endl;
		}
		else
		{
			manager->getrequest(r);
		}
	}
};

class Majordomo :public Manager //总监
{
public:
	Majordomo(string name):Manager(name){}
	void getrequest(request* r)
	{
		if (r->m_num >= 1000 && r->m_num < 5000)
		{
			cout << m_name << "同意了请求加薪" << r->m_num << endl;
		}
		else
		{
			manager->getrequest(r);
		}
	}
};

class generalManager :public Manager //总经理
{
public:
	generalManager(string name):Manager(name){}
	void getrequest(request* r)                         //具有最高权限,处理一切请求
	{
		cout <<m_name<< "同意了请求加薪" << r->m_num << endl;
	}
};
int main()
{
	Manager* common = new commonManager("张经理");
	Manager* major = new Majordomo("李总监");
	Manager* general = new generalManager("赵总");
	
	//形成责任链
	common->setsuccess(major);
	major->setsuccess(general);

	request* r = new request();
	r->m_num = 6000;
	common->getrequest(r);  //上一层的人先接收请求
	return 0;
}

中介者模式(调停者模式)
(1、将一对多的依赖转变成一对一的依赖
2、有效的降低了类和类之间的耦合度
3、中介类的逻辑会随着同事类的增多而变得更复杂)

定义:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使用其耦合松散,而且可以独立的改变它们之间的交互。

作用:为了降低模块内部之间类的相互引用,防止出现系统或模块内部过度耦合

角色:抽象中介者、具体中介者、抽象同事类、具体同事类

优点:
减少了类间的依赖,把原来的一对多的依赖变成了一对一的依赖,同事类依赖中介者减少了依赖,当然同时也降低了类间的耦合
缺点:
中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂

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

class houseperson;  //类的声明
class mediator //抽象中介类
{
public:
	virtual void sendmessage(string msg, houseperson* p) = 0;
};

class houseperson  //房东
{
public:
	houseperson(mediator* m)
	{
		m_me = m;
	}
protected:
	mediator* m_me;
};

class buyhouseperson :public houseperson //买房子的人
{
public:
	buyhouseperson(mediator *m):houseperson(m){}
	void sendmessage(string msg)
	{
		m_me->sendmessage(msg, this);
	}
	void notify(string msg)
	{
		cout << "买房者得到的消息:" << msg << endl;
	}
};

class sellhouseperson :public houseperson  //卖房子的人
{
public:
	sellhouseperson(mediator *m):houseperson(m){}
	void sendmessage(string msg)
	{
		m_me->sendmessage(msg, this);
	}
	void notify(string msg)
	{
		cout << "卖房者得到的消息:" << msg << endl;
	}
};

class concretmediator :public mediator
{
public:
	void sendmessage(string msg, houseperson* p)
	{
		if (p == b)//买房子的人给中介发消息
		{
			s->notify(msg);
		}
		else   //卖房子的人给中介发消息
		{
			b->notify(msg);
		}
	}
public:
	buyhouseperson* b;
	sellhouseperson* s;
};
int main()
{
	concretmediator* c = new concretmediator;
	buyhouseperson* b = new buyhouseperson(c);
	sellhouseperson* s = new sellhouseperson(c);

	c->b = b;
	c->s = s;

	b->sendmessage("300万卖不卖!");
	s->sendmessage("不卖,至少400万!");

	return 0;
}

备忘录模式
命令模式
状态模式
访问者模式
解释器模式
迭代器模式

总结:
创建型模式:思考对象的创建和创建的过程
结构型模式:思考类与类之间的关系,解耦、联通形成更复杂的结构
行为型模式:思考类的协调工作去解决问题

原则:
开放封闭原则:类的改动是通过增加代码进行的,而不是修改源代码
依赖倒置原则:依赖于抽象,不依赖于具体实现
接口隔离原则:类之间的依赖关系应该建立在最小的接口上
里氏替换原则:只要有父类的地方,子类一定可以替代,反过来不行。
合成复用原则:在一个新的对象里面使用已有的对象,使其成为新对象的一部分,尽量首先使用合成\聚合的方式,而不是使用继承。
迪米特原则:一个软件实体应当尽可能少的与其它实体发生相互作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&*Savior

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值