设计模式之创建型模式

一、设计模式的三原则:

  1. 面向接口编程,而非实现;

  2. 多用组合,少用继承;

  3. 高内聚、低耦合;

二、设计模式的六大原则

总原则:开闭原则(Open Close Principle)开闭原则就是说对扩展开放,对修改关闭
使用设计模式的目的:可重用性、易理解性、保证代码可靠性。

1、单一职责原则

不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责

2、里氏替换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。里氏代换原则是对“开-闭”原则的补充。

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

5、迪米特法则(最少知道原则)(Demeter Principle)

就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

6、合成复用原则(Composite Reuse Principle)

原则是尽量首先使用合成/聚合的方式,而不是使用继承。

C++语言将数据成员中包含对象成员的类称为组合类,而将数据成员中包含对象指针的类称为聚合类。聚合类是一种特殊形式的组合类。

聚合类和组合类的区别:

1)组合类的对象成员是独立创建的,聚合类对象只包含指向对象成员的指针。

2)聚合类对象可以共用对象成员。

一、设计模式的分类

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

其实还有两类:并发型模式和线程池模式。

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

1、工厂方法模式
创建一个基类和几个继承基类的子类,创建一个工厂类,工厂类中定义一个成员函数,通过成员函数的参数值不同,让基类指针通过不同的参数值构建不同的子类。

// 简单工厂
class SimpleFactory
{
public:
	
// 获取产品
Prodect* getProdect(PRODECT_TYPE type) {
	
    switch (type)
    {
    case APPLE:
    prodect = new AppleProdect(5);
    break;
    case BANANA:
    prodect = new BananaProdect(2);
    break;
    case PEAR:
    prodect = new PearProdect(3);
    break;
    default:
    cout << "无该产品。" << endl;
    break;
    }

	return prodect;

}
private:
	Prodect* prodect = nullptr;
};

2、抽象工厂模式
核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

//抽象产品
class Product 
{public:virtual void show() = 0;};
//抽象产品族1 生产键盘
class KeyBoard :public Product {};
//具体产品
class LogiKeyBoard :public KeyBoard 
{void show() {}};
class RazerKeyBoard :public KeyBoard 
{void show(){}};
//抽象产品族2 除了生产键盘之外可以生产鼠标
class Mouse :public Product {};
class LogiMouse :public Mouse 
{void show(){}};
class RazerMouse :public Mouse
{void show() {}}
//抽象工厂
class Factory 
{
public:
    //创建一个键盘
	virtual  KeyBoard* CreateKeyBoard() = 0;
    //创建一个鼠标
	virtual Mouse* CreateMouse() = 0;
}; 
//具体工厂 罗技工厂提供罗技键盘、罗技鼠标
class LogiFactory :public Factory 
{
	KeyBoard* CreateKeyBoard() 
	{
		return new LogiKeyBoard;
	}
	Mouse* CreateMouse() 
	{
		return new LogiMouse;
	}
};
//雷蛇工厂提供雷蛇键盘、雷蛇鼠标
class RazerFactory :public Factory 
{
	KeyBoard* CreateKeyBoard() 
	{
		return  new RazerKeyBoard;
	}
	Mouse* CreateMouse() 
	{
		return new RazerMouse;
	}
};
int main() 
{
    //首先需要一个工厂
	Factory* factory = new LogiFactory;
	KeyBoard* keyBoard = factory->CreateKeyBoard();
	Mouse* mouse = factory->CreateMouse();
	keyBoard->show();
	mouse->show();
    //释放后做第二次测试
	delete factory;
	delete keyBoard;
	delete mouse;
    //雷蛇工厂只生产雷蛇产品
	factory = new RazerFactory;
	keyBoard = factory->CreateKeyBoard();
	mouse = factory->CreateMouse();
	keyBoard->show();
	mouse->show();
	delete factory;
	delete keyBoard;
	delete mouse;
	factory = nullptr;
	keyBoard = nullptr;
	mouse = nullptr;
	return 0;
}

3、单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。
定义一个单例类:

  1. 私有化它的构造函数,以防止外界创建单例类的对象;
  2. 使用类的私有静态指针变量指向类的唯一实例;
  3. 使用一个公有的静态方法获取该实例

懒汉版(Lazy Singleton)
单例实例在第一次被使用时才进行初始化,这叫做延迟初始化。

  1. 使用智能指针
  2. 使用静态的嵌套类对象

对于第二种解决方法,代码如下:

// version 1.0
class Singleton
{
private:
	static Singleton* instance;
private:
	Singleton() {};
	~Singleton() {};
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
public:
	static Singleton* getInstance() 
        {
		if(instance == NULL) 
			instance = new Singleton();
		return instance;
	}
};
 
// init static member
Singleton* Singleton::instance = NULL;

**问题1:**Lazy Singleton存在内存泄露的问题,有两种解决方法:

// version 1.1
class Singleton
{
private:
	static Singleton* instance;
private:
	Singleton() { };
	~Singleton() { };
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
private:
	class Deletor {
	public:
		~Deletor() {
			if(Singleton::instance != NULL)
				delete Singleton::instance;
		}
	};
	static Deletor deletor;
public:
	static Singleton* getInstance() {
		if(instance == NULL) {
			instance = new Singleton();
		}
		return instance;
	}
};
 
// init static member
Singleton* Singleton::instance = NULL;

多个线程同时懒汉版单列模式使用为了保证线程安全
方法一:

 	mutex mtx;   //创建互斥锁对象
static Singleton* getInstance() {
	if(instance == NULL) {
		 mtx.lock();
		if(instance == NULL) {
			instance = new Singleton();
		}
		mtx.unlock(mutx);
	}
		return instance;
	}

方法二:

// version 1.2
class Singleton
{
private:
	Singleton() { };
	~Singleton() { };
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
public:
	static Singleton& getInstance() 
        {
		static Singleton instance;
		return instance;
	}
};

饿汉模式

// version 1.3
class Singleton
{
private:
	static Singleton instance;
private:
	Singleton();
	~Singleton();
	Singleton(const Singleton&);
	Singleton& operator=(const Singleton&);
public:
	static Singleton& getInstance() {
		return instance;
	}
}
 
// initialize defaultly
Singleton Singleton::instance;

4、建造者模式

将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
内容可以是不同的,但是组合成的过程是相同的。
在这里插入图片描述

#include <string>
using namespace std;
typedef string Graphics;
typedef string Pen;
 
class PersonBuilder{
 
public:
	virtual void buildHead(){}
	virtual void buildBody(){}
	virtual void buildArmLeft(){}
	virtual void buildArmRight(){}
	virtual void buildLegLeft(){}
	virtual void buildLegRight(){}
 
	PersonBuilder(Graphics g, Pen p);
	virtual ~PersonBuilder();
 
private:
	Graphics *g;
	Pen *p;
};
 
class PersonThinBuilder : public PersonBuilder{
 
public:
	PersonThinBuilder(Graphics g, Pen p);
	void buildHead();
	void buildBody();
	void buildArmLeft();
	void buildArmRight();
	void buildLegLeft();
	void buildLegRight();
};
 
class PersonFatBuilder : public PersonBuilder{
 
public:
	PersonFatBuilder(Graphics g, Pen p);
	void buildHead();
	void buildBody();
	void buildArmLeft();
	void buildArmRight();
	void buildLegLeft();
	void buildLegRight();
};
 
class PersonDirector{
 
public:
	PersonDirector(PersonBuilder *pb);
	void createPersion();
 
private:
	PersonBuilder *pb;
};

PersonDirector::PersonDirector(PersonBuilder *pb)
{
	this->pb = pb;
}
void PersonDirector::createPersion()
{
	pb->buildBody();
	pb->buildHead();
	pb->buildArmLeft();
	pb->buildArmRight();
	pb->buildLegLeft();
	pb->buildLegRight();
}
int main(int *argc, int *argv){
 
	PersonThinBuilder *pT = new PersonThinBuilder("画", "笔");
	PersonDirector *pD = new PersonDirector(pT);
 
	pD->createPersion();
 
	delete pT;
	delete pD;
 
	cout << "------------ 分 割 线 ------------" << endl;
 
	PersonFatBuilder *pF = new PersonFatBuilder("写", "黑笔");
	PersonDirector *pD2 = new PersonDirector(pF);
	pD2->createPersion();
 
	delete pF;
	delete pD2;
	getchar();
	return 0;
}

5、原型模式

通过复制(克隆、拷贝)一个指定类型的对象来创建更多同类型的对象。这个指定的对象可被称为“原型”对象,也就是通过复制原型对象来得到更多同类型的对象。

原型模式的实质就是实现对于原型的拷贝。主要是通过拷贝构造函数来实现

#include <iostream>
using namespace std;

	class Monster{
	public:
		Monster(int m_hp) : hp(m_hp) {
			cout << "战斗!" << endl;
		}
		virtual ~Monster() {}
		virtual Monster* clone() = 0;

	protected:
		int hp;
	};

	class ShiLaimu : public Monster {
	public:
		ShiLaimu(int m_hp) : Monster(m_hp) {
			
		}
		ShiLaimu(const ShiLaimu& slm) : Monster(slm)//拷贝构造
		 {
			this->hp = slm->hp;
		}
		virtual Monster* clone() {
			return new ShiLaimu(*this);
		}
	};
	
	void FenLie(Monster* pMonster) {
		Monster* m_Monster = pMonster->clone();
		/* 业务逻辑 */
		delete m_Monster;
	}


int main() {

	Monster* slm = new ShiLaimu(100, 50, 50);
	Monster* slm1 = slm->clone();
	delete slm;
	delete slm1;

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值