设计模式基本概念

设计模式

设计模式共有23种,它们分为三大类:

  1. 创建型模式:如何创建对象。
  2. 结构型模式:如何实现类和对象的组合,关注类和对象的组合方式。
  3. 行为型模式:类或对象怎么交互以及怎么分配职责,关注对象之间如何通信。

注意:简单工厂模式不在23种之列,加上简单工厂模式共24种。

设计模式基础是多态。

设计模式的7大原则:

(目的都是为了 高内聚,低耦合)

  1. 单一原则(SRP):类的职责单一,对外只提供一种功能,引起变化的原因都应该只有一个。
  2. 开放-封闭原则(OCP):源代码的修改关闭,新功能的增加打开。也就是新加功能时只能通过新加代码来实现,不能修改源代码。
  3. 依赖倒转原则(DIP):依赖于抽象(接口),而不依赖与具体的实现类。也就是针对接口编程。
  4. 里氏代换原则(LSP):任何抽象类出现的地方,都可以用它的实现类进行替换。也就是多态。
  5. 接口隔离原则(ISP):一个接口只提供一种功能,不应该把所有的功能都封装到一个接口中取。也就是说不能强迫用户使用与需求功能无关的接口。
  6. 迪米特法则(LOD):一个对象应该尽可能的少了解其他对象,从而降低各个对象之间的耦合,提高系统的可维护性,各个模块之间相互调用时,通常会提供一个统一的接口来实现。这样一来其他模块不需要了解另外一个模块的内部实现细节,当一个模块改变时也不会影响其他模块。(黑盒原理)
  7. 合成复用原则(CARP):如果使用继承,会导致父类的任何变化都影响子类。如果使用对象组合,就降低了这种依赖关系。对于继承和组合优先使用组合。

重点原则代码示例
1、开闭原则(OCP):

// 开闭原则:对扩展开放,对修改关闭

class AbstractCaculator
{
public:
	virtual int getResult() = 0;
	virtual void setNumber() = 0;
};
// 加法类
class PlusCaculator : public AbstractCaculator
{
public:
	void setNumber(int a, int b) {
		this->m_a = a;
		this->m_b = b;
	}
	virtual int getResult(){
		return m_a + m_b;
	}
public:
	int m_a;
	int m_b;
};
 到这为止,第一个版本的计算器的代码写完了,如果现在要加个减法功能
 第一种方法:在PlusCaculator类中新加一个成员函数进行减法操作
		这很明显违背了开闭原则,修改了源码。
 正确解决办法时新增加一个类继承AbstractCaculator类,再实现减法操作
 减法类
class SubCaculator : public AbstractCaculator
{
public:
	void setNumber(int a, int b) {
		this->m_a = a;
		this->m_b = b;
	}
	virtual int getResult() {
		return m_a - m_b;
	}
public:
	int m_a;
	int m_b;
};

这不是将简单问题复杂化了吗?没错,确实如此,但是我们这个程序简单,假设一个及其复杂的程序,源码的实现非常复杂,后期维护起来,开闭原则就能体现出它的巨大优势

2、依赖倒转原则(DIP)
在这里插入图片描述
传统过程设计倾向于使高层次的模块依赖于低层次的模块,抽象层次依赖于具体层次。
这样设计,高层、中层、底层的耦合度极高。很容易导致牵一发而动全身。

依赖倒转: 指的就是让中层模块依赖底层模块反转成底层依赖抽象,这样一来,高层模块依赖于抽象,底层也依赖于抽象,极大的降低了各层之间的耦合性。
在这里插入图片描述
代码示例:

// 银行工作人员
class BankWorker
{ // 这个类干的事情太多,违背了单一职责原则
public:
	void saveService(){
		cout << "办理存款业务" << endl;
	}

	void payService() {
		cout << "办理支付业务" << endl;
	}

	void tranferService() {
		cout << "办理转账业务" << endl;
	}
};

// 业务依赖于具体工人,每个不同的业务都需要一个特定的函数
中层模块
void doSaveBussiness(BankWorker* worker) {
	worker->saveService();
}
void doPayBussiness(BankWorker* worker) {
	worker->payService();
}
void doTranferBussiness(BankWorker* worker) {
	worker->tranferService();
}

void test01() {
	BankWorker* worker = new BankWorker();
	doSaveBussiness(worker); // 存款业务
	doPayBussiness(worker); // 支付业务
	doTranferBussiness(worker); // 转账业务
}

一般开发如同上述代码,一层依赖于一层。test01依赖于中层,中层依赖于具体实现

符合依赖倒转原则后的代码如下:

// 依赖倒转

class AbstractWorker
{
public:
	virtual void doBusiness() = 0;
};
具体实现:
// 负责存款业务
class SaveBankWorker : public AbstractWorker
{
public:
	virtual void doBusiness() {
		cout << "办理存款业务" << endl;
	}
};
// 负责支付业务
class PayBankWorker : public AbstractWorker
{
public:
	virtual void doBusiness() {
		cout << "办理支付业务" << endl;
	}
};
// 负责转账业务
class TransferBankWorker : public AbstractWorker
{
public:
	virtual void doBusiness() {
		cout << "办理转账业务" << endl;
	}
};

 中层模块
void doNewBusiness(AbstractWorker* worker) {
	worker->doBusiness();
}

void test02()
{
	AbstractWorker* worker = new TransferBankWorker();
	doNewBusiness(worker);
}

如此设计,具体实现类依赖于抽象,中层函数也只需要通过抽象,即使修改具体实现,doNewBusiness函数也不用修改。

3、迪米特法则(LOD)
迪米特法则又叫最小知识原则。

// 迪米特法则
class AbstractBuilding
{
public:
	virtual void sale() = 0;
	virtual string getQulity() = 0;
};
// 楼盘A
class BuildingA : public AbstractBuilding
{
public:
	BuildingA(){
		m_qulity = "高品质";
	}
	virtual void sale() {
		cout << "楼盘A" << m_qulity << "已售出" << endl;
	}
	virtual string getQulity() {
		return m_qulity;
	}
public:
	string m_qulity;
};
// 楼盘B
class BuildingB : public AbstractBuilding
{
public:
	BuildingB() {
		m_qulity = "低品质";
	}
	virtual void sale() {
		cout << "楼盘B" << m_qulity << "已售出" << endl;
	}
	virtual string getQulity() {
		return m_qulity;
	}
public:
	string m_qulity;
};
// 中介类
class Mediator 
{
public:
	Mediator() {
		AbstractBuilding* buildingA = new BuildingA();
		vBuilding.push_back(buildingA);
		AbstractBuilding* buildingB = new BuildingB();
		vBuilding.push_back(buildingB);
	}
	//对外提供接口
	AbstractBuilding* findMyBuilding(string quality) {
		for (auto it = vBuilding.begin(); it != vBuilding.end(); ++it) {
			if ((*it)->getQulity() == quality) {
				return* it;
			}
		}
		return NULL;
	}

	~Mediator() {
		for (auto it = vBuilding.begin(); it != vBuilding.end(); ++it) {
			if (*it != NULL) {
				delete* it;
			}
		}
	}
public:
	vector<AbstractBuilding*> vBuilding;
};

// 客户端1
void test01()
{
	BuildingA* ba = new BuildingA();
	if (ba->m_qulity == "低品质") {
		ba->sale();
	}
	BuildingB* bb = new BuildingB();
	if (bb->m_qulity == "低品质") {
		bb->sale();
	}
}

 可以看到客户端1的实现访问了具体的类,如果我再加一个C类楼盘那客户端就需要修改代码
 如果提供一个中介类如下客户端2,不管你再加楼盘我客户端的代码都不需要修改
 这就是迪米特法则
 
 // 客户端2
void test02()
{
	Mediator* md = new Mediator();
	AbstractBuilding* building = md->findMyBuilding("高品质");
	if (building != NULL) {
		building->sale();
	}
	else {
		cout << "没有你需要的楼盘" << endl;
	}
}

4、合成复用原则(CARP)

// 合成复用原则:能使用组合绝不使用继承
class AbstractCar
{
public:
	virtual void run() = 0;
};

class Dazhong : public AbstractCar
{
public:
	virtual void run() {
		cout << "大众启动" << endl;
	}
};

class Tuolaji : public AbstractCar
{
public:
	virtual void run() {
		cout << "拖拉机启动" << endl;
	}
};
// 一个人针对具体的车
class PersonA : public Tuolaji
{
public:
	virtual void Doufeng() {
		run();
	}
};
// 如果这个人想开大众了,还得再新写一个人的类
class PersonB : public Dazhong
{
public:
	virtual void Doufeng() {
		run();
	}
};
// 上述方式就是将人类与汽车类强耦合在了一起
// 可以使用组合
class Person 
{
public:
	void setCar(AbstractCar* car) {
		this->car = car; 
	}
	void Doufeng() {
		this->car->run();
		这样一来,调用者想开什么车就传什么车就可以了,Person类一直都不用变
		如此写法,人类与汽车类就没有那么强的耦合关系,即使再加几个车也是可以的
		if (this->car != NULL) {
			delete this->car;
		}
	}
public:
	AbstractCar* car;
};
// 用户
void test01()
{
	Person* p = new Person();
	p->setCar(new Dazhong);
	p->Doufeng();

	p->setCar(new Tuolaji); // 想开什么开什么
	p->Doufeng();

	delete p;
}

设计模式总览表

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值