PLC结构化文本设计模式——抽象工厂模式(Abstract Factory Pattern)

PLC Structured Text Design Patterns

PLC结构化文本设计模式——抽象工厂模式(Abstract Factory Pattern)

介绍

工厂方法模式解决了简单工厂模式因新增产品种类而不得不修改/新增工厂内部代码的问题,但是每增加一种产品都需要增加一个工厂类,而且每个工厂类只负责创建一种产品,导致系统中存在大量的工厂类,从而增加系统开销。如何解决上述问题?本章将会介绍抽象工厂模式,将相关产品分类组合成一个产品族,由同一个工厂来统一生产。

抽象工厂模式(Abstract Factory Pattern) 是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。——Java 抽象工厂模式|菜鸟教程

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。——Java 抽象工厂模式|菜鸟教程

抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。——Java 抽象工厂模式|菜鸟教程

使用场景

在一个产品族中定义多个产品,由具体工厂实现创建这些产品的方法。——Java 抽象工厂模式|菜鸟教程

其实比较抽象,PLC中不太好举例,自行体会。举个生活中的例子吧:设备上的鼠标、键盘、显示器,品牌商有戴尔、双飞燕、罗技等。(戴尔/双飞燕/罗技)它们都有各自的工厂每个工厂生产鼠标、键盘、显示器这三类产品。

优缺点

伪代码

创建基接口,后续所有接口均基于此扩展。

INTERFACE I_Interface EXTENDS __SYSTEM.IQueryInterface

创建传感器接口,继承基接口。

INTERFACE I_Sensor EXTENDS I_Interface

METHOD ReadData : LREAL
VAR_INPUT
END_VAR

创建控制器接口,继承基接口。

INTERFACE I_Controller EXTENDS I_Interface

METHOD Execute : HRESULT
VAR_INPUT
END_VAR

创建压力控制器实体类,实现控制器接口。

{attribute 'enable_dynamic_creation'} 
FUNCTION_BLOCK FB_PressureController IMPLEMENTS I_Controller
VAR
END_VAR
------
METHOD Execute : HRESULT

ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='[FB_PressureController]:Execute', strArg := '');

创建压力传感器实体类,实现传感器接口。

{attribute 'enable_dynamic_creation'} 
FUNCTION_BLOCK FB_PressureSensor IMPLEMENTS I_Sensor
VAR
END_VAR
------
METHOD ReadData : LREAL

ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='[FB_PressureSensor]:ReadData', strArg := '');

创建温度控制器实体类,实现控制器接口

{attribute 'enable_dynamic_creation'} 
FUNCTION_BLOCK FB_TemperatureController IMPLEMENTS I_Controller
VAR
END_VAR
------
METHOD Execute : HRESULT

ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='[FB_TemperatureController]:Execute', strArg := '');

创建温度传感器实体类,实现传感器接口。

{attribute 'enable_dynamic_creation'} 
FUNCTION_BLOCK FB_TemperatureSensor IMPLEMENTS I_Sensor
VAR
END_VAR
------
METHOD ReadData : LREAL

ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='[FB_TemperatureSensor]:ReadData', strArg := '');

创建抽象工厂类,包含三个抽象方法,CreateController生成控制器实例,CreateSensor生成传感器实例,ReleaseMemory释放创建对象的内存。

FUNCTION_BLOCK ABSTRACT FB_EquipmentAbstractFactory
VAR
END_VAR
------
METHOD ABSTRACT CreateController : I_Controller
VAR_INPUT
END_VAR
------
METHOD ABSTRACT CreateSensor : I_Sensor
VAR_INPUT
END_VAR
------
METHOD ABSTRACT ReleaseMemory : HRESULT
VAR_INPUT
END_VAR

创建压力设备工厂实体类,继承设备抽象工厂类,主要实现抽象类的三个抽象方法。

FUNCTION_BLOCK FB_PressureEquipmentFactory EXTENDS FB_EquipmentAbstractFactory
VAR
	pPressureController : POINTER TO FB_PressureController;
	pPressureSensor		: POINTER TO FB_PressureSensor;
END_VAR
------
METHOD  CreateController : I_Controller
VAR_INPUT
END_VAR

pPressureController := __NEW(FB_PressureController);
IF	pPressureController <> 0 THEN
	CreateController := pPressureController^;
END_IF
------
METHOD  CreateSensor : I_Sensor
VAR_INPUT
END_VAR

pPressureSensor := __NEW(FB_PressureSensor);
IF	pPressureSensor <> 0 THEN
	CreateSensor := pPressureSensor^;
END_IF
------
METHOD  ReleaseMemory : HRESULT
VAR_INPUT
END_VAR

IF	pPressureController <> 0 THEN
	__DELETE(pPressureController);
END_IF

IF pPressureSensor <> 0 THEN
	__DELETE(pPressureSensor);
END_IF
------
METHOD FB_exit : BOOL
VAR_INPUT
	bInCopyCode : BOOL; // if TRUE, the exit method is called for exiting an instance that is copied afterwards (online change).
END_VAR

IF	pPressureController <> 0 THEN
	__DELETE(pPressureController);
END_IF

IF pPressureSensor <> 0 THEN
	__DELETE(pPressureSensor);
END_IF

创建温度设备工厂实体类,继承设备抽象工厂类,主要实现抽象类的三个抽象方法。

FUNCTION_BLOCK FB_TemperatureEquipmentFactory EXTENDS FB_EquipmentAbstractFactory
VAR
	pTemperatureController : POINTER TO FB_TemperatureController;
	pTemperatureSensor	   : POINTER TO FB_TemperatureSensor;
END_VAR
------
METHOD  CreateController : I_Controller
VAR_INPUT
END_VAR

pTemperatureController := __NEW(FB_TemperatureController);
IF pTemperatureController <> 0 THEN
	CreateController := pTemperatureController^;
END_IF
------
METHOD  CreateSensor : I_Sensor
VAR_INPUT
END_VAR

pTemperatureSensor := __NEW(FB_TemperatureSensor);
IF pTemperatureSensor <> 0 THEN
	CreateSensor := pTemperatureSensor^;
END_IF
------
METHOD  ReleaseMemory : HRESULT
VAR_INPUT
END_VAR

IF pTemperatureController <> 0 THEN
	__DELETE(pTemperatureController);
END_IF

IF pTemperatureSensor <> 0 THEN
	__DELETE(pTemperatureSensor);
END_IF

前面章节应该已经介绍过了,实体类声明指针类型的原因。主要需要使用__New()操作符来创建对象,它的返回值是指针。

PROGRAM MAIN
VAR
	bTest : BOOL;
	fbEquipmentAbstractFactory 		: REFERENCE TO FB_EquipmentAbstractFactory;
	fbPressureEquipmentFactory 		: FB_PressureEquipmentFactory;
	fbTemperatureEquipmentFactory   : FB_TemperatureEquipmentFactory;
	iController	: I_Controller;
	iSensor		: I_Sensor;
END_VAR

IF bTest THEN
	// 测试压力设备工厂
	fbEquipmentAbstractFactory REF= fbPressureEquipmentFactory;
	iController := fbEquipmentAbstractFactory.CreateController();
	iSensor := fbEquipmentAbstractFactory.CreateSensor();
	IF iController <> 0 THEN
		iController.Execute();
	END_IF
	IF iSensor <> 0 THEN
		iSensor.ReadData();
	END_IF
	// 释放内存
	fbEquipmentAbstractFactory.ReleaseMemory();
	// 测试温度设备工厂
	fbEquipmentAbstractFactory REF= fbTemperatureEquipmentFactory;
	iController := fbEquipmentAbstractFactory.CreateController();
	iSensor := fbEquipmentAbstractFactory.CreateSensor();
	IF iController <> 0 THEN
		iController.Execute();
	END_IF
	IF iSensor <> 0 THEN
		iSensor.ReadData();
	END_IF
	// 释放内存
	fbEquipmentAbstractFactory.ReleaseMemory();	
	bTest := FALSE;
END_IF

这里其实还可以再创建个超级工厂,生产FB_PressureEquipmentFactoryFB_TemperatureEquipmentFactory这两个工厂,称为工厂的工厂,自行实现。

主程序运行,输出以下结果。

MSG |'PlcTask' (350): [FB_PressureController]:Execute
MSG |'PlcTask' (350): [FB_PressureSensor]:ReadData
MSG |'PlcTask' (350): [FB_TemperatureController]:Execute
MSG |'PlcTask' (350): [FB_TemperatureSensor]:ReadData

程序中fbEquipmentAbstractFactory引用类型,用于接收FB_PressureEquipmentFactoryFB_TemperatureEquipmentFactory工厂实例,实际项目中可以根据业务/配置自行选择用哪个工厂创建对象实例。

抽象工厂模式相对工厂方法模式,一定程度上降低了工厂类的创建,将创建的种类封装在工厂类中,但同时若产品族扩展/增加就需要修改抽象工厂类和对应的实体工厂类,拓展较为困难。

posted @ 2025-09-12 15:32  J_Sheng  阅读(16)  评论(0)    收藏  举报