设计模式3 创建型模型
目录: 简单工厂模式 工厂方法模式 抽象工厂模式 单例模式
简单工厂 模型
chunli@linux:~$ cat main.cpp //设计模式:简单工厂 模型 #includeusing 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 //设计模式:简单工厂 实现 #includeusing 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,客户端只知道传入工厂类的参数,对于如何创建对象并不关心.
=========================================
工厂方法模式,
看图[工厂方法模式的案例]
chunli@linux:~$ cat main.cpp //工厂模式 //符合开闭原则,添加一个产品不用修改其他的代码 //简单工厂模式 + "开闭原则" = 工厂方法模式 #includeusing 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. 抽象工厂类通过其子类来指定创建哪个对象。
==========================================
抽象工厂模式:
看图:[抽象工厂模式]
chunli@linux:~$ cat main.cpp //抽象工厂方法 模式 #includeusing 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 //抽象工厂方法 模式 #includeusing 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 //抽象工厂方法 模式 #includeusing 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 #includeusing 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 #includeusing 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 #includeusing 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 #includeusing 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 #includeusing 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:~$