(delphi11最新学习资料) Object Pascal 学习笔记---第11章第3节(使用接口实现适配器模式)

11.3 使用接口实现适配器模式

​ 作为在现实世界中使用接口的一个例子,我在本章中增加了一节关于适配器模式的内容。简而言之,适配器模式用于将一个类的接口转换为该类用户所期望的另一个接口。这样,你就可以在一个需要定义接口的框架中使用现有的类。

​ 适配器模式可以通过映射的方式创建一个新的类层次结构来实现,或者通过扩展现有的类定义新的接口来实现。这可以通过多重继承(在支持多重继承的语言中)或使用接口来完成。在最后一种情况,也就是我在这里即将要使用的,一个新继承的类将实现给定的接口,并将现有的行为映射到它的方法中。

​ 在这个具体场景中,适配器提供了一个通用接口,可以查询多个组件的值,而这些组件的接口往往不一致(在用户界面库中经常出现这种情况)。我们定义的这个通用接口被称为 ITextAndValue,因为它允许通过获取文字描述或数字描述来访问组件的状态:

type
  ITextAndValue = interface
    '[51018CF1-OD3C-488E-81B0-0470B09013EB]'
    procedure SetText(const Value: string);
    procedure SetValue(const Value: Integer);
    function GetText: string;
    function GetValue: Integer;
    property Text: string read GetText write SetText;
    property Value: Integer read GetValue write SetValue;
  end;

​ 下一步是为使用该接口的每个组件创建一个新的子类。例如,我们可以编写:

type
  TAdapterLabel = class(TLabel, ITextAndValue)
  protected
    procedure SetText(const Value: string);
    procedure SetValue(const Value: Integer);
    function GetText: string;
    function GetValue: Integer;
  end;

​ 这四个方法的实现非常简单,因为它们可以映射到文本属性,在值(或文本)是数字的情况下执行类型转换。不过,现在你有了一个新组件,你必须安装它(正如我们在上一章中提到的上一章中提到的),并用这个新组件替换窗体中的现有组件。对每一个要适配的组件都进行重复同样的过程将会非常耗时。

​ 一个简单得多的替代方法是使用内插类(interposer class)(即定义一个与基类同名的类,但定义在不同的单元中)。这样编译器和运行时(runtime)的流系统识别。这样,在运行时你将得到一个新的特定类的对象。唯一的区别是,在设计时,你将看到基础组件类的实例并与之交互。

注解 Interposer 类是多年前在《Delphi 杂志》上首次被提及并命名的。它们当然有点像 “黑客”,但有时却很方便。我认为互斥类是 即与基类同名但定义在不同单元中的类,更像是对象 Pascal 的习语。请注意,要使这一机制发挥作用,关键是要将带有互斥类的单元 在 uses 语句中列在它应该替代的普通类的单元之后。换句话说,uses 语句中最后一个单元中定义的符号将取代之前包含的单元中定义的相同符号。当然,您也可以在符号前加上 单元名作为前缀来区分符号,但这样做就违背了这一 hack 的初衷,即利用全局名称解析规则的优势。

​ 要定义一个互斥类,通常需要编写一个新单元,单元中的类与现有基类的名称相同。要引用基类,必须在基类前加上单元名称的前缀(否则编译器会认为这是一个递归定义):

type
  TLabel = class(StdCtrls.TLabel, ITextAndValue)
  protected
    procedure SetText(const Value: string);
    procedure SetValue(const Value: Integer);
    function GetText: string;
    function GetValue: Integer;
  end;

​ 在这种情况下,你无需安装组件或修改现有程序,只需在列表末尾添加一个额外的 uses 语句即可。在两种情况下(在我编写的演示程序中使用了插接器类),您可以查询窗体中组件。例如,你编写代码将所有值设置为 50,这将影响不同组件的不同属性。

var
  Intf: ITextAndValue;
  I: integer;
begin
  for I := 0 to ComponentCount - 1 do
    if Supports(Components[I], ITextAndValue, Intf) then
      Intf.Value := 50;
end;

​ 上面这个示例中的代码将影响进度条或数字框的值,以及标签或编辑器的文本。它还会完全忽略其他几个我没有为其定义适配器接口的组件 。虽然这只是一个非常具体的案例,但如果你仔细研究其他的设计模式,你会很容易发现,在Object Pascal中,利用接口相对于类所拥有的额外灵活性(就像在Java和C#中那样,这里仅举两个广泛使用接口的流行语言为例),可以将它们更好地实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/619193.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解

JDBC 简化JDBC的开发 JDBC仅仅是一套接口 是一套规范 Mybatis是持久层框架 用于简化JDBC的开发 使用Java语言操作关系型数据库的一套API 原始的JDBC程序 package com.bigdate.mybatis;import com.bigdate.mybatis.mapper.UserMapper; import com.bigdate.mybatis.pojo.Use…

(二)Jetpack Compose 布局模型

前文回顾 (一)Jetpack Compose 从入门到会写-CSDN博客 首先让我们回顾一下上一篇文章中里提到过几个问题: ComposeView的层级关系,互相嵌套存在的问题? 为什么Compose可以实现只测量一次? ComposeView和…

【JVM】感觉弗如...类加载机制

【JVM】感觉弗如…类加载机制 在Java开发过程中,从源代码(.java文件)到字节码(.class文件)再到运行时的类加载,会经历几个关键步骤,我们先简单过一遍大体的过程。再介绍今天这篇博客的重点内容—…

几个字符串函数的使用和模拟实现(2)

strcop的使用和模拟实现 strcpy函数的使用事项: 源字符串时不需要修改的,在定义前加上const 源字符串被拷贝到目标字符串上时终止字符\0也被拷贝进去 目标数组的大小要相对于源数组的大小足够大,并且不应该在内存中重叠 函数的返回值是一个字…

【Unity】Unity项目转抖音小游戏(二)云数据库和云函数

业务需求,开始接触一下抖音小游戏相关的内容,开发过程中记录一下流程。 抖音云官方文档:https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/cloud-function-debug 1.开通抖音云环境 抖音云地址&a…

软件体系结构风格

目录 一、定义 二、.经典软件体系结构风格: 1.管道和过滤器 2.数据抽象和面向对象系统 3.基于事件系统(隐式调用) 4.分层系统 5.仓库 6.C2风格 7.C/S 8.三层C/S 9.B/S 题: 一、定义 软件体系机构风格是描述某一特定应用…

C#泛型委托

在C#中,delegate 关键字用于声明委托(delegates),委托是一种类型安全的函数指针,允许你传递方法作为参数或从方法返回方法。有时我们需要将一个函数作为另一个函数的参数,这时就要用到委托(Dele…

java项目之车辆管理系统(springboot+vue+mysql)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的车辆管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 车辆管理系统的主要使用者分…

Deckset for Mac:让演示文稿制作更轻松

还在为繁琐的演示文稿制作而烦恼吗?Deckset for Mac来帮您解决!它支持Markdown语言,让您只需专注于内容的创作,无需在排版和设计上耗费过多精力。丰富的主题和布局选项,让您能够轻松打造出专业级的演示文稿。快来体验D…

云计算第十二课

安装虚拟机 第一步新建虚拟机 选择自定义安装 下一步 选择稍后安装操作系统 选择系统类型和版本 选择虚拟机文件路径(建议每台虚拟机单独存放并且路径不要有中文)点击下一步 选择bios下一步 选择虚拟机处理器内核数量 默认硬盘或者自行调大硬盘 选择虚…

软件测试的分类

1.用户分类 2.查看代码分类 3.阶段分类

云计算十三课

centos安装 点击左上角文件 点击新建虚拟机 点击下一步 点击稍后安装操作系统,下一步 选择Linux(l)下一步 设置虚拟机名称 点击浏览选择安装位置 新建文件夹设置名称不能为中文,点击确定 点击下一步 设置磁盘大小点击下一步…

4.1 编写程序,从键盘接收一个小写字母,然后找出他的前导字符和后续字符,再按顺序显示这三个字符

方法一: 运行效果: 输入B,输出显示ABC;输入A,输出显示AB 思路: 1、通过键盘输入接收一个字母。 2、将输入的字母减去1,得到前导字符,然后输出。 3、将输入的字母加上1,得…

【python量化交易】qteasy使用教程07——创建更加复杂的自定义交易策略

创建更加复杂的自定义交易策略 使用交易策略类,创建更复杂的自定义策略开始前的准备工作本节的目标继承Strategy类,创建一个复杂的多因子选股策略策略和回测参数配置,并开始回测 本节回顾 使用交易策略类,创建更复杂的自定义策略 …

(四十)第 6 章 树和二叉树(树的双亲表存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

基于yolov5+streamlit目标检测演示系统设计

YOLOv5与Streamlit&#xff1a;智能目标检测可视化展示介绍 随着人工智能技术的飞速发展&#xff0c;目标检测技术已成为推动智能化社会进步的关键技术之一。在众多目标检测算法中&#xff0c;YOLOv5以其卓越的性能和实时性&#xff0c;成为了业界的佼佼者。与此同时&#xff…

代码随想录阅读笔记-动态规划【爬楼梯】

题目 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a;给定 n 是一个正整数。 示例 1&#xff1a; 输入&#xff1a; 2输出&#xff1a; 2解释&#xff1a; 有两种方法可以爬到楼…

[AutoSar]BSW_Diagnostic_002 DCM模块介绍

目录 关键词平台说明背景一、DCM所处架构位置二、DCM 与其他模块的交互三、DCM 的功能四、DCM的内部子模块4.1 Diagnostic Session Layer (DSL)4.1 DSL 与其他模块的交互 4.2 Diagnostic Service Dispatcher (DSD)4.3 Diagnostic Service Processing (DSP)4.4 小结 关键词 嵌入…

vue3土味情话pinia可以持久保存再次修改App样式

我是不是你最疼爱的人-失去爱的城市 <template><div class"talk"><button click"getLoveTalk">土味情话</button><ul><li v-for"talk in talkStore.talkList" :key"talk.id">{{ talk.title }}<…

计算机服务器中了360后缀勒索病毒怎么解密,360后缀勒索病毒恢复

计算机网络技术的不断发展与应用&#xff0c;为企业的生产运营提供了极大便利&#xff0c;大大提高了企业的办公效率&#xff0c;为企业的生产运营注入了新的动力&#xff0c;但网络是一把双刃剑&#xff0c;在为企业提供便利的同时&#xff0c;也为企业的数据安全带来严重威胁…