C++几种常用设计模式

1、设计模式

面向过程通过划分功能模块,通过函数相互间的调用来实现,但需求变化时,就需要更改函数。而你改动的函数有多少的地方在调用他关联多少数据,这是很不容易弄得清楚的地方。
通过选择合适得设计模式可以提高代码的可复用性,可维护性,可扩展性以及灵活性,这些都是系统设计中非常重要的非功能性需求。
几大设计原则:

单一职责:对于一个类来说,应该仅有一个引起他变化的原因,功能要单一,降低耦合性。
开放-封闭原则:对于扩展开放,对于更改时封闭的
依赖倒转原则:高层模块不应该依赖低层模块,应该都依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。
里氏替换原则:子类必须能够替换掉他们的父类;子类继承父类,所以字类拥有父类所有非私有方法。
迪米特法则:强调了类之间的松耦合。如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

2、简单工厂模式

客户端和具体实现类进行解耦,不需要考虑某些对象创建过程比较复杂的情况

#include <iostream>
#include <string>
using namespace std;
// 运算父类
class Program {
private:
	string numA;
	string numB;
public:
	Program() {}
	virtual string getRes() {
		return "0";
	}
	void setA(string A) {
		this->numA = A;
	}
	void setB(string B) {
		this->numB = B;
	}
	string getA() {
		return this->numA;
	}
	string getB() {
		return this->numB;
	}
};
//加法类
class ProgramAdd :public Program {
public:
	ProgramAdd() {}
	string getRes() {
		return to_string(stoi(getA()) + stoi(getB()));
	}
};
//减法类
class ProgramSub :public Program {
public:
	ProgramSub() {}
	string getRes() {
		return to_string(stoi(getA()) - stoi(getB()));
	}
};
//乘法类
class ProgramMul :public Program {
public:
	ProgramMul() {}
	string getRes() {
		return to_string(stoi(getA()) * stoi(getB()));
	}
};
//除法类
class ProgramDiv :public Program {
public:
	ProgramDiv() {}
	string getRes() {
		return to_string(stoi(getA()) / stoi(getB()));
	}
};
//简单工厂类
class PragramFactory { // 增加功能时,修改工厂类,不符合开放-封闭原则
public:
	Program* createOperator(char signal) {
		Program *opre = nullptr;
		switch (signal) {
			case '+':
				opre = new ProgramAdd();
				break;
			case '-':
				opre = new ProgramSub();
			case '*':
				opre = new ProgramMul();
				break;
			case '/':
				opre = new ProgramDiv();
				break;
		}
		return opre;
	}
};
//客户端
int main()
{
	char signal = '+';
	Program *pro = new Program;
	pro = PragramFactory().createOperator(signal);
	pro->setA("1");
	pro->setB("2");
	string res = pro->getRes();
	cout << res << endl;
	return 0;
}

简单工厂模式增加新功能需要修改源代码,不符合开闭原则

3、工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到其子类。

#include <iostream>
using namespace std;
//抽象对象接口
class Waiter {
public:
	void sweep() {
		cout << "扫地" << endl;
	}
	void wash() {
		cout << "洗碗" << endl;
	}
	void send() {
		cout << "送菜" << endl;
	}
};
//具体对象接口
class WaiterA :public Waiter {};
class WaiterB:public Waiter{};
//抽象工厂类
class WaiterFactory {
public:
	virtual Waiter* createWaiter() = 0;
};
//具体工厂类
class WaiterAFactory :public WaiterFactory {
public:
	Waiter* createWaiter() {
		return new WaiterA;
	}
};
//具体工厂类
class WaiterBFactory :public WaiterFactory {
public:
	Waiter* createWaiter() {
		return new WaiterB;
	}
};
int main() {
	//想要实现什么具体对象,就new一个什么工厂
	WaiterFactory* factory = new WaiterAFactory;
	//w1为WaiterA类对象
	Waiter* w1 = factory->createWaiter();
	w1->send();
	w1->sweep();
	w1->wash();
	return 0;
}

工厂方法模式保持简单工厂的优点,克服了其缺点,但是由于没加一个具体对象类就要加一个相应的工厂类。

4、抽象工厂模式

提供一个创建一系列或相关依赖对象的接口,而无需指定他们具体的类。很容易交换不同的产品,他让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离。

#include <iostream>

using namespace std;
class User {
private:
	int id;
	string name;
public:
};
class Department {
private:
	int did;
	string dname;
public:

};
//用户表抽象类
class Iuser {
public:
	virtual void insert(User* user) = 0;
	virtual User* getUser(int id) = 0;
};
//sql用户具体类
class SqlserverUser :public Iuser {
public:
	void insert(User* user) {
		cout << "在SQL Server 中给User表增加一条记录\n";
	}
	User* getUser(int id) {
		cout << "在SQL Server 中查到User一条记录\n";
		return nullptr;
	}
};
//access用户具体类
class AccessUser :public Iuser {
	void insert(User* user) {
		cout << "在Acess Server 中给User表增加一条记录\n";
	}
	User* getUser(int id) {
		cout << "在Acess Server 中查到User一条记录\n";
		return nullptr;
	}
};
//部门抽象类
class IdDepartment {
public:
	virtual void insert(Department* dept) = 0;
	virtual User* getUser(int id) = 0;
};
//sql部门具体类
class SqlserverDepartment :public IdDepartment {
public:
	void insert(Department* dept) {
		cout << "在SQL Server 中给Department表增加一条记录\n";
	}
	User* getUser(int id) {
		cout << "在SQL Server 中查到Department一条记录\n";
		return nullptr;
	}
};
//access部门具体类
class AccessDepartment :public IdDepartment {
	void insert(Department* deptr) {
		cout << "在Acess Server 中给Department表增加一条记录\n";
	}
	User* getUser(int id) {
		cout << "在Acess Server 中查到Department一条记录\n";
		return nullptr;
	}
};
//抽象工厂类
class IFactory {
public:
	virtual Iuser* CreateUser() = 0;
	virtual IdDepartment* CreateDepartment() = 0;
};
//sql具体工厂类
class SqlserverFactory :public IFactory {
public:
	Iuser* CreateUser() {
		return new SqlserverUser;
	}
	IdDepartment* CreateDepartment() {
		return new SqlserverDepartment;
	}
};
//access具体工厂类
class AcessserverFactory :public IFactory {
public:
	Iuser* CreateUser() {
		return new AccessUser;
	}
	IdDepartment* CreateDepartment() {
		return new AccessDepartment;
	}
};
int main() {
	User* user = new User;
	Department* dept = new Department;
	//使用sql,就实例化sql工厂对象
	IFactory* factory = new SqlserverFactory;
	Iuser* iu = factory->CreateUser();
	iu->insert(user);
	iu->getUser(1);

	IdDepartment* de = factory->CreateDepartment();
	de->insert(dept);
	de->getUser(2);

	return 0;
}

如果增加新的产品,则要修改三处地方,并且增加三个类

5、策略模式

策略模式:定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换,具体实现与客户端完全分离,客户端只需要操作一个类就可以实现不同功能
优点:1、减少了算法与使用算法之间的耦合度。 2、测试方便,每个算法都有自己的类,只要测试自己接口就行了,不影响其他算法类。
使用场景: 在分析过程中需要在不同时间应用不同的业务规则,可以考虑用策略模式

#include <iostream>
#include <string>

using namespace std;
//策略抽象类,定义所有支持的算法的公共接口
class CashSuper {
public:
	virtual double acceptCash(double money) {
		return money;
	}
};
//具体策略类
class NormalFee :CashSuper {
public:
	double acceptCash(double money) {
		return money;
	}
};
class DiscountFee :CashSuper {
public:
	float discountNum;
public:
	DiscountFee(float discountNum) {
		this->discountNum = discountNum;
		cout << endl;
	}
	double acceptCash(double money) {
		return money * this->discountNum;
	}
};

class ReturnFee :CashSuper {
public:
	int fill;
	int send;
public:
	ReturnFee(int fill, int send) :fill(fill), send(send) {}
	double acceptCash(double money) {
		if (money > this->fill) {
			return money - send;
		}
		return money;
	}
};
//用一个具体策略来配置维护一个对策略对象的引用
class CashContext {
private:
	CashSuper* cs = nullptr;
public:
	CashContext(int type) {
		switch (type) {
		case 0:
			cs = (CashSuper*) new NormalFee;
			break;
		case 1:
			cs = (CashSuper*)new DiscountFee(0.8);
			break;
		case 2:
			cs = (CashSuper*) new DiscountFee(0.7);
			break;
		case 3:
			cs = (CashSuper*) new DiscountFee(0.5);
			break;
		case 4:
			cs = (CashSuper*) new ReturnFee(300, 100);
			break;
		}
	}
	//根据不同策略对象来实现不同结果
	double getResult(double money) {
		return cs->acceptCash(money);
	}
};
int main()
{
	const char* discount[5] = { "正常价格","打八折","打七折","打五折" };
	//实例化打八折类
	CashContext cc(1);
	//获取打折后金额
	double res = cc.getResult(100);
	cout << res << endl;
	return 0;
}

策略模式每增加一种功能需要修改工厂类

6、单例模式

单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。整个系统只有一个全局对象

#include <iostream>

using namespace std;

//懒汉式单例模式
class SingletonLazy {
private:
	static SingletonLazy* instance;
	// 构造函数私有化, 不让外界利用new创建实例
	SingletonLazy() {
		cout << "懒汉式单例模式\n";
	}
public:
	static SingletonLazy* getInstance() {
	//第一次引用时才被实例化
		if (instance == nullptr) {
			instance = new SingletonLazy;
		}
		return instance;
	}
};

SingletonLazy* SingletonLazy::instance = nullptr;

//饿汉式单例模式
class SingletonHungry {
private:
	static SingletonHungry* instance2;
	SingletonHungry() {
		cout << "饿汉式单例模式\n";
	}
public:
	static SingletonHungry* getInstance() {
		return instance2;
	}
};
//加载时实例化
SingletonHungry* SingletonHungry::instance2 = new SingletonHungry;


int main() {

	cout << "action: \n";

	return 0;
}

饿汉式单例模式不存在多线程访问的安全问题,但是类一加载就实例化对象,所以要提前占用系统资源。

7、装饰器模式

动态地给一个类添加一些额外的功能。就增加功能来说,装饰器模式相比生成子类更加灵活

#include <iostream>
#include <string>

using namespace std;
//抽象接口,可以给这些对象动态添加功能
class AbstractPerson {
public:
	string username;
	string heroname;
	int mHp;
	int mMp;
	int mAt;
	int mDf;
public:
	virtual void show() = 0;
};
//具体对象
class Person :public AbstractPerson {
public:
	Person(string username,string heroname) {
		this->username = username;
		this->heroname = heroname;
		mHp = 0;
		mMp = 0;
		mAt = 0;
		mDf = 0;
	}
	virtual void show() {
		cout << "用户名:" << username << endl;
		cout << "英雄名:" << heroname << endl;
		cout << "血量:" << mHp << endl;
		cout << "魔法:" << mMp << endl;
		cout << "攻击:" << mAt << endl;
		cout << "防御:" << mDf << endl;
	}
};
//装饰类,通过继承方式来实现添加额外功能
class Bazhechongzhuang : public AbstractPerson {
public:
	AbstractPerson* per;
public:
	Bazhechongzhuang(AbstractPerson* per) :per(per){}
	void Add() {
		cout << "买了霸者重装后:" << endl;
		this->mHp = this->per->mHp;
		this->mMp = this->per->mMp;
		this->mAt = this->per->mAt;
		this->mDf = this->per->mDf + 800;
	}
	virtual void show() {
		Add();
		cout << "用户名:" << username << endl;
		cout << "英雄名:" << heroname << endl;
		cout << "血量:" << this->mHp << endl;
		cout << "魔法:" << this->mMp << endl;
		cout << "攻击:" << this->mAt << endl;
		cout << "防御:" << this->mDf << endl;
	}

};
//装饰类
class Fanjia : public AbstractPerson {
public:
	AbstractPerson* per;
public:
	Fanjia(AbstractPerson* per) :per(per) {}
	void Add() {
		cout << "买了反甲后:" << endl;
		this->mHp = this->per->mHp;
		this->mMp = this->per->mMp;
		this->mAt = this->per->mAt + 300;
		this->mDf = this->per->mDf + 500;
	}
	virtual void show() {
		Add();
		cout << "血量:" << this->mHp << endl;
		cout << "魔法:" << this->mMp << endl;
		cout << "攻击:" << this->mAt << endl;
		cout << "防御:" << this->mDf << endl;
	}

};
int main() {
	
	AbstractPerson* per = new Person("Timel","典韦");
	per->show();
	cout << "-------------没买装备------------\n";
	Bazhechongzhuang bzcz(per);
	Fanjia fj(per);
	fj.show();
	return 0;
}

8、命令模式

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化

#include <iostream>

using namespace std;
//具体的执行请求
class Request {
public:
	void Get() {
		cout << "Get!\n";
	}
	void Post() {
		cout << "Post!\n";
	}
};
//用来声明执行操作的抽象接口
class Command {
protected:
	Request request;
public:
	Command() {}
	Command(Request& res) :request(res) {}
	virtual void excuteCommand() {};//执行
};
//具体执行动作
class GetCommand :public Command {
public:
	GetCommand(Request res) :Command(res) {}
	void excuteCommand() {
		request.Get();
	}
};

class PostCommand :public Command {
public:
	PostCommand(Request res) :Command(res) {}
	void excuteCommand() {
		request.Post();
	}
};
//具体实施哪个执行动作
class Excutor {
private:
	Command* comm;
public:
	void setOrder(Command* comm) {
		this->comm = comm;
	}
	void modify() {
		comm->excuteCommand();
	}
};

int main() {
	Request boy;
	Command *get = new GetCommand(boy);
	Command *post = new PostCommand(boy);
	Excutor girl;
	girl.setOrder(get);
	girl.modify();
	girl.setOrder(post);
	girl.modify();
	return 0;
}

9、外观模式

为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一系统更加容易使用。

#include <iostream>

using namespace std;

class Stock1 {//实现子系统的功能
public:
	void buy() {
		cout << "买入股票1\n";
	}
	void sell() {
		cout << "卖出股票1\n";
	}
};
class Stock2 {
public:
	void buy() {
		cout << "买入股票2\n";
	}
	void sell() {
		cout << "卖出股票2\n";
	}
};
class Stock3 {
public:
	void buy() {
		cout << "买入股票3\n";
	}
	void sell() {
		cout << "卖出股票3\n";
	}
};
//知道哪些子系统类负责处理请求,将客户的请求代理适当的子系统对象
class Fund {
private:
	Stock1* sk1;
	Stock2* sk2;
	Stock3* sk3;
public:
	Fund() {
		sk1 = new Stock1;
		sk2 = new Stock2;
		sk3 = new Stock3;
	}
	void buyFund() {
		sk1->buy();
		sk2->buy();
		sk3->buy();
	}
	void sellFund() {
		sk1->sell();
		sk2->sell();
		sk3->sell();
	}
};

int main() {
	Fund f;
	f.buyFund();
	f.sellFund();
	return 0;
}

10、代理模式

为其他对象提供一种代理以控制对这个对象的访问。

#include <iostream>

using namespace std;

class SchoolGirl {
public:
	string name;
public:
	SchoolGirl() {}
	SchoolGirl(const char* name) :name(name) {}
};
//真实对象和代理的共用接口
class AbstractPeople {
public:
	virtual void giveDolls() = 0;
	virtual void giveFlowers() = 0;
	virtual void giveChocolate() = 0;
};
//真实对象
class Pursuit:AbstractPeople {
private:
	SchoolGirl *mm;
public:
	Pursuit() {}
	Pursuit(SchoolGirl* sg) :mm(sg) {}
	void giveDolls() {
		cout << mm->name << "送你布娃娃" << endl;
	}
	void giveFlowers() {
		cout << mm->name << "送你鲜花" << endl;
	}
	void giveChocolate() {
		cout << mm->name << "送你巧克力" << endl;
	}
};
//代理人
class Proxy :AbstractPeople {
private:
	Pursuit* ps;
public:
	Proxy(SchoolGirl* sg) {
		ps = new Pursuit(sg);
	}
	void giveDolls() {
		ps->giveDolls();
	}
	void giveFlowers() {
		ps->giveFlowers();
	}
	void giveChocolate() {
		ps->giveChocolate();
	}
};
int main() {
	SchoolGirl* sg = new SchoolGirl("娇娇");
	Proxy ps(sg);
	ps.giveDolls();
	ps.giveFlowers();
	ps.giveChocolate();

	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值