设计模式3 创建型模型

目录:

简单工厂模式
工厂方法模式
抽象工厂模式
单例模式



简单工厂 模型

chunli@linux:~$ cat main.cpp 
//设计模式:简单工厂 模型
#include
using namespace std;
class Fruit
{
public:
	Fruit(string kind)
	{
		this->kind = kind;
		if(kind == "apple")
		{}
		else if (kind == "banana")
		{}
	}
	void getName()
	{
		if(kind == "apple")
		{
			cout << "我是苹果" << endl;
		}
		else if(kind == "banana")
		{
			cout << "我是香蕉" << endl; 
		}
	}
private:
	string kind;//代表水果种类
};



int main()
{
	Fruit* apple = new Fruit("apple");
	apple->getName();

	return 0;
}





chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是苹果
chunli@linux:~$


出现的问题:如果再添加新的水果,越来越复杂

chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是苹果
我是香蕉
chunli@linux:~$ 
chunli@linux:~$ 
chunli@linux:~$ cat main.cpp 
//设计模式:简单工厂 实现
#include
using namespace std;

//抽象的水果类
class Fruit
{
public:
	virtual void getName() = 0;
};
//实际水果
class Apple:public Fruit
{
public:
	virtual void getName()
	{
		cout << "我是苹果"<createFruit("apple");
	apple->getName();
	
	Fruit *banana	 = factory->createFruit("banana");
	banana->getName();
	return 0;
}





chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是苹果
我是香蕉
chunli@linux:~$


简单工厂优缺点,GOF不承认.但是依然有很多人在用.

优点:

1,实现了对象的创建和是使用的分离.

2,不知要记住具体的类名,记住参数即可,减少使用者的记忆量.


缺点:

1,对工厂类的职责过重,一旦不能工作,紫铜受到影响.

2,增加系统中类的个数,负责度和理解度增加.

3,违反了开闭原则,添加新的产品需要修改工厂逻辑,工厂越来越复杂. +



适用场景:

1,工厂类负责创建的对象比较少,由于创建的对象比较少,不会造成工厂方法中的而业务逻辑太过复杂.

2,客户端只知道传入工厂类的参数,对于如何创建对象并不关心.

=========================================




工厂方法模式,

看图[工厂方法模式的案例]

设计模式3 创建型模型_第1张图片


chunli@linux:~$ cat main.cpp 
//工厂模式
//符合开闭原则,添加一个产品不用修改其他的代码
//简单工厂模式 + "开闭原则" = 工厂方法模式

#include
using namespace std;

/////////////// 抽象类 //////////////////////////
class Fruit	//抽象的水果类
{
public:
	virtual void getName() = 0;
	virtual ~Fruit(){}
};

class AbstractFactory//抽象工厂
{
public:
	virtual Fruit* createFruit() = 0;
	virtual ~AbstractFactory(){}
};

////////////// 实现类 //////////////////
//1,苹果
class Apple:public Fruit//苹果类
{
public:
	virtual void getName()
	{
		cout << "我是苹果" <createFruit();	//生产一个香蕉
	banana->getName();
	delete bananaFactory;
	delete banana;

	AbstractFactory* applefactory 	= new AppleFactory;
	Fruit* apple 			= applefactory->createFruit();
	apple->getName();
	delete applefactory;
	delete apple;
	
	AbstractFactory* pearfactory	= new PearFactory;
	Fruit* pear			= pearfactory->createFruit();
	pear->getName();
	delete pearfactory;
	delete pear;

	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是香蕉
我是苹果
我是梨
chunli@linux:~$



工厂方法模式的优缺点

优点: 

        1. 不需要记住具体类名,甚至连具体参数 都不用记忆。 

        2. 实现了对象创建和使用的分离。 

        3. 系统的可扩展性也就变得非常好,无需修改接口和原类。 

  

缺点: 

        1. 增加系统中类的个数,复杂度和理解度增加。  

        2. 增加了系统的抽象性和理解难度。


适用场景 

      1. 客户端不知道它所需要的对象的类。  

      2. 抽象工厂类通过其子类来指定创建哪个对象。

==========================================



抽象工厂模式:

看图:[抽象工厂模式]

设计模式3 创建型模型_第2张图片


chunli@linux:~$ cat main.cpp 
//抽象工厂方法 模式
#include
using namespace std;

/////////////// 抽象 水果 类 //////////////////////////
class Fruit	//抽象的水果类
{
public:
	virtual void getName() = 0;
	virtual ~Fruit(){}
};

////////////// 实现 水果类 //////////////////
class USAApple:public Fruit//苹果类
{
public:
	virtual void getName()
	{
		cout << "我是 美国 苹果" <createBanana();
	usabanana->getName();
	delete	usaf;
	delete	usabanana;

	//想要一个中国的苹果
	//1,来一个中国的工厂
	AbstractFactory* chinaf	= new ChinaFactory;
	Fruit* chinaapple	= chinaf->createApple();
	chinaapple->getName();
	delete	chinaf;
	delete	chinaapple;

	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是 美国 香蕉
我是 中国 苹果
chunli@linux:~$


添加一个日本的工厂,符合 开闭原则

chunli@linux:~$ cat main.cpp 
//抽象工厂方法 模式
#include
using namespace std;

/////////////// 抽象 水果 类 //////////////////////////
class Fruit	//抽象的水果类
{
public:
	virtual void getName() = 0;
	virtual ~Fruit(){}
};

////////////// 实现 水果类 //////////////////
class USAApple:public Fruit//苹果类
{
public:
	virtual void getName()
	{
		cout << "我是 美国 苹果" <createBanana();
	usabanana->getName();
	delete	usaf;
	delete	usabanana;

	//想要一个中国的苹果
	//1,来一个中国的工厂
	AbstractFactory* chinaf	= new ChinaFactory;
	Fruit* chinaapple	= chinaf->createApple();
	chinaapple->getName();
	delete	chinaf;
	delete	chinaapple;

	//想要一个Japan的苹果
	//1,来一个Japan的工厂
	AbstractFactory* japanf	= new JapanFactory;
	Fruit* japanapple	= japanf->createApple();
	japanapple->getName();
	delete	japanf;
	delete	japanapple;
	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是 美国 香蕉
我是 中国 苹果
我是 Japan 苹果
chunli@linux:~$



添加一种新的水果,梨.开闭原则被打破

chunli@linux:~$ cat main.cpp 
//抽象工厂方法 模式
#include
using namespace std;

/////////////// 抽象 水果 类 //////////////////////////
class Fruit	//抽象的水果类
{
public:
	virtual void getName() = 0;
	virtual ~Fruit(){}
};

////////////// 实现 水果类 ,美国&中国&日本 -> 苹果,香蕉,梨//////////////////
class USAApple:public Fruit
{
public:
	virtual void getName()
	{
		cout << "我是 美国 苹果" <createBanana();
	usabanana->getName();
	delete	usaf;
	delete	usabanana;

	//想要一个中国的苹果
	//1,来一个中国的工厂
	AbstractFactory* chinaf	= new ChinaFactory;
	Fruit* chinaapple	= chinaf->createApple();
	chinaapple->getName();
	delete	chinaf;
	delete	chinaapple;

	//想要一个Japan的pear
	//1,来一个Japan的工厂
	AbstractFactory* japanf	= new JapanFactory;
	Fruit* japanpear	= japanf->createPear();
	japanpear->getName();
	delete	japanf;
	delete	japanpear;
	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
我是 美国 香蕉
我是 中国 苹果
我是 Japan pear
chunli@linux:~$


抽象工厂模式的优缺点 


优点 

  1.  拥有工厂方法模式的优点 

  2. 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端

始终只使用同一个产品族中的对象。 

  3   增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。  

缺点  

  1. 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需

要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。 



适用场景 

      (1)  系统中有多于一个的产品族。而每次只使用其中某一产品族。可以通过

配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产

品族。 

      (2)  产品等级结构稳定。设计完成之后,不会向系统中增加新的产品等级结

构或者删除已有的产品等级结构。 






作业: 


 设计一个电脑主板架构,电脑包括(显卡,内存,CPU)3个固定的插口,

显卡具有显示功能(display,功能实现只要打印出意义即可), 内存具有存

储功能(storage),cpu具有计算功能(calculate)。 

  现有Intel厂商,nvidia厂商,Kingston 厂商,均会生产以上三种硬件。 

  要求组装两台电脑,  

           1台(Intel的CPU,Intel的显卡,Intel的内存) 

           1台(Intel的CPU, nvidia的显卡,Kingston 的内存) 

  用抽象工厂模式实现。 


抽象工厂方法,intel系列产品,组装一台Intel的电脑

chunli@linux:~$ cat main.cpp 
#include
using namespace std;
/*	抽象层	*/
class CPU
{
public:
	virtual void caculate() = 0;
};

class Card
{
public:
	virtual void dispaly() = 0;
};

class Memory
{
public:
	virtual void storage() = 0;
};

/*	抽象工厂	*/
class AbstractFactory
{
public:
	virtual	CPU*	createCPU() = 0;
	virtual	Card*	createCard() = 0;
	virtual	Memory*	createMem() = 0;
};
/*	抽象架构	*/
class Computer
{
public:
	Computer(CPU* cpu,Card* card,Memory* mem)
	{
		this->cpu	= cpu;
		this->card	= card;
		this->mem	= mem;
	}
	void work()
	{
		this->cpu->caculate();
		this->card->dispaly();
		this->mem->storage();
	}
private:
	CPU*	cpu;
	Card*	card;
	Memory*	mem;
};
/*------抽象完成--------*/





/*	实现层	*/
class IntelCPU:public CPU
{
public:
	virtual void caculate()
	{
		cout << "开始计算" << endl;
	};
};

class IntelCard:public Card
{
public:
	virtual void dispaly()
	{
		cout << "开始显示 " << endl;
	};
};

class IntelMem:public Memory
{
public:
	virtual void storage()
	{
		cout << "开始存储" << endl;
	};
};
class IntelFactory:public AbstractFactory
{
public:
	virtual CPU*	createCPU()
	{
		return new IntelCPU;
	}
	virtual Card*	createCard()
	{
		return new IntelCard;
	}
	virtual Memory*	createMem()
	{
		return new IntelMem;
	}
};


int main()
{
	//组装一台电脑
	//创建一个Intel的工厂
	AbstractFactory	*intelFactory = new IntelFactory;//父类指针 指向 子类对象
	CPU*	intelCPU 	= intelFactory->createCPU();
	Card*	intelCard  	= intelFactory->createCard();
	Memory*	intelMem  	= intelFactory->createMem();
	Computer* com1 = new Computer(intelCPU,intelCard,intelMem);
	com1->work();
	cout << "-------------------------" << endl;


	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
开始计算
开始显示 
开始存储
-------------------------
chunli@linux:~$


抽象工厂方法,intel系列产品,组装一台 台式机

chunli@linux:~$ cat main.cpp 
#include
using namespace std;
/*	抽象层	*/
class CPU
{
public:
	virtual void caculate() = 0;
};

class Card
{
public:
	virtual void dispaly() = 0;
};

class Memory
{
public:
	virtual void storage() = 0;
};

/*	抽象工厂	*/
class AbstractFactory
{
public:
	virtual	CPU*	createCPU() = 0;
	virtual	Card*	createCard() = 0;
	virtual	Memory*	createMem() = 0;
};
/*	抽象架构	*/
class Computer
{
public:
	Computer(CPU* cpu,Card* card,Memory* mem)
	{
		this->cpu	= cpu;
		this->card	= card;
		this->mem	= mem;
	}
	void work()
	{
		this->cpu->caculate();
		this->card->dispaly();
		this->mem->storage();
	}
private:
	CPU*	cpu;
	Card*	card;
	Memory*	mem;
};
/*------抽象完成--------*/

/*	实现层	 Intel厂商  */
class IntelCPU:public CPU
{
public:
	virtual void caculate()
	{
		cout << "Intel cpu 开始计算" << endl;
	};
};

class IntelCard:public Card
{
public:
	virtual void dispaly()
	{
		cout << "intel card 开始显示 " << endl;
	};
};

class IntelMem:public Memory
{
public:
	virtual void storage()
	{
		cout << "intel mem 开始存储" << endl;
	};
};
class IntelFactory:public AbstractFactory
{
public:
	virtual CPU*	createCPU()
	{
		return new IntelCPU;
	}
	virtual Card*	createCard()
	{
		return new IntelCard;
	}
	virtual Memory*	createMem()
	{
		return new IntelMem;
	}
};

/*	实现层	 英伟达 厂商  */
class NvidiaCPU:public CPU
{
public:
	virtual void caculate()
	{
		cout << "Nvidia cpu 开始计算" << endl;
	};
};

class NvidiaCard:public Card
{
public:
	virtual void dispaly()
	{
		cout << "Nvidia card 开始显示 " << endl;
	};
};

class NvidiaMem:public Memory
{
public:
	virtual void storage()
	{
		cout << "Nvidia mem 开始存储" << endl;
	};
};
class NvidiaFactory:public AbstractFactory
{
public:
	virtual CPU*	createCPU()
	{
		return new NvidiaCPU;
	}
	virtual Card*	createCard()
	{
		return new NvidiaCard;
	}
	virtual Memory*	createMem()
	{
		return new NvidiaMem;
	}
};

/*	实现层	 金士顿 厂商  */
class KingstonCPU:public CPU
{
public:
	virtual void caculate()
	{
		cout << "Kingston cpu 开始计算" << endl;
	};
};

class KingstonCard:public Card
{
public:
	virtual void dispaly()
	{
		cout << "Kingston card 开始显示 " << endl;
	};
};

class KingstonMem:public Memory
{
public:
	virtual void storage()
	{
		cout << "Kingston mem 开始存储" << endl;
	};
};
class KingstonFactory:public AbstractFactory
{
public:
	virtual CPU*	createCPU()
	{
		return new KingstonCPU;
	}
	virtual Card*	createCard()
	{
		return new KingstonCard;
	}
	virtual Memory*	createMem()
	{
		return new KingstonMem;
	}
};



int main()
{
	//组装一台兼容机,要Intel的cpu,nvidia的card,kingston的mem

	AbstractFactory	*intelFactory = new IntelFactory;
	AbstractFactory	*nvidiaFactory = new NvidiaFactory;
	AbstractFactory	*kingstonFactory = new KingstonFactory;

	CPU*	intelCPU 	= intelFactory->createCPU();
	Card*	nvidiaCard  	= nvidiaFactory->createCard();
	Memory*	kingstonlMem  	= kingstonFactory->createMem();
	Computer* computer = new Computer(intelCPU,nvidiaCard,kingstonlMem);
	computer->work();


	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
Intel cpu 开始计算
Nvidia card 开始显示 
Kingston mem 开始存储
chunli@linux:~$



============================================





单例模式,整个程序中只有一个对象.


1,饿汉式

chunli@linux:~$ cat main.cpp 
#include
using namespace std;


// 三个要点: 
// 一是某个类只能有一个实例; 
// 二是它必须自行创建这个实例; 
// 三是它必须自行向整个系统提供这个实例。

class Singleton
{
public:
	static Singleton* getInstance()
	{
		return instance;
	}
private:
	Singleton(){}
	static Singleton* instance;
};

//在编译期间,就已经确定这个唯一的实例了
Singleton* Singleton::instance = new Singleton;//饿汉式



int main()
{
	Singleton *s1 = Singleton::getInstance();
	Singleton *s2 = Singleton::getInstance();
	if(s1 == s2)
	{
		cout << "s1 == s2 " << endl;
	}
	else 
	{

		cout << "s1 != s2 " << endl;
	}


	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
s1 == s2 
chunli@linux:~$


2,懒汉式

chunli@linux:~$ cat main.cpp 
#include
using namespace std;
// 三个要点: 
// 一是某个类只能有一个实例; 
// 二是它必须自行创建这个实例; 
// 三是它必须自行向整个系统提供这个实例。

class Singleton
{
public:
	static Singleton* getInstance()
	{
		if(instance == NULL)	//懒汉式 多线程危险
		{
			instance = new Singleton;
		}
		return instance;
	}
private:
	Singleton(){}
	static Singleton* instance;
};
Singleton* Singleton::instance = NULL;//懒汉式

int main()
{
	Singleton *s1 = Singleton::getInstance();
	Singleton *s2 = Singleton::getInstance();
	if(s1 == s2)
	{
		cout << "s1 == s2 " << endl;
	}
	else 
	{

		cout << "s1 != s2 " << endl;
	}
	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
s1 == s2 
chunli@linux:~$


单例模式,懒汉式多线程问题

class Singleton
{
public:
	static Singleton* getInstance()
	{
		//加锁
		if(instance == NULL)	//懒汉式 多线程危险
		{
			instance = new Singleton;
		}
		//解锁
		return instance;
	}
private:
	Singleton(){}
	static Singleton* instance;
};
Singleton* Singleton::instance = NULL;//懒汉式


单例模式,打印机案例,单例的回收

chunli@linux:~$ cat main.cpp 
#include
using namespace std;
// 三个要点: 
// 一是某个类只能有一个实例; 
// 二是它必须自行创建这个实例; 
// 三是它必须自行向整个系统提供这个实例。

class Printer
{
public:
	static Printer* getInstance()
	{
		if(instance == NULL)	//懒汉式 多线程危险
		{
			instance = new Printer;
		}
		return instance;
	}
	void printf(string text)
	{
		sequence++;
		cout << sequence << " 打印的内容是" << text << endl;
	}
	static int getCount()//返回已经打印了多少次
	{
		return sequence;
	}
private:
	class Garbo	//单例的垃圾回收机制
	{
	public:
		~Garbo()
		{
			if(instance != NULL)
			{
				cout << "开始析构 instance" << endl;
				delete instance;
			}
		}
	};
private:
	Printer(){}
	static int sequence;	//记录打印机已经打印了多少条数据
	static Printer* instance;
	static	Garbo garbo;//在静态区开辟空间,程序运行结束时,释放instance
};

Printer* Printer::instance = NULL;//懒汉式
int Printer::sequence = 0;
Printer::Garbo Printer::garbo;

int main()
{
	Printer *p1 = Printer::getInstance();	p1->printf(" 我的简历.doc");
	Printer *p2 = Printer::getInstance();	p2->printf(" LOL皮肤.jpg");
	Printer *p3 = Printer::getInstance();	p3->printf(" 离职简历.doc");
	return 0;
}
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 
1 打印的内容是 我的简历.doc
2 打印的内容是 LOL皮肤.jpg
3 打印的内容是 离职简历.doc
开始析构 instance
chunli@linux:~$