工厂模式

  • 前言
    • 为什么要使用工厂模式
    • 优点
    • 缺点
  • 简单工厂(Simple Factory)
    • 代码
    • 应用
    • 不足
  • 工厂方法(Factory Method)
    • 代码
    • 应用
    • 不足
  • 抽象工厂(Abstract Factory)
    • 代码
    • 应用
  • 参考资料

前言

为什么要使用工厂模式

主要是对对象的创建进行了一个封装;
因此也属于创建型模式。

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

主要解决:主要解决接口选择的问题。

优点

  1. 一个调用者想创建一个对象,只要知道其名称就可以了;
  2. 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以;
  3. 屏蔽产品的具体实现,调用者只关心产品的接口。

缺点

每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

简单工厂(Simple Factory)

代码

首先是具体产品的实现继承关系

// 系列产品
class Car
{public:Car(string name) :_name(name) {}virtual void show() = 0;
protected:string _name;
};
class Bmw:public Car
{public:Bmw(string name) :Car(name) {}void show(){cout << "获取了一辆宝马汽车:" << _name << endl;}
};
class Audi :public Car
{public:Audi(string name) :Car(name) {}void show(){cout << "获取了一辆奥迪汽车:" << _name << endl;}
};

接下来是简单工厂的实现:

// 产品枚举
enum Cartype
{BMW, AUDI
};
// 简单工厂类
class SimpleFactory
{public:// 用户想要创建一个对象,只需要知道名称就可以了Car* createCar(Cartype ct){switch (ct){case BMW:return new Bmw("x6");case AUDI:return new Audi("a8");default:cerr << "传入参数错误:" << ct << endl;}return nullptr;}
};

应用

具体的使用规则如下:

int main()
{unique_ptr<SimpleFactory> fac(new SimpleFactory());unique_ptr<Car> p1(fac->createCar(BMW));unique_ptr<Car> p2(fac->createCar(AUDI));p1->show();p2->show();return 0;
}

需要注意的是:
为了更好地释放资源,这里使用了智能指针(需要加入头文件#include <memory>);
也可以直接使用new的方法,代码如下:

 SimpleFactory* fac = new SimpleFactory();Car* p1 = fac->createCar(BMW);Car* p2 = fac->createCar(AUDI);p1->show();p2->show();delete fac;delete p1;delete p2;

使用普通指针(new)的时候就需要注意一定记得delete

我们来看运行的结果:

不足

可以看到,简单工厂可以做到,让用户创建对象的时候只需要知道对象的名称(BMWAUDI)就好,而不需要关心创建对象的细节(BMW是如何建造的、型号是什么等等细节)。

当然缺点也很明显:
每当我们想要扩展对象的时候(增加BENZ的对象)就需要在SimpleFactory类中添加代码,增加switch后面的case选项。这样一来,就需要修改源代码。灵活性非常的差!!!

那么,能不能做到添加对象的时候,不对现有代码进行修改呢?(也就是我们开发软件时候需要遵守的开-闭原则)

tips:
什么是开-闭原则呢?
扩展开放、对修改关闭;
也就是说,我们可以添加代码,但是添加代码的时候不能够对现有的代码进行修改。
这样的代码才能算是好代码!!!

于是乎,便有了 工厂方法

工厂方法(Factory Method)

工厂方法的思想就是定义一个Factory基类,基类中定义了一个纯虚函数(创建产品);
之后定义派生类(具体产品的工厂)负责创建对应的产品。
可以做到不同的产品在不同的工厂里面创建,能够对现有工厂以及产品的修改关闭

代码

同样的,具体产品的实现和继承同上:

// 系列产品
class Car
{public:Car(string name) :_name(name) {}virtual void show() = 0;
protected:string _name;
};
class Bmw:public Car
{public:Bmw(string name) :Car(name) {}void show(){cout << "获取了一辆宝马汽车:" << _name << endl;}
};
class Audi :public Car
{public:Audi(string name) :Car(name) {}void show(){cout << "获取了一辆奥迪汽车:" << _name << endl;}
};

接下来是工厂方法的实现:

// 基类(包含纯虚函数,不能实例化对象)
class Factory
{public:virtual Car* createCar(string name) = 0;
};
// 宝马汽车工厂,负责生产宝马汽车
class BmwFac: public Factory
{public:Car* createCar(string name){return new Bmw(name);}
};
// 奥迪汽车工厂,负责生产奥迪汽车
class AudiFac :public Factory
{public:Car* createCar(string name){return new Audi(name);}
};

应用

同样的,使用规则如下:

int main()
{unique_ptr<Factory> bmwfty(new BmwFac());unique_ptr<Factory> audifty(new AudiFac());unique_ptr<Car> p1 (bmwfty->createCar("X6"));unique_ptr<Car> p2 (audifty->createCar("A8"));p1->show();p2->show();return 0;
}

注意:
可以看到这一次的代码和之前简单工厂的不同:
简单工厂unique_ptr<SimpleFactory> fac(new SimpleFactory())
工厂方法unique_ptr<Factory> bmwfty(new BmwFac())
也就是说,工厂方法是用基类指针实例化派生类对象,这也是动态多态发生的条件。这样的话,就能够实现多态了!

之后的unique_ptr<Car> p1 (bmwfty->createCar("X6"))有没有更贴近生活呢?
我去买车,进到一家宝马4S店(对应具体的bmwfty对象),然后看上了心仪的车型bmw X6,然后告诉店员:“我想要一辆宝马X6”。之后办理完手续,就可以开心地提车了!

运行结果如下:

不足

工厂方法解决了简单工厂的问题(无法对修改关闭),但是它也有自己的局限:
试想一下,宝马工厂里面只是售卖成品汽车吗?
应该不是吧,作为一家成熟的工厂,除了汽车之外,还有一系列配套的零件产品:比如说:轮胎车灯真皮豪华座椅等等。也就是说,跟汽车相关联的有一整个产品簇。

但是我们的宝马工厂BmwFac里面只有一个createCar方法,如果想要添加产品的话,就需要增加新的类。但是这些产品其实都应该在一个BmwFac工厂里面。这才是现实的逻辑,另外,工厂类太多,会不好维护。

于是乎,抽象工厂 应运而生。

抽象工厂(Abstract Factory)

抽象工厂的思想是:
把有关联关系的,属于一个产品簇的所有产品创建的接口函数,放在一个抽象工厂里面AbstractFactory,派生类(具体产品的工厂)应该负责创建该产品簇里面所有的产品。

代码

这一次,除了汽车产品外,我们再添加一个车灯产品,系列产品的实现和继承关系代码如下:

// 系列产品1:汽车
class Car
{public:Car(string name) :_name(name) {}virtual void show() = 0;
protected:string _name;
};
class Bmw:public Car
{public:Bmw(string name) :Car(name) {}void show(){cout << "获取了一辆宝马汽车:" << _name << endl;}
};
class Audi :public Car
{public:Audi(string name) :Car(name) {}void show(){cout << "获取了一辆奥迪汽车:" << _name << endl;}
};
// 系列产品2:车灯
class Light
{public:virtual void show() = 0;
};
class BmwLight : public Light
{public:void show() { cout << "BMW light!" << endl; }
};
class AudiLight : public Light
{public:void show() { cout << "Audi light!" << endl; }
};

接下来是抽象工厂的实现:

// 工厂方法 => 抽象工厂(对有一组关联关系的产品簇提供产品对象的统一创建)
class AbstractFactory
{public:virtual Car* createCar(string name) = 0; // 工厂方法 创建汽车virtual Light* createCarLight() = 0; // 工厂方法 创建汽车关联的产品,车灯
};
// 宝马工厂
class BMWFactory : public AbstractFactory
{public:Car* createCar(string name){return new Bmw(name);}Light* createCarLight(){return new BmwLight();}
};
// 奥迪工厂
class AudiFactory : public AbstractFactory
{public:Car* createCar(string name){return new Audi(name);}Light* createCarLight(){return new AudiLight();}
};

应用

对于抽象工厂的使用如下:

int main()
{unique_ptr<AbstractFactory> bmwfty(new BMWFactory());unique_ptr<AbstractFactory> audifty(new AudiFactory());unique_ptr<Car> p1(bmwfty->createCar("X6"));unique_ptr<Car> p2(audifty->createCar("A8"));unique_ptr<Light> l1(bmwfty->createCarLight());unique_ptr<Light> l2(audifty->createCarLight());p1->show();l1->show();p2->show();l2->show();return 0;
}

运行结果如下:

参考资料

【1】工厂模式|菜鸟教程

C++工厂模式(简单工厂、工厂方法、抽象工厂)相关推荐

  1. 工厂模式详解(简单工厂模式,工厂方法模式,抽象工厂模式,只给出抽象工厂模式具体代码)

    1.简单工厂模式(Factory) 应用场景:又叫做静态工厂方法(StaticFactory Method)模式,但不属于 23 种设计模式之一.简单工厂模式的实质是由一个工厂类根据传入的参数,动态决 ...

  2. 抽象工厂模式(三):抽象工厂模式概述

    3 抽象工厂模式概述 抽象工厂模式为创建一组对象提供了一种解决方案.与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品.抽象工厂模式定义如下:        抽象工厂模 ...

  3. 【怎样写代码】工厂三兄弟之抽象工厂模式(四):抽象工厂模式

    如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...

  4. 工厂模式(简单工厂 工厂方法 抽象工厂)

    简单工厂模式 简单工厂模式又叫做静态工厂方法模式(static Factory Method pattern),它是通过使用静态方法接收不同的参数来返回不同的实例对象(这些产品类继承自一个父类或接口) ...

  5. 创建型模式:工厂模式(简单工厂+工厂方法+抽象工厂)

    一.引子 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说"开奔驰车!& ...

  6. java 三种工厂模式(简单工厂+工厂方法+抽象工厂)

    一.简单工厂模式 概述   简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同类的 实例,被创建的实例通常都具有共同的父类.因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因 ...

  7. 最简单java设计模式:抽象工厂模式

    前言 在前一篇文章讲解了一下简单工厂模式和工厂方法模式,这篇文章再把抽象工厂模式讲解一下. 一.什么是抽象工厂模式 抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的.抽象工厂模式可以向客户端提 ...

  8. java 抽象工厂模式简单实例

    抽象工厂模式:提供一个创建一系列的相关的或者依赖的对象的接口,无需指定它们的具体实现类,具体的时间分别在子类工厂中产生. 类似于工厂模式:隔离了具体类的生产实现,使得替换具体的工厂实现类很容易.包含有 ...

  9. 工厂模式,简单工厂模式,抽象工厂模式三者有什么区别

    工厂模式,也叫做说虚构造器,在简单工厂中间插入了一个具体产品工厂,这个工厂知道产品构造时候的具体细节,而简单工厂模式的产品具体构造细节是在一个个if/else分支,或者在switch/case分支里面 ...

  10. 工厂模式--简单工厂模式--抽象工厂模式

    工厂模式 作用:实现创建者与调用者的分离 简单工厂模式.工厂方法模式.抽象工厂模式,都是属于创建型设计模式.严格上来说,简单工厂模式不属于23设计模式之一,因为它违背了开闭原则. ========== ...

最新文章

  1. Xargs用法详解(原创)
  2. mysql 禁用查询缓存 query cache
  3. SpringBoot 全局异常处理
  4. 命令python所在的驱动器和文件夹_Python读取不同本地驱动器位置的文件
  5. 雷林鹏分享:XML 编码
  6. 数据结构-Hash总结(二)
  7. php 访问url获得返回值,如何在curl php请求中获取数组值作为返回值?
  8. 自动操作电脑的软件_技术干货 | 自动透镜植入定位仪
  9. DXUT框架剖析(1)
  10. Linux文件类型与文件权限详解(三)
  11. 蓝鲸ERP标准版-进销存-采购管理子系统操作说明1
  12. 广告视频投放展示平台 springboot+vue
  13. OpenCL中kernel的循环调用
  14. 转发文章【我们是怎样一步步的走向平庸的】
  15. This'is wath!
  16. python 保存图片
  17. jquery发送Ajax请求预处理和后置处理
  18. App首屏接口性能优化
  19. 通过两个小例子,更快了解-Xms -Xmx
  20. Tcp连接时三次握手的问题和思考

热门文章

  1. bzoj3529: [Sdoi2014]数表
  2. 大一暑假实习day4
  3. 微电子学与计算机 投稿格式,微电子学与计算机杂志投稿须知,编辑部最新刊期投稿格式...
  4. 现代控制理论-秩判据和PBH判据
  5. 傅盛谈AI场景化:猎户星空远场语音识别采用率业内第一
  6. generic泛型c语言编程,_Generic关键字及其语法和应用(C11标准),C语言_Generic详解...
  7. 魔兽争霸助手(改键+显血)v1.1--屏蔽power键
  8. Quested V2108录音室监听音箱评测
  9. 银行ATM系统——活动图及文档
  10. 【VMware vSAN 7.0】6.13 将双节点集群分配给共享见证主机—我们有软硬件解决方案