当前位置: 首页 > news >正文

PLC结构化文本设计模式——适配器模式(Adapter Pattern)

PLC Structured Text Design Patterns

PLC结构化文本设计模式——适配器模式(Adapter Pattern)

介绍

适配器模式(Adapter Pattern)充当两个不兼容接口之间的桥梁,属于结构型设计模式。它通过一个中间件(适配器)将一个类的接口转换成客户期望的另一个接口,使原本不能一起工作的类能够协同工作。适配器模式是一种软件设计模式,旨在解决不同接口之间的兼容性问题。适配器通过继承或依赖现有对象,并实现所需的目标接口。——Java 适配器模式|菜鸟教程

使用场景

  • 需要使用现有类,但其接口不符合系统需求。
  • 希望创建一个可复用的类,与多个不相关的类(包括未来可能引入的类)一起工作,这些类可能没有统一的接口。
  • 通过接口转换,将一个类集成到另一个类系中。

生活中经典的例子,手机适配器或电脑适配器,连接手机或电脑端的接口为USB,连接充电插座端是两孔/三孔,充电就通过中间的适配器。

优缺点

  • 优点

    • 促进了类之间的协同工作,即使它们没有直接的关联。
    • 提高了类的复用性。
    • 增加了类的透明度。
    • 提供了良好的灵活性。
  • 缺点

    • 过度使用适配器可能导致系统结构混乱,难以理解和维护。
    • 由于只能继承一个类,因此只能适配一个类,且目标类必须是抽象的。

    Java 适配器模式|菜鸟教程

伪代码

socket通讯串口通讯为例,设计适配器用以适配客户端接口I_Communication

INTERFACE I_Interface EXTENDS __SYSTEM.IQueryInterface

串口通讯接口,接口的属性成员和方法成员与客户端接口I_Communication不一致,因此需要进行适配。

INTERFACE I_SerialCom EXTENDS I_InterfacePROPERTY BaudRate : INT
Get()
------
PROPERTY DataBits : INT
Get()
------
PROPERTY IsConnected : BOOL
Get()
------
PROPERTY Parity : INT
Get()
------
PROPERTY PortName : STRING
Get()
------
PROPERTY StopBits : INT
Get()
------
METHOD Close : BOOL
VAR_INPUT
END_VAR
------
METHOD Open : BOOL
VAR_INPUT
END_VAR
------
METHOD SendData : STRING
VAR_INPUTdata : STRING;
END_VAR

Socket通讯接口,接口的属性成员和方法成员与客户端接口I_Communication不一致,因此需要进行适配。

INTERFACE I_Socket EXTENDS I_InterfaceMETHOD Connect : BOOL
VAR_INPUT
END_VAR
------
METHOD Disconnect : BOOL
VAR_INPUT
END_VAR
------
METHOD SendMessage : STRING
VAR_INPUTmessage : STRING;
END_VAR
------
PROPERTY IpAddress : STRING
Get()
------
PROPERTY IsConnected : BOOL
Get()
------
PROPERTY Port : INT
Get()

客户端需要系统通用接口,直接工作在业务中。前面的I_SerialComI_Socket接口需要适配I_Communication接口。

INTERFACE I_Communication EXTENDS I_InterfaceMETHOD Connect : BOOL
VAR_INPUT
END_VAR
------
METHOD Disconnect : BOOL
VAR_INPUT
END_VAR
------
METHOD Send : STRING
VAR_INPUTsContent : STRING;
END_VAR
------
PROPERTY IsConnected : BOOL
Get()

FB_SerialCom串口通讯,实现I_SerialCom接口。

FUNCTION_BLOCK FB_SerialCom IMPLEMENTS I_SerialCom
VAR_IsConnected : BOOL := FALSE;_BaudRate 	 : INT;_DataBits	 : INT;_Parity		 : INT;_PortName	 : STRING;_StopBits	 : INT;
END_VAR
------
PROPERTY BaudRate : INT
Get:BaudRate := THIS^._BaudRate;
------
PROPERTY DataBits : INT
Get:DataBits := THIS^._DataBits;
------
PROPERTY IsConnected : BOOL
Get:IsConnected := THIS^._IsConnected;
------
PROPERTY Parity : INT
Get:Parity := THIS^._Parity;
------
PROPERTY PortName : STRING
Get:PortName := THIS^._PortName;
------
PROPERTY StopBits : INT
Get:StopBits := THIS^._StopBits;
------
METHOD FB_init : BOOL
VAR_INPUTbInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)bInCopyCode : BOOL;  // if TRUE, the instance afterwards gets moved into the copy code (online change)portName : STRING; // 端口号baudRate : INT; // 波特率parity   : INT; // 校验位dataBits : INT; // 数据位stopBits : INT; // 停止位
END_VARTHIS^._PortName := portName;
THIS^._BaudRate := baudRate;
THIS^._Parity 	:= parity;
THIS^._DataBits := dataBits;
THIS^._StopBits := stopBits;
------
METHOD Open : BOOL
VAR_INPUT
END_VARADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com port name:%s', strArg := THIS^._PortName);
ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com baud rate:%s', strArg := TO_STRING(THIS^._BaudRate));
ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com parity:%s', strArg := TO_STRING(THIS^._Parity));
ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com data bits:%s', strArg := TO_STRING(THIS^._DataBits));
ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com stop bits:%s', strArg := TO_STRING(THIS^._StopBits));// 打开串口逻辑
// ************
// 打开串口逻辑
THIS^._IsConnected := TRUE;ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com state:%s', strArg := 'Opened');
------
METHOD SendData : STRING
VAR_INPUTdata	: STRING;
END_VAR// 串口发送数据逻辑
// ******************
// 串口发送数据逻辑ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com send data:%s', strArg := data);
------
METHOD Close : BOOL// 关闭串口逻辑
// ***********
// 关闭串口逻辑
THIS^._IsConnected := FALSE;ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Serial port com state:%s', strArg := 'Closed');

FB_Socket通讯实体类,实现I_Socket接口

FUNCTION_BLOCK FB_Socket IMPLEMENTS I_Socket
VAR_isConnect : BOOL;_ipAddress : STRING;_port	   : INT;
END_VAR
------
PROPERTY IpAddress : STRING
Get:IpAddress := THIS^._ipAddress;
------
PROPERTY Port : INT
Get:Port := THIS^._port;
------
PROPERTY IsConnected : BOOL
Get:IsConnected := THIS^._isConnect;
------
METHOD FB_init : BOOL
VAR_INPUTbInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)bInCopyCode : BOOL;  // if TRUE, the instance afterwards gets moved into the copy code (online change)ipAddress	: STRING; // IP地址port		: INT; // 端口号
END_VARTHIS^._ipAddress := ipAddress;
THIS^._port		 := port;
------
METHOD Connect : BOOL
VAR_INPUT
END_VARADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Socket ip address:%s', strArg := THIS^._ipAddress);ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Socket port:%s', strArg := TO_STRING(THIS^._port));// socket连接逻辑
// **************
// socket连接逻辑THIS^._isConnect := TRUE;ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Socket state:%s', strArg := 'Connected');
------
METHOD SendMessage : STRING
VAR_INPUTmessage	: STRING;
END_VAR// socket发送数据逻辑
// ******************
// socket发送数据逻辑
ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Socket send message:%s', strArg := message);
------
METHOD Disconnect : BOOL// socket断开连接逻辑
// **************
// socket断开连接逻辑
THIS^._isConnect := FALSE;ADSLOGSTR(msgCtrlMask :=ADSLOG_MSGTYPE_LOG, msgFmtStr :='Socket state:%s', strArg := 'DisConnected');
FUNCTION_BLOCK FB_SerialComAdapter IMPLEMENTS I_Communication
VAR_iSerialCom : I_SerialCom;
END_VAR
------
PROPERTY IsConnected : BOOL
Get:IsConnected := THIS^._iSerialCom.IsConnected;
------
METHOD FB_init : BOOL
VAR_INPUTbInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)bInCopyCode : BOOL;  // if TRUE, the instance afterwards gets moved into the copy code (online change)iSerialCom : I_SerialCom; // 串口通讯
END_VARTHIS^._iSerialCom := iSerialCom;
------
METHOD Connect : BOOLTHIS^._iSerialCom.Open();
------
METHOD Send : STRING
VAR_INPUTsContent	: STRING;
END_VARTHIS^._iSerialCom.SendData(sContent);
------
METHOD Disconnect : BOOLTHIS^._iSerialCom.Close();

Socket通讯适配器FB_SocketAdapter,实现I_Communication客户端接口

FUNCTION_BLOCK FB_SocketAdapter IMPLEMENTS I_Communication
VAR_iSocket : I_Socket;
END_VAR
------
PROPERTY IsConnected : BOOL
Get:IsConnected := THIS^._iSocket.IsConnected;
------
METHOD FB_init : BOOL
VAR_INPUTbInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)bInCopyCode : BOOL;  // if TRUE, the instance afterwards gets moved into the copy code (online change)iSocket : I_Socket; // Socket通讯
END_VARTHIS^._iSocket := iSocket;
------
METHOD Connect : BOOLTHIS^._iSocket.Connect();
------
METHOD Send : STRING
VAR_INPUTsContent	: STRING;
END_VARTHIS^._iSocket.SendMessage(sContent);
------
METHOD Disconnect : BOOLTHIS^._iSocket.Disconnect();

客户端主程序MAIN运行测试,声明fbSerialComfbSocket两个与客户端不同的接口通讯实例,并初始化连接参数。实例化FB_SerialComAdapterFB_SocketAdapter初始化分别传入fbSerialComfbSocket实例。客户端根据实际需求使用I_Communication接口接收适配器实例,执行ConnectSendDisconnect方法测试接口。

PROGRAM MAIN
VARfbSerialCom		: FB_SerialCom('COM1',9600,0,8,1);fbSocket		: FB_Socket('192.168.0.1',801);fbSerialComAdapter 	: FB_SerialComAdapter(fbSerialCom);fbSocketAdapter		: FB_SocketAdapter(fbSocket);iCommunication : I_Communication;bTest	 : BOOL;
END_VARIF bTest THENiCommunication := fbSerialComAdapter;iCommunication.Connect();iCommunication.Send('this is serial com data');iCommunication.Disconnect();iCommunication := fbSocketAdapter;iCommunication.Connect();iCommunication.Send('this is socket message');iCommunication.Disconnect();bTest := FALSE;
END_IF

日志输出结果:

MSG | 'PlcTask' (350): Serial port com port name:COM1
MSG | 'PlcTask' (350): Serial port com baud rate:9600
MSG | 'PlcTask' (350): Serial port com parity:0
MSG | 'PlcTask' (350): Serial port com data bits:8
MSG | 'PlcTask' (350): Serial port com stop bits:1
MSG | 'PlcTask' (350): Serial port com send data:this is serial com data
MSG | 'PlcTask' (350): Serial port com state:ClosedMSG | 'PlcTask' (350): Socket ip address:192.168.0.1
MSG | 'PlcTask' (350): Socket port:801
MSG | 'PlcTask' (350): Socket state:Connected
MSG | 'PlcTask' (350): Socket send message:this is socket message
MSG | 'PlcTask' (350): Socket state:DisConnected

日志输出结果显示,客户端接口I_Communication通过适配器FB_SerialComAdapterFB_SocketAdapter均可以正常工作,接口测试成功。

http://www.wxhsa.cn/company.asp?id=5557

相关文章:

  • DRAM、SRAM、NAND Flash、NOR Flash、EEPROM、MRAM存储器你分得清吗?
  • 【初赛】最短路 次短路 k短路 - Slayer
  • hyperv 安装 ubuntu 压缩磁盘
  • 【实战记录】使用 wp-cli 恢复/修改 WordPress 密码
  • Spring Boot 下 Druid 连接池:多维度优化打造卓越性能
  • 讨好型人格自救指南:重建健康自我与关系
  • vue3使用vue3-pdf-app预览pdf文档
  • 使用lvgl/lv_port_pc_visual_studio在PC上运行LVGL模拟器
  • 深入解析:Spring Boot 深入剖析:SpringApplicationRunListener
  • Hutool 调用第三方接口报错
  • 丑东西经济学:全面分析
  • 深入浅出 Java 多线程:从线程生命周期到并发安全
  • 儿童无屏幕对讲机 Bunny 融资百万美元;腾讯会议推出 AI 托管:先行听会、代听多会、全程记录丨日报
  • Python turtle 海龟画图入门指南
  • uni-app中v-if使用”异常”
  • 如何创建可引导的 macOS Tahoe 安装介质
  • 二叉树遍历
  • Python Socket网络编程(3)
  • 实用指南:有关gitlab14.x版本在内网环境下无法添加webhooks的解决方法
  • 强类型、类型安全
  • 完整教程:数据结构——逻辑结构物理结构
  • 前端面试
  • 外置Tomcat启动Springboot项目后,请求参数中文乱码的问题解决 - yjry
  • gradle项目多模块中主模块加载子模块中的sqlmapper文件方法
  • MCP - 使用 fastmcp 编写 Client 调用 MCP Serverr - Streamable HTTP (四)
  • 全面理解MySQL架构
  • Figma EX 125.7.5 UI原型设计
  • 基于WebSocket的命令与控制工具WSC2详解
  • LocalDateTime节日和平日在时间占比计算方法
  • JSON字符串转换List对象列表 JSONArray toJavaList