C++ 工厂模式 分析和总结
简介
用一个单独的类来做创建实例的过程,是工厂;用工厂方法代替new操作的一种模式;工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象。
分类
简单工厂模式、工厂方法模式、抽象工厂模式
为什么要使用工厂模式?
- 程序更规范有条理,当我们创建实例对象时,如果不仅仅做赋值这样简单的事情,而是有一大段逻辑,那这个时候我们要将所有的初始化逻辑都写在构造函数中吗? 显然,这样使得代码很难看;
- 降低耦合度,提高可阅读性。面向对象的基本思想封装告诉我们,我们尽量将长的代码进行"切割",再将每一个小逻辑都"封装"起来,这样可以降低耦合度,修改的时候也可以直奔错误段落。
1)简单工厂模式
简介
简单工厂模式是属于创建型模式,又叫做静态工厂方法(static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出来哪一种产品类的实例。
特点
是由一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类继承自一个父类或接口)的实例;
需要在工厂类中作出判断,在创建产品的时候,指定响应产品创造。
举个例子:
假设有一个工厂,他能生产出A、B两种产品。当客户需要产品的时候一定要告诉共产是哪种产品,是A还是B。当新增加一种新产品的时候,那么就要去修改工厂的类。
应用说明:
一个工厂,多个产品。产品需要有一个虚基类。通过传入参数,生成具体产品对象,并利用基类指针指向此对象。
程序案例:
#include "stdafx.h" #include <iostream> using namespace std; //类方法—生产的产品 class Product { public: virtual void show()=0; } class Product_A :public Product //产品A { public: void show() { cout<<"Product_A"<<endl; } }; class Product_B : public Product //产品B { public: void show() { cout<<"Product_B"<<endl; } }; //工厂 class Factory //只有一家工厂,可以生产不同的产品 { public: Product* Create(int i) { switch(i) { case 1: //生产产品A return new Prodent_A; break; case 2: //生产产品B return new Product_B; break; default: break; } } }; int main() { Factory *factoty = new Factory(); //实例化--工厂对象 factoty->Create(1)->show(); //指定生产A产品 factoty->Create(2)->show(); //指定生产B产品 system("pause"); return 0; }
缺点:
每次新增一个类时,都需要改变工厂函数,破坏了封装性;(如果生产厂家需要新增一个产品,那么工厂函数Factory就需要跟着改变,所以上面的工厂模式违背了开放封闭原则;)
补:开放封闭原则:软件实体(类、模块、函数)可以扩展,但是不可修改。
2)工厂方法模式
简介
多个工厂,多个产品,每个产品对应于一个工厂。此时工厂和产品都是通过虚基类的方式构建。
特点
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
当增加一个新产品时,同时增加一个新工厂。增加新工厂属于扩展,不会修改以前工厂类和产品类的任何代码。可以看过多个独立的简单工厂模式构成了工厂方法模式。
举个例子:
假设现在有A、B两种产品,那么久开两个工厂。工厂A负责生产A产品,工厂B负责生产B种产品。这时候客户不需要告诉共产生产哪种产品了,只需要告诉共产生产就可以了。
应用说明:
把简单工厂模式中的工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。
程序案例:
#include "stdafx.h" #include<iostream> using namespace std; //类方法—生产的产品 class Product { public: virtual void show() = 0; }; class Product_A : public Product //产品A { public: void show() { cout << "Product_A" << endl; } }; class Product_B : public Product //产品B { public: void show() { cout << "Product_B" << endl; } }; class Factory //工厂 { public: virtual Product* create() = 0; }; class Factory_A : public Factory //工厂A 只有一个函数方法(产品) { public: Product* create() { return new Product_A; } }; class Factory_B : public Factory //工厂B 只有一个函数方法(产品) { public: Product* create() { return new Product_B; } }; int main() { Factory_A* productA = new Factory_A(); //实例化--工厂对象A Factory_B* productB = new Factory_B(); //实例化--工厂对象B productA->create()->show(); //工厂A 调用函数(生产产品) productB->create()->show(); //工厂B 调用函数(生产产品) system("pause"); return 0; }
缺点:
每增加一个新的产品,就需要增加一个新的工厂
3)抽象工厂模式
简介
多个工厂,多个产品,并且每个产品可以包含多个型号。此时工厂和产品都是通过虚基类的方式构建。每一个工厂类可以生产同一个产品的多个型号。
特点
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
举个例子:
例1)假如我们A产品中有A1和A2两种型号的厂品,B产品中有B1和B2两种型号的厂品,那怎么办,上面两种工厂模式就不能解决了。这个时候抽象工厂模式就登场了。还是开设两家工厂,工厂A负责生产A1 、A2型号产品,B工厂负责生产B1、B2型号的产品。
例2)假设一种情况,在的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
应用说明:
#include <iostream> using namespace std; //定义抽象类 class product1 { public: virtual void show() = 0; }; //定义具体类 class product_A1 :public product1 { public: void show(){ cout << "product A1" << endl; } }; class product_B1 :public product1 { public: void show(){ cout << "product B1" << endl; } }; //定义抽象类 class product2 { public: virtual void show() = 0; }; //定义具体类 class product_A2 :public product2 { public: void show(){ cout << "product A2" << endl; } }; class product_B2 :public product2 { public: void show(){ cout << "product B2" << endl; } }; class Factory //工厂 { public: virtual product1 *creat1() = 0; virtual product2 *creat2() = 0; }; class FactoryA //工厂A 可以有多个函数方法(产品) { public: product1 *creat1(){ return new product_A1(); } product2 *creat2(){ return new product_A2(); } }; class FactoryB //工厂B 可以有多个函数方法(产品) { public: product1 *creat1(){ return new product_B1(); } product2 *creat2(){ return new product_B2(); } }; int main() { FactoryA *factoryA = new FactoryA(); //实例化--工厂对象A factoryA->creat1()->show(); //工厂A 调用函数(生产产品1) factoryA->creat2()->show(); //工厂A 调用函数(生产产品2) FactoryB *factoryB = new FactoryB(); //实例化--工厂对象B factoryB->creat1()->show(); //工厂B 调用函数(生产产品1) factoryB->creat2()->show(); //工厂B 调用函数(生产产品2) return 0; }
优点:
易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这样就使得改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可使用不同的产品配置。
让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂实现分离,不会出现在客户代码中。
缺点:
增加新的产品时需要改动多处代码。
希望你对有帮助;
如发现有错误的,欢迎指正。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
首届 Apache Spark AI智能诊断大赛重磅来袭!
Spark“数字人体”AI挑战赛——脊柱疾病智能诊断大赛介绍 首届 Apache Spark AI智能诊断大赛由阿里云、Intel、Databricks 共同举办。Spark“数字人体”AI挑战赛——脊柱疾病智能诊断大赛,召集全球开发者利用人工智能技术探索高效准确的脊柱退化性疾病自动诊断,并积极推动相关技术的临床应用。本次比赛尤其鼓励企业参赛,代表企业参赛并进入第二赛季的队伍,将有机会成为阿里云医疗行业合作伙伴。 本次大赛分为第一赛季、第二赛季、决赛三个阶段, 进入第二赛季的队伍将会被要求选择赛道,结合选手初赛排名情况和意向,选手将会被分配分别到GPU赛道和CPU赛道。 报名及实名认证(2020年5月20日-7月17日)第一赛季(2020年6月10日-7月17日,UTC+8)第二赛季(2020年7月20日-8月30日,UTC+8)
- 下一篇
Python之路---初识函数
Python之路---初识函数 程序员三大美德: 懒惰因为一直致力于减少工作的总工作量。 缺乏耐性因为一旦让你去做本该计算机完成的事,你将会怒不可遏。 傲慢因为被荣誉感冲晕头的你会把程序写得让谁都挑不出毛病来。 大家好😄, 现在让我们一起来学习一下函数 🎉 1|1Why-为什么要使用函数? 现在我们需要计算一个字符串的长度,我们可以直接使用len()方法: num = len('hello') 但是如果我们不用len方法,怎么实现这个需求?其实也不难: s = 'hello' length = 0 for i in s: length += 1 print(length) 好了,功能实现了,然后又有一个需求(产品经理日常加需求),要计算另一个字符串的长度---“world”。 于是,本着程序员三大美德,😏我们使用最强大的快捷键---Ctrl+c , Ctrl+v: s1 = 'world' length = 0 for i in s1: length += 1 print(length) 这样确实可以实现需求,但是总感觉不是那么完美,为什么呢? 首先,之前我只需要执行len方法就...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Hadoop3单机部署,实现最简伪集群
- Docker安装Oracle12C,快速搭建Oracle学习环境