尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

PLC结构化文本设计模式——原型模式(Prototype Pattern)

PLC结构化文本设计模式——原型模式(Prototype Pattern)
📅 发布时间:2026/6/20 22:56:30

PLC Structured Text Design Patterns

PLC结构化文本设计模式——原型模式(Prototype Pattern)

介绍

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。——Java 原型模式|菜鸟教程

使用原型实例指定要创建对象的种类,并通过拷贝这些原型创建新的对象。与直接实例化类创建新对象不同,原型模式通过拷贝现有对象生成新对象——Java 原型模式|菜鸟教程

使用场景

  • 当创建一个对象需要消耗大量资源(如数据库查询、网络请求、复杂计算),或构造过程非常复杂时,原型模式可以通过复制已有对象来避免重复的高成本操作。

  • 当系统需要在运行时动态创建多种相似但略有差异的对象,且这些对象的类型可能无法提前预知时,原型模式可以通过克隆不同原型来快速生成新对象。

  • 当需要创建对象但无法访问其构造函数(如构造函数为私有),或构造函数参数复杂难以获取时,原型模式可以通过克隆已有实例绕过这些限制。

Tips:对于PLC来说FB构造函数(FB_init)明确禁止私有。

  • 当需要保存对象在不同阶段的状态(如撤销操作),原型模式可以通过克隆当前状态来实现历史记录的保存。

  • 当需要创建大量结构相似、仅部分属性不同的对象时,原型模式可以通过克隆基准对象并修改差异部分,提高创建效率。

优缺点

  • 优点
    • 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高新实例的创建效率。

    • 可以使用深复制的方式保存对象的状态。将对象复制一份并将其状态保存起来,以便于在使用的时候使用,比如恢复到某一个历史状态,可以辅助实现撤销操作。

  • 缺点
    • 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了开闭原则。

    • 为了支持深复制,当对象之间存在多重嵌套引用关系时,每一层对象都必须支持深复制,实现起来可能比较麻烦。

伪代码

创建基础接口类型,主要目的:为了后续接口类型转换,接口与接口和接口与指针之间的转换。

INTERFACE I_Interface EXTENDS __SYSTEM.IQueryInterface

创建可销毁/清除I_Disposable接口类型,扩展于I_Interface。

INTERFACE I_Disposable EXTENDS I_InterfaceMETHOD Dispose
VAR_INPUT
END_VAR

创建可克隆I_Cloneable接口,扩展于I_Disposable。

INTERFACE I_Cloneable EXTENDS I_DisposableMETHOD Clone : I_Cloneable
VAR_INPUT
END_VAR

创建产品参数接口I_ProductParameter,继承I_Cloneable。

INTERFACE I_ProductParameter EXTENDS I_CloneablePROPERTY Height : REAL
Get()
Set()PROPERTY ID : INT
Get()
Set()PROPERTY Name : STRING
Get()
Set()PROPERTY Width : REAL
Get()
Set()

定义FB_ProductParameter类并实现I_ProductParameter接口。使用PLC动态创建对象实例需要开发人员手动去管理对象的生命周期,使用完需要销毁/释放内存,这区别于C#存在gc机制,自动回收内存。因此,需要实现方法Dispose,释放内存防止资源浪费,使用__New()创建对象实例时需要特别注意这一点。

{attribute 'enable_dynamic_creation'}
FUNCTION_BLOCK FB_ProductParameter IMPLEMENTS I_ProductParameter
VARsProductName 	: STRING;nProductId	 	: INT;nProductWidth	: REAL;nProductHeight	: REAL;
END_VAR
------
METHOD Clone : I_Cloneable
VARpProductParameter : POINTER TO FB_ProductParameter;
END_VARpProductParameter := __NEW(FB_ProductParameter);
(* 以下操作均为"浅拷贝" *)
// 内部成员(变量)按个拷贝
pProductParameter^.Name 	:= THIS^.sProductName;
pProductParameter^.ID 		:= THIS^.nProductId;
pProductParameter^.Width 	:= THIS^.nProductWidth;
pProductParameter^.Height 	:= THIS^.nProductHeight;
// 或者直接赋值
// pProductParameter^ := THIS^;
Clone := pProductParameter^;
------
METHOD Dispose__DELETE(THIS);
ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Memory has released', strArg := '');
------
PROPERTY Height : REAL
Get:Height := THIS^.nProductHeight;
Set:THIS^.nProductHeight := Height;
------
PROPERTY ID : INT
Get:ID := THIS^.nProductId;
Set:THIS^.nProductId := ID;
------
PROPERTY Name : STRING
Get:Name := THIS^.sProductName;
Set:THIS^.sProductName := Name;
------
PROPERTY Width : REAL
Get:Width := THIS^.nProductWidth;
Set:THIS^.nProductWidth := Width;

浅拷贝(Shallow Copy)
定义:创建一个新对象,然后将原对象的字段值直接复制到新对象中。
对于值类型成员(如 int、float、struct 等):直接复制值本身,新对象和原对象的值类型成员相互独立。
对于引用类型成员(如类实例、数组等):只复制引用地址,新对象和原对象的引用类型成员指向同一个内存地址。

深拷贝(Deep Copy)
定义:创建一个新对象,然后递归复制原对象的所有成员,包括引用类型成员所指向的对象。
无论属性值是基本数据类型还是引用类型,都会创建一个完全独立的副本。

对于PLC而言若相同类型FB直接fb1:=fb2,内部成员无论是POINTER或REFERENCE或者INTERFACE只是将fb2内的地址赋值给fb1,fb1里的引用类型变量地址指向的是fb2里的内存,也就是fb1和fb2引用类型使用的是同一块内存。(浅拷贝)

主程序运行,先对fbProductParameter属性赋值初始值,iProductParameterClone接收克隆对象实例,接着将接口iProductParameterClone转换成iProductParameter,日志记录克隆之后的属性值。最后再将iProductParameterClone接口转换成iProductParameterDispose释放创建的内存。

PROGRAM MAIN
VARbTest1 : BOOL;iProductParameter 		: I_ProductParameter;fbProductParameter 		: FB_ProductParameter;iProductParameterClone	: I_Cloneable;iProductParameterDispose: I_Disposable;	
END_VARIF bTest1 THENfbProductParameter.ID := 1;fbProductParameter.Name := 'glasses';fbProductParameter.Width:= 800;fbProductParameter.Height:= 1000;iProductParameterClone := 	fbProductParameter.Clone();// 将拷贝创建的新对象转换成I_ProductParameter接口类型IF __QUERYINTERFACE(iProductParameterClone,iProductParameter) THEN// 输出拷贝对象成员值ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Name:%s', strArg := iProductParameter.Name);ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Id:%s', strArg := TO_STRING(iProductParameter.ID));ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Width:%s', strArg := TO_STRING(iProductParameter.Width));ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Height:%s', strArg := TO_STRING(iProductParameter.Height));END_IF// iProductParameter.Dispose();释放内存// 将拷贝的新对象转换成I_Disposable接口类型(主要演示__QUERYINTERFACE用法)IF __QUERYINTERFACE(iProductParameterClone,iProductParameterDispose) THEN// 将对象内存释放iProductParameterDispose.Dispose();END_IFbTest1 := FALSE;
END_IF

日志输出结果:

MSG | 'PlcTask' (350): Name:glasses
MSG | 'PlcTask' (350): Id:1
MSG | 'PlcTask' (350): Width:800.0
MSG | 'PlcTask' (350): Height:1000.0
MSG | 'PlcTask' (350): Memory has released

相关新闻

  • PHP-FPM 深度调优指南 告别 502 错误,让你的 PHP 应用飞起来
  • RAG系统大脑调教指南:模型选择、提示设计与质量控保一本通
  • trl ppo

最新新闻

  • CANN/asc-devkit Exp函数API
  • Binding库单元测试终极指南:如何编写可靠的绑定测试用例
  • 2026年中国出海展会展台设计搭建服务商选型指南 覆盖美洲欧洲东南亚非洲中东市场 - 寻茫精选
  • 2026找汕头代理记账公司,这5个关键点你必须知道! - 企业品牌
  • AI写专著全攻略:从构思到完成,AI工具助力20万字专著高效诞生!
  • 3步搞定知网文献批量下载:CNKI-download自动化工具完全指南

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号