文章目录

  • 1. 解决问题
  • 2. 应用场景
  • 3. 实现
    • C++实现:
    • C语言实现
  • 4. 缺点
1. 解决问题

举例如下:

我们实现一个卖衣服的功能,衣服的种类有很多:帽子,裤子,T恤。。。 每卖一种衣服,我们都要进行一次实例化,通过new/malloc申请空间,会有如下两种问题:

  1. new /malloc之后往往需要跟随一堆异常处理代码,当衣服种类越来越多,我们的代码会显得异常臃肿。
  2. 当新的服务员来到商店,他想要卖衣服,但是不知道买衣服的流程(从哪个仓库取出来?进行什么样的加工。。。。)

此时,简单工厂就能解决这样的问题

  1. 简单工厂模式将 new/malloc以及一些衣服的加工操作 进行封装,并不会暴露给外界,将对象的创建和使用完全分离。
  2. 新来的同事不需要知道 卖衣服的具体流程,直接调用生产函数拿到衣服的对象,直接卖就可以。

总之,建立对象的类就像加工一个产品,使用产品的人不需要知道我的产品怎么加工的,只需要使用工厂生成产品,直接用即可。从软件开发角度来说,工厂模式降低了模块之间的耦合度。

2. 应用场景
  1. 针对需要大量实例化对象的类 的设计
  2. 逻辑处理是简单单一的场景
3. 实现

维护一个工厂类,专门负责创建不同的产品,创建产品的内容由工厂自己决定。

C++实现:

实现功能:简单工厂模式 创建不同种类的衣服,直接售卖,而不需要关心衣服的创建 销毁逻辑。

#include <iostream>using namespace std;/*工厂的可以制造的衣服种类*/
enum ClothType{hat,paths};class Cloth{public:virtual void createCloth(void) = 0;virtual ~Cloth(){} //定义为虚函数,对象空间回收时则会调用子类的析构含糊是
};/*帽子类*/
class Hat: public Cloth{public:Hat(){cout << "Hat::hat()" << endl;}virtual void createCloth(void) {cout << "Hat::createHat()" << endl;}~Hat(){cout << "Hat::delete()" << endl;}
};/*裤子类*/
class Paths: public Cloth{public:Paths(){cout << "Paths::paths()" << endl;}virtual void createCloth(void) {cout << "Paths::createPaths()" << endl;}~Paths(){cout << "Paths::delete()" << endl;}
};/*工厂类,负责不同的衣服的生产*/
class clothFactory { public:Cloth * createSpecificCloth(ClothType type) {switch(type){case hat:return (new Hat());case paths:return (new Paths());default:return NULL;}}
};int main()
{clothFactory cloFac;Cloth *clothA = cloFac.createSpecificCloth(hat);//制造帽子Cloth *clothB = cloFac.createSpecificCloth(paths);//制造裤子clothA -> createCloth();clothB -> createCloth();delete clothA;delete clothB;return 0;
}

编译运行输出如下:

Hat::hat()
Hat::createHat()
Paths::paths()
Paths::createPaths()
Hat::delete()
Paths::delete()
C语言实现

实现功能:和C++实现的功能一样,通过简单工厂封装衣服的创建逻辑,通过工厂创建出指定的衣服对象,直接使用。

实现逻辑:函数指针

retval.h 规范返回值,以及free逻辑

#include <stdio.h>
#include <stdlib.h>#define return_if_fail(p)\if(!(p)){\printf("%s:%d Warning:"#p"Failed\n",__func__,__LINE__);\return;}#define return_val_if_fail(p, ret)\if(!(p)){\printf("%s:%d Warning:"#p"Failed\n",__func__,__LINE__);\return (ret);}#define SAFE_FREE(p) if(p != NULL){free(p); p = NULL;}

cloth.h 衣服厂商

#ifndef __CLOTH_H__
#define __CLOTH_H__#include <stdio.h>
#include <stdlib.h>
#include "retval.h"struct _Cloth;
typedef struct _Cloth Cloth;typedef Cloth* (*createClothFunc)();
typedef void (*deleteClothFunc)(Cloth* thiz);struct _Cloth
{createClothFunc createCloth;deleteClothFunc deleteCloth;
};static inline Cloth* oper_createCloth(Cloth *thiz) {return_val_if_fail(thiz != NULL,NULL);return thiz -> createCloth();
} static inline void oper_deleteCloth(Cloth *thiz) {if (NULL != thiz && NULL != thiz -> deleteCloth ) {thiz -> deleteCloth(thiz);}return;
}#endif

hat.h

#include <stdio.h>
#include "cloth.h"typedef struct _Hat Hat;typedef Cloth* (*createHatClothFunc)();
typedef void (*deleteHatClothFunc)(Hat* thiz);struct _Hat {createHatClothFunc createHatCloth;//创建帽子deleteHatClothFunc deleteHatCloth;//删除帽子
};Hat * oper_hat_create(void);//创建帽子对象

hat.c

#include <stdio.h>
#include "retval.h"
#include "hat.h"static Cloth* oper_createHatCloth()
{Cloth *cloth = malloc(sizeof(cloth));if(cloth != NULL) { printf("create hat cloth\n");}return cloth;
}static void oper_deleteHatCloth(Hat* thiz) {printf("delete hat cloth\n"); if(thiz != NULL) {SAFE_FREE(thiz);}return;
} Hat * oper_hat_create(void) {Hat *thiz = (Hat *)malloc(sizeof(Hat));if(thiz != NULL) {thiz -> createHatCloth = oper_createHatCloth;thiz -> deleteHatCloth = oper_deleteHatCloth;}return thiz;
}

path.h

#include <stdio.h>
#include "cloth.h"typedef struct _Path Path;typedef Cloth* (*createPathClothFunc)();
typedef void (*deletePathClothFunc)(Path* thiz);struct _Path {createPathClothFunc createPathCloth;//创建裤子deletePathClothFunc deletePathCloth;//删除裤子
};/*创建裤子对象*/
Path * oper_path_create(void);

path.c

/*裤子类,封装了对象的创建和删除*/
#include <stdio.h>
#include "retval.h"
#include "path.h"static Cloth* oper_createHatCloth() //创建
{Cloth *cloth = malloc(sizeof(cloth));if(cloth != NULL) { printf("create paths cloth\n");}return cloth;
}static void oper_deletePathCloth(Hat* thiz) {//删除printf("delete paths cloth\n"); if(thiz != NULL) {SAFE_FREE(thiz);}return;
} Hat * oper_path_create(void) {Path *thiz = (Path *)malloc(sizeof(Path));if(thiz != NULL) {thiz -> createPathCloth = oper_createHatCloth;thiz -> deletePathCloth = oper_deletePathCloth;}return thiz;
}

factory.c

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>#include "hat.h"
#include "paths.h"
#include "cloth.h"
#include "retval.h"
#include "factory.h"/*通过传入的字符类型 clothName 来表示要创建对应的衣服对象*/
Cloth* factory_create_op(char clothName) {Cloth *cloth = (Cloth*) malloc(sizeof(Cloth));if(NULL != cloth) {switch (clothName) {case 'h':cloth = (Cloth*)oper_hat_create();break;case 'p':cloth = (Cloth*)oper_path_create();break;default:;}}   return cloth;
}/*释放工厂对象*/
void facory_delete_op(Factory *thiz) {assert(thiz != NULL);SAFE_FREE(thiz);
}Factory *FactoryCreate(void) {Factory *thiz = malloc(sizeof(Factory));if(thiz != NULL){thiz -> create_op = factory_create_op;thiz -> delete_op = facory_delete_op;}return thiz;
}

factory.h

#ifndef __FACTORY_H__
#define __FACTORY_H__#include <stdio.h>
#include "cloth.h"typedef struct  _Factory Factory;typedef Cloth* (*factoryCreateFunc)();
typedef void (*factoryDeleteFunc)(Factory *thiz);struct _Factory{factoryCreateFunc create_op;factoryDeleteFunc delete_op;
};Factory *FactoryCreate(void);
Cloth* factory_create_op(char clothName);
void facory_delete_op(Factory *thiz);#endif

main.c

#include <stdio.h>
#include <stdlib.h>#include "factory.h"
#include "cloth.h"int main(int argc, char *argv[]) {Factory *factory = FactoryCreate();Cloth *clothA = factory_create_op('h');oper_createCloth(clothA);oper_deleteCloth(clothA);Cloth *clothB = factory_create_op('p');oper_createCloth(clothB);oper_deleteCloth(clothB);  factory->delete_op(factory);return 0;
}

编译输出如下:

create hat cloth
delete hat cloth
create paths cloth
delete paths cloth
4. 缺点

通过以上的实现,我们很明显的发现当增加商品的时候需要修改工厂,同时无法增加除了衣服之外的其他种类商品。

  1. 违反了开闭原则:简单工厂模式在扩展产品的时候需要去修改工厂。开闭原则讲究的是对扩展开发,对修改关闭。
  2. 不支持扩展新种类的商品。

设计模式 之美 -- 简单工厂模式相关推荐

  1. 23种设计模式 -----Day01:简单工厂模式

    目录 前言 1.设计模式(Design pattern)定义 2.为什么要使用设计模式(使用设计模式的意义) 3.设计原则 a.单一职责原则 b.开放封闭原则 c.里氏代换原则 d.迪米特法则 e.依 ...

  2. 设计模式 笔记4 | 简单工厂模式 在源码中的应用 | Calendar 日历 | 源码浅析 | 使用总结 | 建造者模式

    文章目录 一.Calendar 日历类 1.1 内部属性 1.2 设置时间属性值 1.3 获取时间属性 1.4 使用 Calander 计算时间 二.Calender 类中的设计模式 2.1 简单工厂 ...

  3. 大话设计模式Python实现-简单工厂模式

    简单工厂模式(Simple Factory Pattern):是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 下面使用简单工厂模式实现一个简单的四则运算 1 #!/us ...

  4. 手撕设计模式之「简单工厂模式」(Java描述)

    前言 利用简单工厂模式可以实现对象创建和业务逻辑处理的分离,但存在工厂类职责过重,增添新产品违背开闭原则等问题.它不属于GoF 23种设计模式之一,但是它可以作为学习工厂方法模式前的一个很好的引导. ...

  5. 设计模式----2(简单工厂模式的概念,简单工厂模式的实现,简单工厂模式的优缺点)

    简单工厂模式 简单工厂模式的概念 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式.通过专门定义一个类来负 责创建其他类的实例,被创建的实例通常都具有共同的父类. 具体分类 工厂(Creator ...

  6. 设计模式(1):简单工厂模式(Simple Factory Pattern)

    1. 从一个简单的例子开始 在众多的设计原则中,有一条原则是这么说的:要针对接口编程,不要针对实现编程. 针对接口编程的话,可以使用不同的实现类来创建这个对象.比如需要一个List: List< ...

  7. Java描述设计模式(02):简单工厂模式

    一.生活场景简介 1.引入场景 订餐流程简单描述 1).食品抽象类,规定食品的基础属性操作 2).鱼类,鸡肉类食品类扩展 3).订餐流程类,根据食品名称,加工指定类型食品 4).模拟客户端预定操作 2 ...

  8. 设计模式学习-简单工厂模式

    模式概述: 专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类,简单工厂(Simple Factory)模式又称为静态工厂方法(Static Factory Method)模式,属 ...

  9. 从王者荣耀看设计模式(四.简单工厂模式)

    从王者荣耀看设计模式(简单工厂模式) 一.简介 游戏开始前,玩家可从英雄池自由挑选将要出战的英雄 二.简单工厂模式 简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫 ...

最新文章

  1. Ember入门指南——教程目录
  2. rust(25)-皮尔逊相关系数
  3. SharePoint2010整合Silverlight 4应用——Bing地图控件
  4. dynamic_cast详解
  5. 设计模式--结构型模式
  6. Centos、Ubuntu的区别
  7. Stata:面板数据模型一文读懂
  8. Linux基础知识(5)-压缩与关机命令
  9. PS合成下雨天蹲在路灯下的天使男人清(15)
  10. 易基因|植物育种:ChIP-seq(组蛋白)揭示H3K36me修饰影响温度诱导的植物可变剪接和开花
  11. 一种 Python 获取时间序列数据集的方式
  12. python简单温度转换,python编写的简单温度转换程序
  13. python英文文本情感分析_sentimentpy模块进行中文文本情感分类
  14. 解决sublime text2字体显示模糊问题
  15. 上楼梯问题+不死兔子
  16. 写bat文件for循环批量创建文件夹
  17. 【PCB封装中的_L/_M/_N解释】IPC low/medium/high density 什么意思?
  18. 存储过程(数组参数、for循环、拼接的动态sql游标、merge into)
  19. halcon脚本-找直线并拟合
  20. vim-3 粘贴命令、替换命令、替换模式和修改命令

热门文章

  1. AngularJS 指令
  2. url中去掉index.php,方便redirect()
  3. NOIP2013普及组 T2 表达式求值
  4. 【URAL】1091 Tmutarakan Exams
  5. 编译-链接-运行-环境配置各种error汇总
  6. 打不开_网页打不开,怎解?
  7. java 窗体隐藏和关闭_java JFrame窗体真正关闭
  8. 该文件 linux命令,Linux网络系统,如果执行行命令#chmod 746 file.txt,那么该文件的权限是?...
  9. 解压ubi文件_制作ubi文件系统
  10. MySQL面试题 | 附答案解析(八)