C++基本设计模式01

C++基本设计模式01

1 简单工厂模式:不直接在客户端创建类对象,利用工厂类的方法CreateObject来创建。
优点:1 客户端和具体类解耦 即分开来 2 不需要担心对象创建的复杂程度。
缺点:1 增加新功能通过改变源代码 ,不符合开闭原则。 2 工程类职责过多,该类发生问题影响许多类。
在这里插入图片描述

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

//水果抽象类
class AbstractFruit{
public:
	virtual void ShowName() = 0;
};

class Apple:public AbstractFruit{
public:
	virtual void ShowName(){
		cout<<"我是苹果"<<endl;
	}
};

class Banana:public AbstractFruit{
public:
	virtual void ShowName(){
		cout<<"我是香蕉"<<endl;
	}
};

class Pear:public AbstractFruit{
public:
	virtual void ShowName(){
		cout<<"我是鸭梨"<<endl;
	}
};

//简单工厂模式 利用工厂创建水果
class FruitFactory{
public:
	//最好使用静态 这样类名也可以调用
	static AbstractFruit* CreateObject(string fruit){
		if(fruit=="苹果"){
			return new Apple;
		}else if(fruit=="香蕉"){
			return new Banana;
		}else if(fruit=="鸭梨"){
			return new Pear;
		}else{
			return NULL;
		}
	}
};

void test01(){

	FruitFactory *fac=new FruitFactory;
	AbstractFruit *fruit=fac->CreateObject("苹果");
	fruit->ShowName();
	delete fruit;

    fruit=fac->CreateObject("香蕉");
	fruit->ShowName();
	delete fruit;

	//创建鸭梨
	fruit=fac->CreateObject("鸭梨");
	fruit->ShowName();
	delete fruit;

	delete fac;

}

int main(){

	test01();

	return 0;
}

总结简单工厂模式:不直接在客户端创建类对象,利用工厂类的方法CreateObject来创建。例子:苹果、香蕉、鸭梨。通过简单工厂类的方法CreateObject创建对象返回相应的水果,比较简单。

2 工厂方法模式: 将工厂抽象出来 一个工厂具体类对应一个水果具体类,即简单工厂模式+开闭法则。
优点: 符合开闭法则。
缺点: 类成倍的增加,维护难度加大。
在这里插入图片描述

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

//水果抽象类
class AbstractFruit{
public:
	virtual void ShowName() = 0;
};

class Apple:public AbstractFruit{
public:
	virtual void ShowName(){
		cout<<"我是苹果"<<endl;
	}
};

class Banana:public AbstractFruit{
public:
	virtual void ShowName(){
		cout<<"我是香蕉"<<endl;
	}
};

class Pear:public AbstractFruit{
public:
	virtual void ShowName(){
		cout<<"我是鸭梨"<<endl;
	}
};


//工厂方法模式 将工厂抽象出来
class AbstractFruitFactory{
public:
	virtual AbstractFruit* CreateObject()=0;  //因为要创建对象 所以需要创建对象纯虚函数
};

//苹果工厂
class AppleFactory:public AbstractFruitFactory{
public:
	virtual AbstractFruit* CreateObject(){
		return new Apple;
	}
};

//香蕉工厂
class BananaFactory:public AbstractFruitFactory{
public:
	virtual AbstractFruit* CreateObject(){
		return new Banana;
	}
};

//鸭梨工厂
class PearFactory:public AbstractFruitFactory{
public:
	virtual AbstractFruit* CreateObject(){
		return new Pear;
	}
};

void test01(){

	//先创建两个抽象类指针 用于接收具体工厂和具体水果
	AbstractFruitFactory *factory=NULL;
	AbstractFruit *fruit=NULL;

	//通过苹果工厂 创建苹果
	factory=new AppleFactory;//多态的必要条件之一,基类指针指向派生类,另一个是具有virtual。
	fruit=factory->CreateObject();
	fruit->ShowName();
	delete factory;
	delete fruit;

	//通过香蕉工厂 创建香蕉
	factory=new BananaFactory;
	fruit=factory->CreateObject();
	fruit->ShowName();
	delete factory;
	delete fruit;

	//通过鸭梨工厂 创建鸭梨
	factory=new PearFactory;
	fruit=factory->CreateObject();
	fruit->ShowName();
	delete factory;
	delete fruit;

}

int main(){

	test01();

	return 0;
}

总结工厂模式:两个抽象类,一个派生工厂对应一个派生类生产。例子没必要深刻记忆,记住前面那句话便可。

3 抽象工厂模式:针对的是产品族,而不是产品结构。
产品族: 同一产地或者同一厂商,功能不同 即中国产地的,不同品种水果。
产品等级: 功能相同,产地或者厂商不同,即同一水果在不同产地。
如果此时增加一个西瓜,产品等级符合开辟原则,只需要写多个西瓜抽象类就可以不用改变源代码。
而产品族则需要改变源代码,需要在抽象工厂类添加一个函数,不符合开辟法则,所以说抽象工厂是针对!!!产品族!!!的。
在这里插入图片描述

例子1的思想:
思想:抽象工厂是针对于产品族的 所以一个具体工厂包含苹果香蕉鸭梨,而苹果又分中国的,美国的,倭国的。
显然一个抽象水果类无法完成,所以需要将苹果,香蕉,鸭梨各自抽象出来,然后就可以分成多个产地的苹果,香蕉,鸭梨。

//抽象苹果
class AbstractApple{
public:
	virtual void ShowName() = 0;
};

//中国苹果
class ChinaApple : public AbstractApple{
public:
	virtual void ShowName(){
		cout << "中国苹果!" << endl;
	}
};

//美国苹果
class USAApple : public AbstractApple{
public:
	virtual void ShowName(){
		cout << "美国苹果!" << endl;
	}
};

//倭国苹果
class JapanApple : public AbstractApple{
public:
	virtual void ShowName(){
		cout << "倭国苹果!" << endl;
	}
};

//抽象香蕉
class AbstractBanana{
public:
	virtual void ShowName() = 0;
};

//中国香蕉
class ChinaBanana : public AbstractBanana{
public:
	virtual void ShowName(){
		cout << "中国香蕉!" << endl;
	}
};

//美国香蕉
class USABanana : public AbstractBanana{
public:
	virtual void ShowName(){
		cout << "美国香蕉!" << endl;
	}
};

//倭国香蕉
class JapanBanana : public AbstractBanana{
public:
	virtual void ShowName(){
		cout << "倭国香蕉!" << endl;
	}
};

//抽象鸭梨
class AbstractPear{
public:
	virtual void ShowName() = 0;
};

//中国鸭梨
class ChinaPear : public AbstractPear{
public:
	virtual void ShowName(){
		cout << "中国鸭梨!" << endl;
	}
};

//美国鸭梨
class USAPear : public AbstractPear{
public:
	virtual void ShowName(){
		cout << "美国鸭梨!" << endl;
	}
};

//倭国鸭梨
class JapanPear : public AbstractPear{
public:
	virtual void ShowName(){
		cout << "倭国鸭梨!" << endl;
	}
};


//产品族:不同品种 例如苹果香蕉鸭梨 产品等级:同一品种 例如中国苹果美国苹果倭国苹果
class AbstracFactory{
public:
	//因为抽象工厂针对产品族 所以每个工厂创建苹果香蕉鸭梨这组产品族
	virtual AbstractApple* CreateApple()=0;
	virtual AbstractBanana* CreateBanana()=0;
	virtual AbstractPear* CreatePear()=0;
};

//中国工厂
class ChinaFactory:public AbstracFactory{
public:
	virtual AbstractApple* CreateApple(){
		return new ChinaApple;
	}
	virtual AbstractBanana* CreateBanana(){
		return new ChinaBanana;
	}
	virtual AbstractPear* CreatePear(){
		return new ChinaPear;
	}
};

//美国工厂
class USAFactory:public AbstracFactory{
public:
	virtual AbstractApple* CreateApple(){
		return new USAApple;
	}
	virtual AbstractBanana* CreateBanana(){
		return new USABanana;
	}
	virtual AbstractPear* CreatePear(){
		return new USAPear;
	}
};

//倭国工厂
class JapanFactory:public AbstracFactory{
public:
	virtual AbstractApple* CreateApple(){
		return new JapanApple;
	}
	virtual AbstractBanana* CreateBanana(){
		return new JapanBanana;
	}
	virtual AbstractPear* CreatePear(){
		return new JapanPear;
	}
};

void test01(){

	//定义四个抽象类指针
	AbstracFactory *factory=NULL;
	AbstractApple *apple=NULL;
	AbstractBanana *banana=NULL;
	AbstractPear *pear=NULL;

	//创建中国工厂 并且显示其产品族
	factory=new ChinaFactory();

	apple=factory->CreateApple();	
	banana=factory->CreateBanana();
	pear=factory->CreatePear();

    apple->ShowName();
    banana->ShowName();
	pear->ShowName();
	
	delete apple;
	delete banana;
	delete pear;
	delete factory;
}

int main(){

	test01();

	return 0;
}

例子2:电脑练习。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

/*
       设计一个电脑主板架构,电脑包括(显卡,内存,CPU)3个固定的插口
       显卡具有显示功能(display,功能实现只 要打印出意义即可)内存具有存储功能(storage)
       cpu具有计算功能(calculate)

 	现有Intel厂商,nvidia厂商,Kingston厂商,均会生产以上三种硬件。要求组装两台电脑:
		1台(Intel的CPU,Intel的显卡,Intel的内存)
		1台(Intel的CPU, nvidia的显卡,Kingston的内存)
	    用抽象工厂模式实现

抽象工厂类:   针对产品族 而不是产品结构  而且工厂按照需求来建立 例如这里需要两个工厂建造电脑

例子有:苹果香蕉鸭梨 和 电脑组装
*/


//抽象类卡
class AbstructCard{
public:
	virtual void display()=0;
};

//具体类 英特尔的显卡
class IntelCard:public AbstructCard{
public:
	virtual void display(){
		cout<<"这是英特尔的显卡"<<endl;
	}
};

//具体类 英伟达的显卡
class NvidiaCard:public AbstructCard{
public:
	virtual void display(){
		cout<<"这是英伟达的显卡"<<endl;
	}
};

//具体类 Kingston的显卡
class KingstonCard:public AbstructCard{
public:
	virtual void display(){
		cout<<"这是Kingston的显卡"<<endl;
	}
};

//抽象类内存
class AbstructStorage{
public:
	virtual void storage()=0;
};

//具体类 Intel的内存
class IntelStorage:public AbstructStorage{
public:
	virtual void storage(){
		cout<<"这是英特尔的存储内存"<<endl;
	}
};

//具体类 Nvidia的内存
class NvidiaStorage:public AbstructStorage{
public:
	virtual void storage(){
		cout<<"这是Nvidia的存储内存"<<endl;
	}
};

//具体类 Kingston的内存
class KingstonStorage:public AbstructStorage{
public:
	virtual void storage(){
		cout<<"这是Kingston的存储内存"<<endl;
	}
};

//抽象类CPU
class AbstructCpu{
public:
	virtual void caculate()=0;
};

//具体类 英特尔的CPU
class IntelCPU:public AbstructCpu{
public:
	virtual void caculate(){
		cout<<"这是英特尔的CPU"<<endl;
	}	
};

//具体类 Nvidia的CPU
class NvidiaCPU:public AbstructCpu{
public:
	virtual void caculate(){
		cout<<"这是Nvidia的CPU"<<endl;
	}	
};

//具体类 Kingston的CPU
class KingstonCPU:public AbstructCpu{
public:
	virtual void caculate(){
		cout<<"这是Kingston的CPU"<<endl;
	}	
};


//抽象工厂类   请记得是帮别人创建对象
class AbstructFactory{
public:
	virtual AbstructCard*    CreateCard()     = 0;
	virtual AbstructStorage* CreateStorage()  = 0;
	virtual AbstructCpu*     CreateCaculate() = 0;
};

//具体工厂类 按照电脑零件的需求 创建工厂 不必向苹果那样!!!!!
//生产第一种要求的电脑
//这里再次强调,当零件(显卡内存CPU)写好后,抽象工厂的定义是按照需要实现的。
class FirstComputerFactory:public AbstructFactory{
public:
	virtual AbstructCard* CreateCard(){
		return (new IntelCard);
	}
	virtual AbstructStorage* CreateStorage() {
		return (new IntelStorage);
	}
	virtual AbstructCpu*     CreateCaculate(){
		return (new IntelCPU);
	}
};

//具体工厂类 生产第二种电脑的工厂
class SecondComputerFactory:public AbstructFactory{
public:
	virtual AbstructCard* CreateCard(){
		return (new NvidiaCard);
	}
	virtual AbstructStorage* CreateStorage(){
		return (new KingstonStorage);
	}
	virtual AbstructCpu*  CreateCaculate(){
		return (new IntelCPU);
	}
};

#if 0
//具体工厂类 Kingston工厂 不必创建每一个工厂 按需求建立工厂
class KingstonFactory:public AbstructFactory{
public:
	virtual AbstructCard* CreateCard(){
		return (new KingstonCard);
	}
	virtual AbstructStorage* CreateStorage(){
		return (new KingstonStorage);
	}
	virtual AbstructCpu* CreateCaculate(){
		return (new KingstonCPU);
	}
};
#endif



//电脑类
class Computer{
public:

	//电脑一开始初始化为空
	Computer(){
		m_card=NULL;
		m_storage=NULL;
		m_cpu=NULL;
	}
	//开始设置电脑零件
	void setComputerCard(AbstructCard* card){
		m_card=card;
	}
	void setComputerStorage(AbstructStorage* storage){
		m_storage=storage;
	}
	void setComputerCpu(AbstructCpu* cpu){
		m_cpu=cpu;
	}

	//启动电脑
	void run(){
		if(m_card!=NULL){
			m_card->display();;
		}
		if(m_storage!=NULL){
			m_storage->storage();
		}
		if(m_cpu!=NULL){
			m_cpu->caculate();
		}
	}

	//释放成员变量
	~Computer(){
		if(m_card!=NULL){
			delete m_card;
		}
		if(m_storage!=NULL){
			delete m_storage;
		}
		if(m_cpu!=NULL){
			delete m_cpu;
		}
	}

public:
	AbstructCard* m_card;
	AbstructStorage* m_storage;
	AbstructCpu* m_cpu;
};

void test01(){
#if 0 
	//这样写在组装第二台电脑非常麻烦
	AbstructFactory* factory=NULL;
	AbstructCard* card=NULL;
	AbstructStorage* storage=NULL;
	AbstructCpu* cpu=NULL;

	//开始组装电脑1
	factory=new IntelFactory;
	Computer* computer=new Computer;
	computer->setComputer(factory->CreateCard(),storage=factory->CreateStorage()
	 ,cpu=factory->CreateCaculate());
	delete factory;
#endif

	//生产电脑需要 工厂和原始电脑 电脑1
	Computer* comp1=new Computer;
	AbstructFactory* factory=new FirstComputerFactory;
	//装配零件
	comp1->setComputerCard(factory->CreateCard());
	comp1->setComputerStorage(factory->CreateStorage());
	comp1->setComputerCpu(factory->CreateCaculate());
	comp1->run();

	delete comp1;
	delete factory;

	cout<<"================="<<endl;

	//电脑2
	Computer* comp2=new Computer;
	factory=new SecondComputerFactory;
	//装配零件
	comp2->setComputerCard(factory->CreateCard());
	comp2->setComputerStorage(factory->CreateStorage());
	comp2->setComputerCpu(factory->CreateCaculate());
	comp2->run();

	delete comp2;
	delete factory;

}


int main(){

	test01();

	return 0;
}

总结抽象工厂模式:针对产品族,而不是产品结构。 例子1,中国工厂能生产中国苹果、香蕉、鸭梨。美国工厂能生产美国苹果、香蕉、鸭梨。倭国工厂能生产倭国苹果、香蕉、鸭梨;例子2,电脑练习,按需求生产工厂,最后定义电脑类生产电脑。
即具体零部件具有多个抽象类,工厂类只有一个。

对比简单工厂模式:

  • 1)简单工厂模式符合开辟原则,但是源码太大,不易维护。
  • 2)而抽象工厂模式不符合开辟原则,增加新的内容需要改变抽象工厂类的源代码,容易维护。
  • 3)简单工厂与抽象工厂看具体情况选择即可,并且强调抽象工厂模式,当具体零件写好后,工厂类按照实际需求编写即可,无需死板固定思路。

4 单例模式:所谓单例模式,就是只有一个实体对象。
/*
实现单例步骤:
1 构造私有
2 设有一个私有静态本类指针
3 提供静态函数接口
*/
下面是单例模式的两个典型例子:懒汉模式和饿汉模式。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<mutex>
using namespace std;

#define SAVE_DELETE(obj) if(obj){delete obj;obj=NULL;}
#define SAVE_A_DELETE(obj) if(obj){delete [] obj;obj=NULL;}

//单例模型实例 懒汉模式 --调用时才初始化对象
class Singleton_lazy {
private:
	Singleton_lazy() {}
	~Singleton_lazy(){}//可有可无

public:
	static Singleton_lazy*  get_Singleton_lazy() {
		if (m_lazy == NULL) {
			unique_lock<mutex> uLock(m_mutex);
			if (m_lazy == NULL) {
				m_lazy = new Singleton_lazy;
			}
		}
		return m_lazy;
	}

	class Garbor {
	public:
		Garbor(){}
		~Garbor(){
			SAVE_DELETE(m_lazy);
		}
	};
private:
	static Singleton_lazy* m_lazy;
	static mutex m_mutex;
	static Garbor m_garbor;
};
//类外初始化静态变量
Singleton_lazy* Singleton_lazy::m_lazy = NULL;
mutex Singleton_lazy::m_mutex;
Singleton_lazy::Garbor Singleton_lazy::m_garbor;


//单例模型实例 饿汉模式 --初始化比main函数还快 所以叫饿汉
class Singleton_hungry {
private:
	Singleton_hungry() {
		//cout<<"我是饿汉"<<endl;
	}

public:
	static Singleton_hungry*  get_Singleton_hungry() {
		return m_hun;
	}

	class Garbor {
	public:
		Garbor() {}
		~Garbor() {
			SAVE_DELETE(m_hun);
		}
	};

private:
	static Singleton_hungry*  m_hun;
};
//类外初始化静态变量
Singleton_hungry* Singleton_hungry::m_hun = new Singleton_hungry;

int main() {

	//懒汉模式
	Singleton_lazy *a = Singleton_lazy::get_Singleton_lazy();
	Singleton_lazy *b = Singleton_lazy::get_Singleton_lazy();

	if (a == b) {
		cout << "是单例模式" << endl;
	}
	else {
		cout << "不是单例模式" << endl;
	}

	//饿汉模式
	Singleton_hungry *c = Singleton_hungry::get_Singleton_hungry();
	Singleton_hungry *d = Singleton_hungry::get_Singleton_hungry();
	if (c == d) {
		cout << "是单例模式" << endl;
	}
	else {
		cout << "不是单例模式" << endl;
	}

	return 0;

	/*
	单例内存释放问题: 因为单例只有一个对象 即使在不断调用它也不会不断开辟内存 不会导致程序崩溃
		程序结束后系统自动回收 我们平时不回收对象内存是因为会不断开辟内存 容易造成内存泄漏
		并不是说程序结束不会回收 以前不回收的风险好大
		但是单列模式一般不考虑内存回收问题 让他程序结束自动回收
		实在想自己回收可以内嵌一个类 将该类对象作为单例类的数据 也是程序结束回收 但没必要
		栈是函数调用完毕就回收
	*/

}

单例模式要注意的两个问题:
1)可以不考虑它的内存问题,因为只有一个实体对象。
2)单例模式遇上多线程。
当我们的懒汉模式遇到多线程时,两个线程同时执行if(lazy==NULL),若刚好都满足条件,那么就不符合单个对象了;而饿汉模式在多线程下,因为对象在mian函数之前就已经类外初始化完毕了,所以不管你怎么调用静态函数,它返回的都是同一个对象。 所以可以得出:
/*
1 懒汉模式碰到多线程是不安全的 因为可能同时调用时会new两个对象—代码已解决多线程问题。
2 饿汉模式碰到多线程是安全的 因为在调用时就已经确定好返回哪个对象
*/

总结单例模式:
实现单例步骤:
1 构造私有
2 设有一个私有静态本类指针
3 提供静态函数接口
例子,懒汉模式和饿汉模式。

最后将这4个基本模式对比记忆:
1 总结简单工厂模式:不直接在客户端创建类对象,利用工厂类的方法CreateObject来创建。例子:苹果、香蕉、鸭梨。通过简单工厂类的方法CreateObject创建对象返回相应的水果,比较简单。

2 总结工厂模式:一个工厂对应一个类生产。例子没必要深刻记忆,记住前面那句话便可。

3 总结抽象工厂模式:针对产品族,而不是产品结构。 例子1,中国工厂能生产中国苹果、香蕉、鸭梨。美国工厂能生产美国苹果、香蕉、鸭梨。倭国工厂能生产倭国苹果、香蕉、鸭梨;例子2,电脑练习,按需求生产工厂,最后定义电脑类生产电脑。

4 总结单例模式:
实现单例步骤:
1 构造私有
2 设有一个私有静态本类指针
3 提供静态函数接口
例子,懒汉模式和饿汉模式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值