C语言抽象工厂模式

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕着一个超级工厂来创建其他的工厂。这个我加粗了超级工厂,那么什么是超级工厂?

简单理解:工厂是对具体的产品的抽象的概念,比如我有颜色工厂(color factory)和一个形状工厂(shape factory),这里的颜色和形状是抽象的概念。因为颜色可能是红色,蓝色等等具体的颜色,而形状也可能是圆形,方形具体的形状。工厂将这些具体的实体提炼抽象出来并且提供统一的接口来创造不同实体,而抽象工厂则就是工厂的进一步的抽象来提供统一的接口来创造不同的工厂。

目的:抽象工厂模式其实想干的事情就是给用户提供一个创建一系列相关或相互依赖对象的接口,但用户是不需要指定它们的具体类。

​ 通过以上的简单的介绍,我们可以知道抽象工厂模式主要是为了解决接口接口选择的问题。为了方便理解,我们举一个例子来进行说明。

类图设计

实例要求

​ 功能要求:要实现一个图形绘画画笔的功能,这个功能要求可以绘制不同的颜色也可以绘制不同的形状和填充不同的颜色。

首先可以抽象两个工厂,一个工厂用来实现具体的形状类,我们称之为shape factory,另外一个工厂用来实现不同的颜色类,称之为颜色工厂。

然后假设目前形状工厂要实现的形状产品有"圆形"和"方形",颜色工厂要实现的颜色产品有"蓝色"和"红色"

实例类图

​ 根据以上的描述,使用抽象工厂模式使用以下的类图

根据类图,我们可以明显抽象工厂的设计步骤:

  • 创建shape_t和color_t这两个接口并且实现由于这些接口实体化的类。
  • 创建抽象工厂类brush_factory_t,接着定义工厂类 shape_factory_t 和 color_factory_t,这两个工厂类都继承了抽象工厂类 brush_factory_t。
  • 创建一个工厂生成器 factory_producer_t ,该接口提供给用户使用。

C语言的实现

1 创建shape_t和color_t这两个接口并且实现由于这些接口实体化的类。

typedef void(*draw_t)();
typedef struct _shape_t {
	draw_t draw;
}shape_t;

/* square_t implement shape_t */
typedef struct _square_t {
	shape_t shape;
}square_t;

static void square_draw() {
	printf("square_draw!\n");
}

square_t* square_create() {
	square_t* square = malloc(sizeof(square_t));
	square->shape.draw = square_draw;
	return square;
}

/* circle_t implement shape_t */
typedef struct _circle_t {
	shape_t shape;
}circle_t;

static void circle_draw() {
	printf("circle_draw!\n");
}

circle_t* circle_create() {
	circle_t* circle = malloc(sizeof(circle_t));
	circle->shape.draw = circle_draw;
	return circle;
}

2 创建 color_t 接口并完成具体实现(red_t、blue_t):

/************************* color_t *************************/
typedef void(*fill_t)();
typedef struct _color_t {
	fill_t fill;
}color_t;

/* red_t implement color_t */
typedef struct _red_t {
	color_t color;
}red_t; 

static void red_fill() {
	printf("red_fill!\n");
}

red_t* red_create() {
	red_t* red = malloc(sizeof(red_t));
	red->color.fill = red_fill;
	return red;
}

/* blue_t implement color_t */
typedef struct _blue_t {
	color_t color;
}blue_t;

static void blue_fill() {
	printf("blue_fill!\n");
}

red_t* blue_create() {
	blue_t* blue = malloc(sizeof(blue_t));
	blue->color.fill = blue_fill;
	return blue;
}

3 为 shape_t 和 color_t 创建抽象工厂( brush_factory_t )来获取具体的工厂:

/************************* brush_factory_t (Abstract Factory) *************************/
typedef shape_t* (*brush_shape_create_t)(char* shape);
typedef void(*brush_shape_destory_t)(shape_t* shape);
typedef color_t* (*brush_color_create_t)(char* color);
typedef void(*brush_color_destroy_t)(color_t* color);

typedef struct _brush_factory_t {
	brush_shape_create_t brush_shape_create;
	brush_shape_destory_t brush_shape_destory;
	brush_color_create_t brush_color_create;
	brush_color_destroy_t brush_color_destroy;
}brush_factory_t;

4 实现具体工厂 shape_factory_t 和 color_factory_t :

/* shape_factory_t implement brush_factory_t */
typedef struct _shape_factory_t {
	brush_factory_t brush_factory;
}shape_factory_t;

static shape_t* brush_shape_create(char* shape) {
	if (!strcmp(shape, "square")) {
		return square_create();
	} else if (!strcmp(shape, "circle")) {
		return circle_create();
	}
	return NULL;
}

static void brush_shape_destroy(shape_t* shape) {
	free(shape);
}

shape_factory_t* shape_factory_create() {
	shape_factory_t* shape_factory = malloc(sizeof(shape_factory_t));
	shape_factory->brush_factory.brush_shape_create = brush_shape_create;
	shape_factory->brush_factory.brush_shape_destory = brush_shape_destroy;
	shape_factory->brush_factory.brush_color_create = NULL;
	shape_factory->brush_factory.brush_color_destroy = NULL;
	return shape_factory;
}

/* color_factory_t implement brush_factory_t */
typedef struct _color_factory_t {
	brush_factory_t brush_factory;
}color_factory_t;

static color_t* brush_color_create(char* color) {
	if (!strcmp(color, "red")) {
		return red_create();
	} else if (!strcmp(color, "blue")) {
		return blue_create();
	}
	return NULL;
}

static void brush_color_destroy(color_t* color) {
	free(color);
}

color_factory_t* color_factory_create() {
	color_factory_t* color_factory = malloc(sizeof(color_factory_t));
	color_factory->brush_factory.brush_shape_create = NULL;
	color_factory->brush_factory.brush_shape_destory = NULL;
	color_factory->brush_factory.brush_color_create = brush_color_create;
	color_factory->brush_factory.brush_color_destroy = brush_color_destroy;
	return color_factory;
}

5、实现工厂生成器( factory_producer_t ),提供给用户使用:

/************************* factory_producer_t  *************************/
brush_factory_t* factory_create(char* choice) {
	if (!strcmp(choice, "shape")) {
		return shape_factory_create();
	}
	else if (!strcmp(choice, "color")) {
		return color_factory_create();
	}
	return NULL;
}

void factory_destroy(brush_factory_t* brush_factory) {
	free(brush_factory);
}
6、使用代码如下:

int main(int argc, const char* argv[]) {
	brush_factory_t* shape_factory = factory_create("shape");
	shape_t* shape1 = shape_factory->brush_shape_create("circle");
	shape_t* shape2 = shape_factory->brush_shape_create("square");
	shape1->draw();
	shape2->draw();

	brush_factory_t* color_factory = factory_create("color");
	color_t* color1 = color_factory->brush_color_create("red");
	color_t* color2 = color_factory->brush_color_create("blue");
	color1->fill();
	color2->fill();

	shape_factory->brush_shape_destory(shape1);
	shape_factory->brush_shape_destory(shape2);
	color_factory->brush_color_destroy(color1);
	color_factory->brush_color_destroy(color2);
	factory_destroy(shape_factory);
	factory_destroy(color_factory);
	getchar();

	return 0;
}

总结

对于的抽象工厂模式而言,存在一些模式带来的优点,当然也存在一些缺点。

  • 抽象模式将实现和抽象概念进行分离,用户使用抽象工厂和抽象产品的接口,没有直接对接到具体的产品,这样方便代码的通用。
  • 工厂模式有利产品的切换,如果产品发生改变,只需要修改产品的具体的实现,而不用修改工厂,比如我这个原本红色的fill修改了红色的色号,但是对于工厂而言接口并没有改变,使用方式也没有改变。
  • 它有利于产品的一致性:当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象。
  • 有利于产品的一致性:当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象。
  • 难以支持新种类的产品(扩展性较差):新增新种类的产品,需要修改抽象工厂类及其所有子类,工作量较大。

简单工厂、抽象工厂和工厂方法之间的区别

最后,通过对抽象工厂模式的学习发现该模式包含了简单工厂模式和工厂方法的某些特性,三者之间的区别如下:

简单工厂模式:一个具体工厂可生产多种具体产品;

抽象工厂模式:一个抽象工厂可生产多种具体工厂,其中每个具体工厂可以生成多种具体产品;

工厂方法模式:一个具体工厂只能生成一种具体产品。

posted @ 2023-07-22 00:15  Kroner  阅读(147)  评论(0编辑  收藏  举报