设计模式3 创建型模型

目录:简单工厂模式工厂方法模式抽象工厂模式单例模式



简单工厂 模型

chunli@linux:~$catmain.cpp//设计模式:简单工厂模型#include<iostream>usingnamespacestd;classFruit{public:Fruit(stringkind){this->kind=kind;if(kind=="apple"){}elseif(kind=="banana"){}}voidgetName(){if(kind=="apple"){cout<<"我是苹果"<<endl;}elseif(kind=="banana"){cout<<"我是香蕉"<<endl;}}private:stringkind;//代表水果种类};intmain(){Fruit*apple=newFruit("apple");apple->getName();return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out我是苹果chunli@linux:~$


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

chunli@linux:~$g++main.cpp-Wall&&./a.out我是苹果我是香蕉chunli@linux:~$chunli@linux:~$chunli@linux:~$catmain.cpp//设计模式:简单工厂实现#include<iostream>usingnamespacestd;//抽象的水果类classFruit{public:virtualvoidgetName()=0;};//实际水果classApple:publicFruit{public:virtualvoidgetName(){cout<<"我是苹果"<<endl;}};classBanana:publicFruit{public:virtualvoidgetName(){cout<<"我是香蕉"<<endl;}};classFactory{public://水果生产器Fruit*createFruit(stringkind){if(kind=="apple"){returnnewApple;}elseif(kind=="banana"){returnnewBanana;}returnNULL;}};intmain(){Factory*factory=newFactory;Fruit*apple=factory->createFruit("apple");apple->getName();Fruit*banana=factory->createFruit("banana");banana->getName();return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out我是苹果我是香蕉chunli@linux:~$


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

优点:

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

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


缺点:

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

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

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



适用场景:

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

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

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




工厂方法模式,

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


chunli@linux:~$catmain.cpp//工厂模式//符合开闭原则,添加一个产品不用修改其他的代码//简单工厂模式+"开闭原则"=工厂方法模式#include<iostream>usingnamespacestd;///////////////抽象类//////////////////////////classFruit//抽象的水果类{public:virtualvoidgetName()=0;virtual~Fruit(){}};classAbstractFactory//抽象工厂{public:virtualFruit*createFruit()=0;virtual~AbstractFactory(){}};//////////////实现类////////////////////1,苹果classApple:publicFruit//苹果类{public:virtualvoidgetName(){cout<<"我是苹果"<<endl;}};classAppleFactory:publicAbstractFactory//苹果的工厂{public:virtualFruit*createFruit(){returnnewApple;}};//2,香蕉classBanana:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是香蕉"<<endl;}};classBananaFactory:publicAbstractFactory//香蕉的工厂{public:virtualFruit*createFruit(){returnnewBanana;}};//3添加一个产品,梨classPear:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是梨"<<endl;}};classPearFactory:publicAbstractFactory//香蕉的工厂{public:virtualFruit*createFruit(){returnnewPear;}};intmain(){AbstractFactory*bananaFactory=newBananaFactory;//来一个香蕉的工厂Fruit*banana=bananaFactory->createFruit();//生产一个香蕉banana->getName();deletebananaFactory;deletebanana;AbstractFactory*applefactory=newAppleFactory;Fruit*apple=applefactory->createFruit();apple->getName();deleteapplefactory;deleteapple;AbstractFactory*pearfactory=newPearFactory;Fruit*pear=pearfactory->createFruit();pear->getName();deletepearfactory;deletepear;return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out我是香蕉我是苹果我是梨chunli@linux:~$



工厂方法模式的优缺点

优点:

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

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

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

缺点:

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

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


适用场景

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

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

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



抽象工厂模式:

看图:[抽象工厂模式]


chunli@linux:~$catmain.cpp//抽象工厂方法模式#include<iostream>usingnamespacestd;///////////////抽象水果类//////////////////////////classFruit//抽象的水果类{public:virtualvoidgetName()=0;virtual~Fruit(){}};//////////////实现水果类//////////////////classUSAApple:publicFruit//苹果类{public:virtualvoidgetName(){cout<<"我是美国苹果"<<endl;}};classUSABanana:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是美国香蕉"<<endl;}};classChinaApple:publicFruit//苹果类{public:virtualvoidgetName(){cout<<"我是中国苹果"<<endl;}};classChinaBanana:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是中国香蕉"<<endl;}};//////////定义一个抽象工厂,是面向产品族进行生产///////classAbstractFactory//抽象工厂{public:virtualFruit*createApple()=0;virtualFruit*createBanana()=0;virtual~AbstractFactory(){}};/////////美国的具体工厂////////////////////////////////////////classUSAFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewUSAApple;}virtualFruit*createBanana(){returnnewUSABanana;}};////中国的具体工厂///////////////////////////////////////classChinaFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewChinaApple;}virtualFruit*createBanana(){returnnewChinaBanana;}};intmain(){//想要一个美国的香蕉//1,来一个美国的工厂AbstractFactory*usaf=newUSAFactory;Fruit*usabanana=usaf->createBanana();usabanana->getName();deleteusaf;deleteusabanana;//想要一个中国的苹果//1,来一个中国的工厂AbstractFactory*chinaf=newChinaFactory;Fruit*chinaapple=chinaf->createApple();chinaapple->getName();deletechinaf;deletechinaapple;return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out我是美国香蕉我是中国苹果chunli@linux:~$


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

chunli@linux:~$catmain.cpp//抽象工厂方法模式#include<iostream>usingnamespacestd;///////////////抽象水果类//////////////////////////classFruit//抽象的水果类{public:virtualvoidgetName()=0;virtual~Fruit(){}};//////////////实现水果类//////////////////classUSAApple:publicFruit//苹果类{public:virtualvoidgetName(){cout<<"我是美国苹果"<<endl;}};classUSABanana:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是美国香蕉"<<endl;}};classChinaApple:publicFruit//苹果类{public:virtualvoidgetName(){cout<<"我是中国苹果"<<endl;}};classChinaBanana:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是中国香蕉"<<endl;}};classJapanApple:publicFruit//苹果类{public:virtualvoidgetName(){cout<<"我是Japan苹果"<<endl;}};classJapanBanana:publicFruit//香蕉类{public:virtualvoidgetName(){cout<<"我是Japan香蕉"<<endl;}};//////////定义一个抽象工厂,是面向产品族进行生产///////classAbstractFactory//抽象工厂{public:virtualFruit*createApple()=0;virtualFruit*createBanana()=0;virtual~AbstractFactory(){}};/////////美国的具体工厂////////////////////////////////////////classUSAFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewUSAApple;}virtualFruit*createBanana(){returnnewUSABanana;}};////中国的具体工厂///////////////////////////////////////classChinaFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewChinaApple;}virtualFruit*createBanana(){returnnewChinaBanana;}};////日本的具体工厂///////////////////////////////////////classJapanFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewJapanApple;}virtualFruit*createBanana(){returnnewJapanBanana;}};intmain(){//想要一个美国的香蕉//1,来一个美国的工厂AbstractFactory*usaf=newUSAFactory;Fruit*usabanana=usaf->createBanana();usabanana->getName();deleteusaf;deleteusabanana;//想要一个中国的苹果//1,来一个中国的工厂AbstractFactory*chinaf=newChinaFactory;Fruit*chinaapple=chinaf->createApple();chinaapple->getName();deletechinaf;deletechinaapple;//想要一个Japan的苹果//1,来一个Japan的工厂AbstractFactory*japanf=newJapanFactory;Fruit*japanapple=japanf->createApple();japanapple->getName();deletejapanf;deletejapanapple;return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out我是美国香蕉我是中国苹果我是Japan苹果chunli@linux:~$



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

chunli@linux:~$catmain.cpp//抽象工厂方法模式#include<iostream>usingnamespacestd;///////////////抽象水果类//////////////////////////classFruit//抽象的水果类{public:virtualvoidgetName()=0;virtual~Fruit(){}};//////////////实现水果类,美国&中国&日本->苹果,香蕉,梨//////////////////classUSAApple:publicFruit{public:virtualvoidgetName(){cout<<"我是美国苹果"<<endl;}};classUSABanana:publicFruit{public:virtualvoidgetName(){cout<<"我是美国香蕉"<<endl;}};classUSAPear:publicFruit{public:virtualvoidgetName(){cout<<"我是美国pear"<<endl;}};classChinaApple:publicFruit{public:virtualvoidgetName(){cout<<"我是中国苹果"<<endl;}};classChinaBanana:publicFruit{public:virtualvoidgetName(){cout<<"我是中国香蕉"<<endl;}};classChinaPear:publicFruit{public:virtualvoidgetName(){cout<<"我是中国pear"<<endl;}};classJapanApple:publicFruit{public:virtualvoidgetName(){cout<<"我是Japan苹果"<<endl;}};classJapanBanana:publicFruit{public:virtualvoidgetName(){cout<<"我是Japan香蕉"<<endl;}};classJapanPear:publicFruit{public:virtualvoidgetName(){cout<<"我是Japanpear"<<endl;}};//////////定义一个抽象工厂,是面向产品族进行生产///////classAbstractFactory//抽象工厂{public:virtualFruit*createApple()=0;virtualFruit*createBanana()=0;virtualFruit*createPear()=0;virtual~AbstractFactory(){}};/////////美国的具体工厂////////////////////////////////////////classUSAFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewUSAApple;}virtualFruit*createBanana(){returnnewUSABanana;}virtualFruit*createPear(){returnnewUSAPear;}};////中国的具体工厂///////////////////////////////////////classChinaFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewChinaApple;}virtualFruit*createBanana(){returnnewChinaBanana;}virtualFruit*createPear(){returnnewChinaPear;}};////日本的具体工厂///////////////////////////////////////classJapanFactory:publicAbstractFactory{public:virtualFruit*createApple(){returnnewJapanApple;}virtualFruit*createBanana(){returnnewJapanBanana;}virtualFruit*createPear(){returnnewJapanPear;}};intmain(){//想要一个美国的香蕉//1,来一个美国的工厂AbstractFactory*usaf=newUSAFactory;Fruit*usabanana=usaf->createBanana();usabanana->getName();deleteusaf;deleteusabanana;//想要一个中国的苹果//1,来一个中国的工厂AbstractFactory*chinaf=newChinaFactory;Fruit*chinaapple=chinaf->createApple();chinaapple->getName();deletechinaf;deletechinaapple;//想要一个Japan的pear//1,来一个Japan的工厂AbstractFactory*japanf=newJapanFactory;Fruit*japanpear=japanf->createPear();japanpear->getName();deletejapanf;deletejapanpear;return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out我是美国香蕉我是中国苹果我是Japanpearchunli@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:~$catmain.cpp#include<iostream>usingnamespacestd;/*抽象层*/classCPU{public:virtualvoidcaculate()=0;};classCard{public:virtualvoiddispaly()=0;};classMemory{public:virtualvoidstorage()=0;};/*抽象工厂*/classAbstractFactory{public:virtualCPU*createCPU()=0;virtualCard*createCard()=0;virtualMemory*createMem()=0;};/*抽象架构*/classComputer{public:Computer(CPU*cpu,Card*card,Memory*mem){this->cpu=cpu;this->card=card;this->mem=mem;}voidwork(){this->cpu->caculate();this->card->dispaly();this->mem->storage();}private:CPU*cpu;Card*card;Memory*mem;};/*------抽象完成--------*//*实现层*/classIntelCPU:publicCPU{public:virtualvoidcaculate(){cout<<"开始计算"<<endl;};};classIntelCard:publicCard{public:virtualvoiddispaly(){cout<<"开始显示"<<endl;};};classIntelMem:publicMemory{public:virtualvoidstorage(){cout<<"开始存储"<<endl;};};classIntelFactory:publicAbstractFactory{public:virtualCPU*createCPU(){returnnewIntelCPU;}virtualCard*createCard(){returnnewIntelCard;}virtualMemory*createMem(){returnnewIntelMem;}};intmain(){//组装一台电脑//创建一个Intel的工厂AbstractFactory*intelFactory=newIntelFactory;//父类指针指向子类对象CPU*intelCPU=intelFactory->createCPU();Card*intelCard=intelFactory->createCard();Memory*intelMem=intelFactory->createMem();Computer*com1=newComputer(intelCPU,intelCard,intelMem);com1->work();cout<<"-------------------------"<<endl;return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out开始计算开始显示开始存储-------------------------chunli@linux:~$


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

chunli@linux:~$catmain.cpp#include<iostream>usingnamespacestd;/*抽象层*/classCPU{public:virtualvoidcaculate()=0;};classCard{public:virtualvoiddispaly()=0;};classMemory{public:virtualvoidstorage()=0;};/*抽象工厂*/classAbstractFactory{public:virtualCPU*createCPU()=0;virtualCard*createCard()=0;virtualMemory*createMem()=0;};/*抽象架构*/classComputer{public:Computer(CPU*cpu,Card*card,Memory*mem){this->cpu=cpu;this->card=card;this->mem=mem;}voidwork(){this->cpu->caculate();this->card->dispaly();this->mem->storage();}private:CPU*cpu;Card*card;Memory*mem;};/*------抽象完成--------*//*实现层Intel厂商*/classIntelCPU:publicCPU{public:virtualvoidcaculate(){cout<<"Intelcpu开始计算"<<endl;};};classIntelCard:publicCard{public:virtualvoiddispaly(){cout<<"intelcard开始显示"<<endl;};};classIntelMem:publicMemory{public:virtualvoidstorage(){cout<<"intelmem开始存储"<<endl;};};classIntelFactory:publicAbstractFactory{public:virtualCPU*createCPU(){returnnewIntelCPU;}virtualCard*createCard(){returnnewIntelCard;}virtualMemory*createMem(){returnnewIntelMem;}};/*实现层英伟达厂商*/classNvidiaCPU:publicCPU{public:virtualvoidcaculate(){cout<<"Nvidiacpu开始计算"<<endl;};};classNvidiaCard:publicCard{public:virtualvoiddispaly(){cout<<"Nvidiacard开始显示"<<endl;};};classNvidiaMem:publicMemory{public:virtualvoidstorage(){cout<<"Nvidiamem开始存储"<<endl;};};classNvidiaFactory:publicAbstractFactory{public:virtualCPU*createCPU(){returnnewNvidiaCPU;}virtualCard*createCard(){returnnewNvidiaCard;}virtualMemory*createMem(){returnnewNvidiaMem;}};/*实现层金士顿厂商*/classKingstonCPU:publicCPU{public:virtualvoidcaculate(){cout<<"Kingstoncpu开始计算"<<endl;};};classKingstonCard:publicCard{public:virtualvoiddispaly(){cout<<"Kingstoncard开始显示"<<endl;};};classKingstonMem:publicMemory{public:virtualvoidstorage(){cout<<"Kingstonmem开始存储"<<endl;};};classKingstonFactory:publicAbstractFactory{public:virtualCPU*createCPU(){returnnewKingstonCPU;}virtualCard*createCard(){returnnewKingstonCard;}virtualMemory*createMem(){returnnewKingstonMem;}};intmain(){//组装一台兼容机,要Intel的cpu,nvidia的card,kingston的memAbstractFactory*intelFactory=newIntelFactory;AbstractFactory*nvidiaFactory=newNvidiaFactory;AbstractFactory*kingstonFactory=newKingstonFactory;CPU*intelCPU=intelFactory->createCPU();Card*nvidiaCard=nvidiaFactory->createCard();Memory*kingstonlMem=kingstonFactory->createMem();Computer*computer=newComputer(intelCPU,nvidiaCard,kingstonlMem);computer->work();return0;}chunli@linux:~$g++main.cpp-Wall&&./a.outIntelcpu开始计算Nvidiacard开始显示Kingstonmem开始存储chunli@linux:~$



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





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


1,饿汉式

chunli@linux:~$catmain.cpp#include<iostream>usingnamespacestd;//三个要点://一是某个类只能有一个实例;//二是它必须自行创建这个实例;//三是它必须自行向整个系统提供这个实例。classSingleton{public:staticSingleton*getInstance(){returninstance;}private:Singleton(){}staticSingleton*instance;};//在编译期间,就已经确定这个唯一的实例了Singleton*Singleton::instance=newSingleton;//饿汉式intmain(){Singleton*s1=Singleton::getInstance();Singleton*s2=Singleton::getInstance();if(s1==s2){cout<<"s1==s2"<<endl;}else{cout<<"s1!=s2"<<endl;}return0;}chunli@linux:~$g++main.cpp-Wall&&./a.outs1==s2chunli@linux:~$


2,懒汉式

chunli@linux:~$catmain.cpp#include<iostream>usingnamespacestd;//三个要点://一是某个类只能有一个实例;//二是它必须自行创建这个实例;//三是它必须自行向整个系统提供这个实例。classSingleton{public:staticSingleton*getInstance(){if(instance==NULL)//懒汉式多线程危险{instance=newSingleton;}returninstance;}private:Singleton(){}staticSingleton*instance;};Singleton*Singleton::instance=NULL;//懒汉式intmain(){Singleton*s1=Singleton::getInstance();Singleton*s2=Singleton::getInstance();if(s1==s2){cout<<"s1==s2"<<endl;}else{cout<<"s1!=s2"<<endl;}return0;}chunli@linux:~$g++main.cpp-Wall&&./a.outs1==s2chunli@linux:~$


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

classSingleton{public:staticSingleton*getInstance(){//加锁if(instance==NULL)//懒汉式多线程危险{instance=newSingleton;}//解锁returninstance;}private:Singleton(){}staticSingleton*instance;};Singleton*Singleton::instance=NULL;//懒汉式


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

chunli@linux:~$catmain.cpp#include<iostream>usingnamespacestd;//三个要点://一是某个类只能有一个实例;//二是它必须自行创建这个实例;//三是它必须自行向整个系统提供这个实例。classPrinter{public:staticPrinter*getInstance(){if(instance==NULL)//懒汉式多线程危险{instance=newPrinter;}returninstance;}voidprintf(stringtext){sequence++;cout<<sequence<<"打印的内容是"<<text<<endl;}staticintgetCount()//返回已经打印了多少次{returnsequence;}private:classGarbo//单例的垃圾回收机制{public:~Garbo(){if(instance!=NULL){cout<<"开始析构instance"<<endl;deleteinstance;}}};private:Printer(){}staticintsequence;//记录打印机已经打印了多少条数据staticPrinter*instance;staticGarbogarbo;//在静态区开辟空间,程序运行结束时,释放instance};Printer*Printer::instance=NULL;//懒汉式intPrinter::sequence=0;Printer::GarboPrinter::garbo;intmain(){Printer*p1=Printer::getInstance();p1->printf("我的简历.doc");Printer*p2=Printer::getInstance();p2->printf("LOL皮肤.jpg");Printer*p3=Printer::getInstance();p3->printf("离职简历.doc");return0;}chunli@linux:~$g++main.cpp-Wall&&./a.out1打印的内容是我的简历.doc2打印的内容是LOL皮肤.jpg3打印的内容是离职简历.doc开始析构instancechunli@linux:~$