【创建型】简单工厂模式&工厂方法
简单工厂模式
简单工厂模式,其实不算23种设计模式之一,它引入了创建者的概念,将实例化的代码从客户端代码中抽离,交给服务端维护
Java代码实现
需求:服务端开发一个计算器功能,完成加减乘除运算操作
根据简单工厂模式,可以画出它的UML类图如下:
1、需要一个产品抽象类(Operation父类)、工厂类、具体的实现类(AddOperation...)
2、Operation类中有操作数x和y,以及获取结果的函数getResult()
3、工厂类OperationFactory类创建具体的Operation,其中OperationFactory类依赖Operation类
服务端代码
public class OperationFactory {
public static Operation createOperation(String operate) {
Operation operation = null;
switch (operate) {
case "+":
operation = new AddOperation();
break;
case "-":
operation = new SubOperation();
break;
case "*":
operation = new MulOperation();
break;
case "/":
operation = new DivOperation();
break;
}
return operation;
}
}
public abstract class Operation {
double x;
double y;
double result;
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public double getResult() throws Exception {
return result;
}
}
public class AddOperation extends Operation {
@Override
public double getResult() {
return x + y;
}
}
public class SubOperation extends Operation {
@Override
public double getResult() throws Exception {
return x - y;
}
}
public class MulOperation extends SubOperation {
@Override
public double getResult() throws Exception {
return x / y;
}
}
public class DivOperation extends MulOperation {
@Override
public double getResult() throws Exception {
if (0 == y) {
throw new Exception("除数不能为0");
}
return x / y;
}
}
客户端代码
public class Main {
public static void main(String[] args) throws Exception {
Operation operation = OperationFactory.createOperation("+");
operation.setX(1);
operation.setY(2);
System.out.println(operation.getResult()); // print 3.0
}
}
C代码实现
需求:某一项目需要用到 eeprom、flash 这两个设备保存不同数据,有初始化、读、写三个功能,后续有可能扩展设备
服务端代码:
需要定义设备类型flash.c
flash.h
eeprom.c
eeprom.h
// flash.c
#include <stdint.h>
#include <stdio.h>
#include "factory_function.h"
void flash_init(void) {
printf("初始化 FLASH\n");
}
void flash_open(void) {
printf("启用 FLASH\n");
}
void flash_write(uint32_t addr, uint8_t *data, uint16_t len) {
printf("向FLASH 地址:%x 写入%d 字节数据:%s\n", addr, len, (char *) data);
// eeprom.c
#include <stdint.h>
#include <stdio.h>
void eeprom_init(void) {
printf("初始化 EEPROM\n");
}
void eeprom_open(void) {
printf("启用 EEPROM\n");
}
void eeprom_write(uint32_t addr, uint8_t *data, uint16_t len) {
printf("向EEPROM 地址:%x 写入%d 字节数据:%s\n", addr, len, (char *) data);
}
需要定义工厂方法:
// factory_function.c
#include <string.h>
#include "factory_function.h"
#include "flash.h"
#include "eeprom.h"
typedef struct {
char *name;
void (*init)(void);
void (*open)(void);
void (*write)(uint32_t, uint8_t *, uint16_t);
} Storage;
Storage storage_list[] = {
{"eeprom", eeprom_init, eeprom_open, eeprom_write},
{"flash", flash_init, flash_open, flash_write},
};
Storage *factory_pro(char *name) {
for (int i = 0; i < sizeof(storage_list) / sizeof(storage_list[0]); ++i) {
if (0 == strcmp(name, storage_list[i].name)) {
storage_list->init();
storage_list->open();
return &storage_list[i];
}
}
return NULL;
}
客户端代码
void test_01_factory_method() {
char *str[] = {"我是EEPROM", "我是FLASH"};
Storage *byte_data = factory_pro("eeprom");
Storage *sector_data = factory_pro("flash");
byte_data->write(0x0100, str[0], strlen(str[0]));
sector_data->write(0x02000100, str[1], strlen(str[1]));
}
模式应用
1、JDK类库中广泛使用了简单工厂模式,如工具类java.text.DateFormat,它用于格式化一个本地日期或者时间
public final static DateFormat getDateInstance();
public final static DateFormat getDateInstance(int style);
public final static DateFormat getDateInstance(int style,Locale locale);
2、获取不同加密算法的密钥生成器
KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
总结
简单工厂模式下,后续拓展功能,需要侵入式的修改工厂中的代码,违反了开闭原则,但是客户端代码不用修改。
C语言的简单工厂模式和面向对象的Java略有不同
1、Java用的继承和多态的思想按需动态的创建所需要的类型
2、C语言用循环遍历的方式来寻找具体的类型并执行方法
工厂方法
需求:服务端开发一个计算器功能,完成加减乘除运算操作。
相比简单工厂模式,工厂方法的UML类图如下:
针对不同的操作,有不同的工厂,这种修改带来了优点是减少侵入式修改,但是会增加服务端的开发量同时客户端需要适配
本文作者:__Helios
本文链接:https://www.cnblogs.com/ffopen/p/13192040.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验