25、【C++基础】工厂模式

C++的工厂模式分为三种:简单工厂模式、工厂模式和抽象工厂模式

简单工厂模式

简单工厂模式是工厂模式中最简单的一种,他可以用比较简单的方式隐藏创建对象的细节,一般只需要告诉工厂类所需要的类型,工厂类就会返回需要的产品类,但客户端看到的只是产品的抽象对象,无需关心到底是返回了哪个子类。客户端唯一需要知道的具体子类就是工厂子类。除了这点,基本是达到了依赖倒转原则的要求。

假如,我们不用工厂类,只用AbstractProduct和它的子类,那客户端每次使用不同的子类的时候都需要知道到底是用哪一个子类,当类比较少的时候还没什么问题,但是当类比较多的时候,管理起来就非常的麻烦了,就必须要做大量的替换,一个不小心就会发生错误。

而使用了工厂类之后,就不会有这样的问题,不管里面多少个类,我只需要知道类型号即可。不过,这里还有一个疑问,那就是如果我每次用工厂类创建的类型都不相同,这样修改起来的时候还是会出现问题,还是需要大量的替换。所以简单工厂模式一般应该于程序中大部分地方都只使用其中一种产品,工厂类也不用频繁创建产品类的情况。这样修改的时候只需要修改有限的几个地方即可。

常用的场景

例如部署多种数据库的情况,可能在不同的地方要使用不同的数据库,此时只需要在配置文件中设定数据库的类型,每次再根据类型生成实例,这样,不管下面的数据库类型怎么变化,在客户端看来都是只有一个AbstractProduct,使用的时候根本无需修改代码。提供的类型也可以用比较便于识别的字符串,这样不用记很长的类名,还可以保存为配置文件。

这样,每次只需要修改配置文件和添加新的产品子类即可。

所以简单工厂模式一般应用于多种同类型类的情况,将这些类隐藏起来,再提供统一的接口,便于维护和修改。

优点

  1.隐藏了对象创建的细节,将产品的实例化推迟到子类中实现。

  2.客户端基本不用关心使用的是哪个产品,只需要知道用哪个工厂就行了,提供的类型也可以用比较便于识别的字符串。

  3.方便添加新的产品子类,每次只需要修改工厂类传递的类型值就行了。

  4.遵循了依赖倒转原则。

缺点

  1.要求产品子类的类型差不多,使用的方法名都相同,如果类比较多,而所有的类又必须要添加一种方法,则会是非常麻烦的事情。或者是一种类另一种类有几种方法不相同,客户端无法知道是哪一个产品子类,也就无法调用这几个不相同的方法。

  2.每添加一个产品子类,都必须在工厂类中添加一个判断分支,这违背了开放-封闭原则。

【示例】

AbstractProduct.h

 1 #ifndef _ABSTRACTPRODUCT_H_
 2 #define _ABSTRACTPRODUCT_H_
 3
 4
 5 #include <stdio.h>
 6
 7
 8 class AbstractProduct{
 9
10 public:
11     AbstractProduct();
12     virtual ~AbstractProduct();
13
14 public:
15     virtual void operation() = 0;
16 };
17
18 class ProductA:public AbstractProduct{
19
20 public:
21     ProductA();
22     virtual ~ProductA();
23
24 public:
25     void operation();
26 };
27
28 class ProductB:public AbstractProduct{
29
30 public:
31     ProductB();
32     ~ProductB();
33
34 public:
35     void operation();
36 };
37
38 #endif
39
40 AbstractProduct.h

AbstractProduct.cpp

 1 #include "AbstractProduct.h"
 2
 3
 4
 5 AbstractProduct::AbstractProduct(){
 6 }
 7
 8
 9 AbstractProduct::~AbstractProduct(){
10 }
11
12
13 ProductA::ProductA(){
14 }
15
16
17 ProductA::~ProductA(){
18 }
19
20
21 void ProductA::operation(){
22     fprintf(stderr,"productA operation!\n");
23 }
24
25
26 ProductB::ProductB(){
27 }
28
29
30 ProductB::~ProductB(){
31 }
32
33
34 void ProductB::operation(){
35     fprintf(stderr,"productB operation!\n");
36 }
37
38 AbstractProduct.cpp

SimpleFactory.h

 1 #ifndef _SIMPLEFACTORY_H_
 2 #define _SIMPLEFACTROY_H_
 3
 4 #include <stdio.h>
 5 #include "AbstractProduct.h"
 6
 7
 8 class AbstractFactory{
 9
10 public:
11     AbstractFactory();
12     virtual ~AbstractFactory();
13
14 public:
15     virtual AbstractProduct* createProduct(int type) = 0;
16 };
17
18
19 class SimpleFactory:public AbstractFactory{
20
21 public:
22     SimpleFactory();
23     ~SimpleFactory();
24
25 public:
26     AbstractProduct* createProduct(int type);
27 };
28
29 #endif
30
31 SimpleFactory.h

SimpleFactory.cpp

 1 #include "SimpleFactory.h"
 2
 3
 4 AbstractFactory::AbstractFactory(){
 5 }
 6
 7
 8 AbstractFactory::~AbstractFactory(){
 9 }
10
11
12 SimpleFactory::SimpleFactory(){
13 }
14
15
16 SimpleFactory::~SimpleFactory(){
17 }
18
19
20 AbstractProduct* SimpleFactory::createProduct(int type){
21     AbstractProduct* temp = NULL;
22     switch(type)
23     {
24     case 1:
25         temp = new ProductA();
26         break;
27     case 2:
28         temp = new ProductB();
29         break;
30     default:
31         break;
32     }
33     return temp;
34 }
35
36 SimpleFactory.cpp

client.cpp

 1 #include "SimpleFactory.h"
 2
 3
 4 int main(){
 5     AbstractFactory* factory = new SimpleFactory();
 6     AbstractProduct* product = factory->createProduct(1);
 7     product->operation();
 8     delete product;
 9     product = NULL;
10
11     product = factory->createProduct(2);
12     product->operation();
13     delete product;
14     product = NULL;
15     return 0;
16 }
17
18 client.cpp

执行结果:

productA operation!
productB operation!

工厂模式

工厂模式

工厂模式基本与简单工厂模式差不多,上面也说了,每次添加一个产品子类都必须在工厂类中添加一个判断分支,这样违背了开放-封闭原则,因此,工厂模式就是为了解决这个问题而产生的。

既然每次都要判断,那我就把这些判断都生成一个工厂子类,这样,每次添加产品子类的时候,只需再添加一个工厂子类就可以了。这样就完美的遵循了开放-封闭原则。但这其实也有问题,如果产品数量足够多,要维护的量就会增加,好在一般工厂子类只用来生成产品类,只要产品子类的名称不发生变化,那么基本工厂子类就不需要修改,每次只需要修改产品子类就可以了。

同样工厂模式一般应该于程序中大部分地方都只使用其中一种产品,工厂类也不用频繁创建产品类的情况。这样修改的时候只需要修改有限的几个地方即可。

常用的场景

基本与简单工厂模式一致,只不过是改进了简单工厂模式中的开放-封闭原则的缺陷,使得模式更具有弹性。将实例化的过程推迟到子类中,由子类来决定实例化哪个。

优点

基本与简单工厂模式一致,多的一点优点就是遵循了开放-封闭原则,使得模式的灵活性更强。

缺点

与简单工厂模式差不多。

AbstractProduct.h

 1 #ifndef _ABSTRACTPRODUCT_H_
 2 #define _ABSTRACTPRODUCT_H_
 3
 4
 5 #include <stdio.h>
 6
 7
 8 class AbstractProduct{
 9
10 public:
11     AbstractProduct();
12     virtual ~AbstractProduct();
13
14 public:
15     virtual void operation() = 0;
16 };
17
18 class ProductA:public AbstractProduct{
19
20 public:
21     ProductA();
22     virtual ~ProductA();
23
24 public:
25     void operation();
26 };
27
28 class ProductB:public AbstractProduct{
29
30 public:
31     ProductB();
32     ~ProductB();
33
34 public:
35     void operation();
36 };
37
38 #endif
39
40 AbstractProduct.h

AbstractProduct.cpp

 1 #include "AbstractProduct.h"
 2
 3
 4
 5 AbstractProduct::AbstractProduct(){
 6 }
 7
 8
 9 AbstractProduct::~AbstractProduct(){
10 }
11
12
13 ProductA::ProductA(){
14 }
15
16
17 ProductA::~ProductA(){
18 }
19
20
21 void ProductA::operation(){
22     fprintf(stderr,"productA operation!\n");
23 }
24
25
26 ProductB::ProductB(){
27 }
28
29
30 ProductB::~ProductB(){
31 }
32
33
34 void ProductB::operation(){
35     fprintf(stderr,"productB operation!\n");
36 }
37
38 AbstractProduct.cpp

AbstractFactory.h

 1 #ifndef _SIMPLEFACTORY_H_
 2 #define _SIMPLEFACTROY_H_
 3
 4 #include <stdio.h>
 5 #include "AbstractProduct.h"
 6
 7
 8 class AbstractFactory{
 9
10 public:
11     AbstractFactory();
12     virtual ~AbstractFactory();
13
14 public:
15     virtual AbstractProduct* createProduct() = 0;
16 };
17
18
19 class FactoryA:public AbstractFactory{
20
21 public:
22     FactoryA();
23     ~FactoryA();
24
25 public:
26     AbstractProduct* createProduct();
27 };
28
29
30 class FactoryB:public AbstractFactory{
31
32 public:
33     FactoryB();
34     ~FactoryB();
35
36 public:
37     AbstractProduct* createProduct();
38 };
39 #endif
40
41 AbstractFactory.h

AbstractFactory.cpp

 1 #include "AbstractFactory.h"
 2
 3
 4 AbstractFactory::AbstractFactory(){
 5 }
 6
 7
 8 AbstractFactory::~AbstractFactory(){
 9 }
10
11
12 FactoryA::FactoryA(){
13 }
14
15
16 FactoryA::~FactoryA(){
17 }
18
19
20 AbstractProduct* FactoryA::createProduct(){
21     AbstractProduct* temp = NULL;
22     temp = new ProductA();
23     return temp;
24 }
25
26
27 FactoryB::FactoryB(){
28 }
29
30
31 FactoryB::~FactoryB(){
32 }
33
34
35 AbstractProduct* FactoryB::createProduct(){
36     AbstractProduct* temp = NULL;
37     temp = new ProductB();
38     return temp;
39 }
40
41 AbstractFactory.cpp

client.cpp

 1 #include "AbstractFactory.h"
 2
 3
 4 int main(){
 5     AbstractFactory* factory = new FactoryA();
 6     AbstractProduct* product = factory->createProduct();
 7     product->operation();
 8     delete product;
 9     product = NULL;
10     delete factory;
11     factory = NULL;
12
13     factory = new FactoryB();
14     product = factory->createProduct();
15     product->operation();
16     delete product;
17     product = NULL;
18     delete factory;
19     factory = NULL;
20     return 0;
21 }
22
23 client.cpp

执行结果:

productA operation!
productB operation!

抽象工厂模式

抽象工厂模式就变得比工厂模式更为复杂,就像上面提到的缺点一样,工厂模式和简单工厂模式要求产品子类必须要是同一类型的,拥有共同的方法,这就限制了产品子类的扩展。于是为了更加方便的扩展,抽象工厂模式就将同一类的产品子类归为一类,让他们继承同一个抽象子类,我们可以把他们一起视作一组,然后好几组产品构成一族。

此时,客户端要使用时必须知道是哪一个工厂并且是哪一组的产品抽象类。每一个工厂子类负责产生一族产品,而子类的一种方法产生一种类型的产品。在客户端看来只有AbstractProductA和AbstractProductB两种产品,使用的时候也是直接使用这两种产品。而通过工厂来识别是属于哪一族产品。

产品ProductA_1和ProductB_1构成一族产品,对应于有Factory1来创建,也就是说Factory1总是创建的ProductA_1和ProductB_1的产品,在客户端看来只需要知道是哪一类工厂和产品组就可以了。一般来说, ProductA_1和ProductB_1都是适应同一种环境的,所以他们会被归为一族。

常用的场景

例如Linux和windows两种操作系统下,有2个挂件A和B,他们在Linux和Windows下面的实现方式不同,Factory1负责产生能在Linux下运行的挂件A和B,Factory2负责产生能在Windows下运行的挂件A和B,这样如果系统环境发生变化了,我们只需要修改工厂就行了。

优点

1.封装了产品的创建,使得不需要知道具体是哪种产品,只需要知道是哪个工厂就行了。

2.可以支持不同类型的产品,使得模式灵活性更强。

3.可以非常方便的使用一族中间的不同类型的产品。

缺点

1.结构太过臃肿,如果产品类型比较多,或者产品族类比较多,就会非常难于管理。

2.每次如果添加一组产品,那么所有的工厂类都必须添加一个方法,这样违背了开放-封闭原则。所以一般适用于产品组合产品族变化不大的情况。

【示例】

AbstractProductA.h

 1 #ifndef _ABSTRACTPRODUCTA_H_
 2 #define _ABSTRACTPRODUCTA_H_
 3
 4
 5 #include <stdio.h>
 6
 7
 8 class AbstractProductA{
 9
10 public:
11     AbstractProductA();
12     virtual ~AbstractProductA();
13
14 public:
15     virtual void operationA() = 0;
16 };
17
18 class ProductA_1:public AbstractProductA{
19
20 public:
21     ProductA_1();
22     virtual ~ProductA_1();
23
24 public:
25     void operationA();
26 };
27
28 class ProductA_2:public AbstractProductA{
29
30 public:
31     ProductA_2();
32     ~ProductA_2();
33
34 public:
35     void operationA();
36 };
37
38 #endif
39
40 AbstractProductA.h

AbstractProductA.cpp

 1 #include "AbstractProductA.h"
 2
 3
 4
 5 AbstractProductA::AbstractProductA(){
 6 }
 7
 8
 9 AbstractProductA::~AbstractProductA(){
10 }
11
12
13 ProductA_1::ProductA_1(){
14 }
15
16
17 ProductA_1::~ProductA_1(){
18 }
19
20
21 void ProductA_1::operationA(){
22     fprintf(stderr,"productA_1 operation!\n");
23 }
24
25
26 ProductA_2::ProductA_2(){
27 }
28
29
30 ProductA_2::~ProductA_2(){
31 }
32
33
34 void ProductA_2::operationA(){
35     fprintf(stderr,"productA_2 operation!\n");
36 }
37
38 AbstractProductA.cpp

AbstractProductB.h

 1 #ifndef _ABSTRACTPRODUCTB_H_
 2 #define _ABSTRACTPRODUCTB_H_
 3
 4
 5 #include <stdio.h>
 6
 7
 8 class AbstractProductB{
 9
10 public:
11     AbstractProductB();
12     virtual ~AbstractProductB();
13
14 public:
15     virtual void operationB() = 0;
16 };
17
18 class ProductB_1:public AbstractProductB{
19
20 public:
21     ProductB_1();
22     virtual ~ProductB_1();
23
24 public:
25     void operationB();
26 };
27
28 class ProductB_2:public AbstractProductB{
29
30 public:
31     ProductB_2();
32     ~ProductB_2();
33
34 public:
35     void operationB();
36 };
37
38 #endif
39
40 AbstractProductB.h

AbstractProductB.cpp

 1 #include "AbstractProductB.h"
 2
 3
 4
 5 AbstractProductB::AbstractProductB(){
 6 }
 7
 8
 9 AbstractProductB::~AbstractProductB(){
10 }
11
12
13 ProductB_1::ProductB_1(){
14 }
15
16
17 ProductB_1::~ProductB_1(){
18 }
19
20
21 void ProductB_1::operationB(){
22     fprintf(stderr,"productB_1 operation!\n");
23 }
24
25
26 ProductB_2::ProductB_2(){
27 }
28
29
30 ProductB_2::~ProductB_2(){
31 }
32
33
34 void ProductB_2::operationB(){
35     fprintf(stderr,"productB_2 operation!\n");
36 }
37
38 AbstractProductB.cpp

AbstractFactory.h

 1 #ifndef _SIMPLEFACTORY_H_
 2 #define _SIMPLEFACTROY_H_
 3
 4 #include <stdio.h>
 5 #include "AbstractProductA.h"
 6 #include "AbstractProductB.h"
 7
 8
 9 class AbstractFactory{
10
11 public:
12     AbstractFactory();
13     virtual ~AbstractFactory();
14
15 public:
16     virtual AbstractProductA* createProductA() = 0;
17     virtual AbstractProductB* createProductB() = 0;
18 };
19
20
21 class Factory1:public AbstractFactory{
22
23 public:
24     Factory1();
25     ~Factory1();
26
27 public:
28     AbstractProductA* createProductA();
29     AbstractProductB* createProductB();
30 };
31
32
33 class Factory2:public AbstractFactory{
34
35 public:
36     Factory2();
37     ~Factory2();
38
39 public:
40     AbstractProductA* createProductA();
41     AbstractProductB* createProductB();
42 };
43 #endif
44
45 AbstractFactory.h

AbstractFactory.cpp

 1 #include "AbstractFactory.h"
 2
 3
 4 AbstractFactory::AbstractFactory(){
 5 }
 6
 7
 8 AbstractFactory::~AbstractFactory(){
 9 }
10
11
12 Factory1::Factory1(){
13 }
14
15
16 Factory1::~Factory1(){
17 }
18
19
20 AbstractProductA* Factory1::createProductA(){
21     AbstractProductA* temp = NULL;
22     temp = new ProductA_1();
23     return temp;
24 }
25
26
27 AbstractProductB* Factory1::createProductB(){
28     AbstractProductB* temp = NULL;
29     temp = new ProductB_1();
30     return temp;
31 }
32
33
34 Factory2::Factory2(){
35 }
36
37
38 Factory2::~Factory2(){
39 }
40
41
42 AbstractProductA* Factory2::createProductA(){
43     AbstractProductA* temp = NULL;
44     temp = new ProductA_2();
45     return temp;
46 }
47
48
49 AbstractProductB* Factory2::createProductB(){
50     AbstractProductB* temp = NULL;
51     temp = new ProductB_2();
52     return temp;
53 }
54
55 AbstractFactory.cpp

client.cpp

 1 #include "AbstractFactory.h"
 2
 3
 4 int main(){
 5
 6     AbstractFactory* factory = new Factory1();
 7     AbstractProductA* productA = factory->createProductA();
 8     AbstractProductB* productB = factory->createProductB();
 9     productA->operationA();
10     productB->operationB();
11
12     delete factory;
13     factory = NULL;
14     delete productA;
15     productA = NULL;
16     delete productB;
17     productB = NULL;
18
19     factory = new Factory2();
20     productA = factory->createProductA();
21     productB = factory->createProductB();
22     productA->operationA();
23     productB->operationB();
24
25     delete factory;
26     factory = NULL;
27     delete productA;
28     productA = NULL;
29     delete productB;
30     productB = NULL;
31     return 0;
32 }
33
34 client.cpp

执行结果:

productA_1 operation!
productB_1 operation!
productA_2 operation!
productB_2 operation!

原文地址:https://www.cnblogs.com/Long-w/p/9676018.html

时间: 2024-08-02 05:45:27

25、【C++基础】工厂模式的相关文章

Java基础——工厂模式

通过学习,一句话概括Java工厂模式的特点--通过建立一个工厂来创建对象,不必关心构造对象实例能不能被实例化啊等诸多细节和复杂过程. 工厂模式呢?就像我们从劳动密集型社会转型到技术密集型社会.打个比方,从前要制造一个桌子,从上山选木头.砍木头.运木头,到设计桌子,制造桌子等细节问题都需要一个人去做好,由于付出的劳动成本极高和技术学成的时间等问题,一般一个木匠在创新方面有一定的局限性.后来,人们步入了工业时代,制造业的发展突飞猛进,另外,倡导分工细化.比如,电脑的制造厂商,它懂得怎样装好一部电脑和

JAVA基础--工厂模式

interface Fruit{ // 定义一个水果接口 public void eat() ; // 吃水果 } class Apple implements Fruit{ public void eat(){ System.out.println("** 吃苹果.") ; } }; class Orange implements Fruit{ public void eat(){ System.out.println("** 吃橘子.") ; } }; clas

从基础知识到重写Spring的Bean工厂中学习java的工厂模式

1.静态工厂模式其他对象不能直接通过new得到某个类,而是通过调用getInstance()方法得到该类的对象这样,就可以控制类的产生过程.顺带提一下单例模式和多例模式:  单例模式是指控制其他对象获得该对象永远只有同一个对象  而多例模式则是根据需要从某个具体集合中获取所需的对象 1 import java.util.ArrayList; 2 import java.util.List; 3 4 5 public class Car implements Moveable{ 6 private

PHP 设计模式 笔记与总结(6)基础设计模式:工厂模式、单例模式和注册树模式

三种基础设计模式(所有面向对象设计模式中最常见的三种): ① 工厂模式:使用工厂方法或者类生成对象,而不是在代码中直接new 在 Common 目录下新建 Factory.php: <?php namespace Common; class Factory{ static function createDatabase(){ //$db = new \Common\Database; $db = new Database; return $db; } } index.php: <?php de

面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式

什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下来将为大家讲解在JS中面向对象的实现. 工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,而由于在ECMAScript中无法创建类,因此用函数封装以特定接口创建对象.其实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可. function createBlog(

php基础---单例模式&amp;&amp;工厂模式

//PHP设计模式 //工厂模式:工厂类 用于创建对象 interface Dongwu { function say(); } class Mao implements Dongwu { public function say() { echo "喵喵!我是一只小野猫!"; } } //工厂类,用来创建猫类 class GongChang { public static function GetObj($className) { return new $className(); }

【幻化万千戏红尘】qianfengDay10-java基础学习:成员内部类、静态内部类、局部和匿名内部类,设计模式之简单工厂模式

课程回顾: 接口:1.属性:public\static\final2.方法:public\abstract 多态:1.静态化(编译时)多态重载2.动态化(运行时)多态重写对象转型 1.向上转型 2.向下转型 今日内容:内部类:定义在类的内部的类1.成员内部类格式:[修饰符] class 类名 { }内部不能有静态的属性和方法,可以访问外部类的属性,也可以调用外部类的方法 在静态方法中的使用格式:外部类 外对象=new 外部类();成员内部类 对象名=外对象.new 成员内部类(); 2.静态内部

C#基础之简单工厂模式和单例模式

设计模式(Design pattern):指的是一种大多数人反复使用的代码设计经验. 作用:代码复用.易读性.保证代码可靠性. 一.简单工厂模式 用法:创建一个工厂类(命名习惯以Factiory结尾),一个静态的带参数(根据不同的参数返回不同的子类对象)的父类类型的方法. public class FunctionFactory { public static FatherClass Function(string str) { FatherClass fc = null; ... return

JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模)

什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下来将为大家讲解在JS中面向对象的实现.   工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,而由于在ECMAScript中无法创建类,因此用函数封装以特定接口创建对象.其实现方法非常简单,也就是在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可. ? 1 2 3 4 5 6 7 8