设计模式学习(二):实现可动态注册的简单工厂模式(C语言)

一、前言

上周学习了抽象工厂模式,该模式包含了简单工厂模式和工厂方法的某些特性,三者之间的区别详见:上周博客,本周深入了解一下简单工厂模式,并对其进行优化,实现一个可动态注册的简单工厂,本次练习参考了AWTK源码中 widget_factory 的实现,感兴趣的可以查阅源码,GitHub仓库:https://github.com/zlgopen/awtk

AWTK是 ZLG 开发的开源 GUI 引擎,官网地址:https://www.zlg.cn/index/pub/awtk.html

二、简单工厂模式

简单工厂模式(Factory Pattern)是属于创建型模式,在该模式中,用户通过使用一个共同的接口来创建的具体对象。

简单理解:工厂是对具体产品(对象)的抽象,工厂提供统一接口创建不同的产品。本质上就是定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

目的:给用户提供一个创建一系列相关对象的接口,但用户是不需要指定它们的具体类,其主要是解决接口选择的问题。

优点

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

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

通常情况下简单工厂模式中的工厂类是静态实现的,即具体对象的构造函数写在工厂类的代码中,那么在新增产品时,就需要修改工厂类的代码,比较麻烦,因此需要进行优化,让工厂类提供动态注册的功能,方便用户可以在从外部直接向工厂类添加新产品,接下来我们来看一个示例。

三、示例类图及C语言代码

3.1 示例介绍

假如要实现一个画笔功能,可以画不同的形状(shape),此处有具体产品方形(square)和圆形(circle),它们具有的绘制(draw)行为,并且需要实现一个具有动态注册功能的形状工厂(shape_factory),让用户可从外部新增具体形状。

3.2 示例类图

在这里插入图片描述

首先需要创建 shape_t 接口以及实现该接口的具体类。下一步是创建工厂类 shape_factory_t ,实现它的动态注册功能,提供给用户使用。

3.3 C语言实现

1、创建 shape_t 接口

/* shape.h */
#ifndef SHAPE_H
#define SHAPE_H

#include "awtk.h"

BEGIN_C_DECLS

typedef struct _shape_t shape_t;
typedef struct _shape_vtable_t shape_vtable_t;

typedef shape_t* (*shape_create_t)();
typedef ret_t (*shape_destroy_t)(shape_t* shape);
typedef ret_t (*shape_draw_t)(shape_t* shape);

struct _shape_vtable_t {
   
  uint32_t size;
  const char* type;
  shape_create_t create;
  shape_destroy_t destroy;
  shape_draw_t draw;
};

/**
 * @class shape_t
 * 形状接口,具体形状的基类。
 */
struct _shape_t {
   
  /**
   * @property {shape_vtable_t*} vt
   * 虚函数表。
   */
  const shape_vtable_t* vt;
};

/**
 * @method shape_create
 * 创建shape对象(仅在子类构造函数中使用)。
 * @param {shape_vtable_t*} vt 虚表。
 * @return {shape_t*} shape对象本身。
 */
shape_t* shape_create(const shape_vtable_t* vt);

/**
 * @method shape_destroy
 * 销毁shape对象。
 * @param {shape_t*} shape 形状对象。
 * @return {ret_t} 返回RET_OK表示成功,否则表示失败。
 */
ret_t shape_destroy(shape_t* shape);

/**
 * @method shape_draw
 * 绘制(此处模拟对象行为)。
 * @param {shape_t*} shape 形状对象。
 * @return {ret_t} 返回RET_OK表示成功,否则表示失败。
 */
ret_t shape_draw(shape_t* shape);

/* 子类类型常量 */
#define SHAPE_TYPE_SQUARE "square" /* 方形 */
#define SHAPE_TYPE_CIRCLE "circle" /* 圆形 */

#endif /* SHAPE_H */
/* shape.c */
#include "shape.h"

shape_t* shape_create(const shape_vtable_t* vt) {
   
  return_value_if_fail(vt != NULL, NULL);

  /* 初始化子类虚函数表 */
  shape_t* shape = TKMEM_ALLOC(vt->size)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值