Ruby中的设计模式——《松本行弘的程序世界》

2024-04-27 08:08

本文主要是介绍Ruby中的设计模式——《松本行弘的程序世界》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    《 设计模式 一书是用C++ Smalltalk 介绍模式实例的。看了那些例子,大家都会感觉到,绝大多数的模式用 Smalltalk 实现起来非常简单。这是为什么呢?

         因为Smalltalk 没有静态类型,所以也就不需要匹配类型的模板等机制,也不需要仅仅为满足类型要求而进行继承,这就是 Smalltalk 简单的理由。而且,由于语言本身的动态性质,有些模式根本不必要以模式的形式来抽象出来就可以得到简洁的实现,这也是 Smalltalk 显得简单的原因之一。

         Ruby在很多方面很像 Smalltalk ,实现设计模式也毫无困难。一般说来,用 Ruby 来实现设计模式的场合,要比 C++ 简洁得多,有些模式用现成的库就足以表现。

         下面以Ruby 为中心,让我们来看几个在实际设计中 用设计模式的例子。


Singleton( 单件 模式

 

    首先, 让我们来看一下最简单的设计模式之一,Singleton 模式。 Singleton 模式用来保证某个类的实例只有一个。

         为什么需要Singleton 模式呢?比如作为其他对象的雏形而存在的对象(用于 Prototype 模式),系统全体只存在唯一一个的对象等,都要用到 Singleton 模式。

         用Ruby 实现 Singleton 模式的方法有几个 让我们按顺序来逐一说明。

使用singleton 库的方法

         Ruby已经以库的形式实现了 Singleton 模式。如图 4-1 所示,使用singleton 库的话,在任意的类里只要包含( include )上 Singleton 模块,那个类就变成了 Singleton 模式的对象。

         要想取得Singleton 模式的类的对象,像图 4-1 最后一行那样,使用该类的 instance 方法。如果该类对象还没有生成, instance 方法会生成该类对象并返回。如果该类对象已经生成, instance 方法就返回既有对象。

使用类或模块

         C++ Java 是不能把类作为对象来使用的,与之不同的是, Smalltalk Ruby 能把类也作为对象来处理。因此,在类或模块里定义一个方法就可以实现 Singleton 模式( 参见 4- 2)。

4-1  使用 singleton 库的 Ruby 代码

4-2  利用类定义来实现 Singleton 模式的代码

把一般的对象作为Singleton 来使用

        为了把一个类的对象限制成只有一个,并不一定需要对对象的一般生成方法加以限制。我们可以生成一个一般的对象,然后遵守绅士协定,不要再生成 其他更 多个对象,也就 了( 参见 4- 3)。

使用对象和特异方法

         其实还有不用类就可以实现的方法。Ruby 可以在对象生成之后再增加新的方法,这样我们就可以生成一个 Object 类的对象,然后给它追加必要的功能( 参见 4- 4)。

4-3  在编程上下点功夫来实现 Singleton 模式

4-4  利用特殊方法来实现 Singleton 模式的代码

         这种使用特异方法的办法是很符合Ruby 特征的。 Ruby 自身的 main (最高层的 self ARGF 虚拟文件,用来代表参数所指定的文件 等也都是用这种方法实现的。


Proxy( 代理 模式

          Proxy模式是为某个对象提供代理对象的模式。为什么需要 Proxy 模式呢?

         假设有个生成代价非常大的对象。 如果 在还不知道是否真正需要该对象的时候就事先生成它的话,可能会带来很大的浪费。但话虽这么说,不生成对象的话什么事也做不了。这时候代理对象就有用武之地了。

         比如字处理软件,它利用Proxy 对象来处理嵌入图像,把嵌入图像的生成处理延迟到需要表示的瞬间才来进行。

         Ruby的库中也有使用 Proxy 模式的。比如 tempfile 库,它不用指定文件名就可以生成临时的工作文件( 参见 4- 5)。

         Tempfile类与实际负责文件输出的 IO 类没有继承关系,它的有关输入、输出处理的方法都通过 Proxy 转送到实际的 IO 类对象。因此,通过使用 Tempfile 类的对象,在任何有必要的时候也都可以使用相关的 IO 对象。

         Proxy模式也可以用 Ruby 的库来实现。使用 delegate 库就可以了。 delegate 是委托的意思。 Tempfile 类也是用 delegate 库来实现的( 参见 4- 6)。

4-5  采用 Proxy 模式的 tempfile 库的使用示例

4-6  使用 delegate 库来实现 Proxy 模式的例子

 

         看一下就知道,delegate 库的源代码是相当复杂的,但基本上只是把被调用的方法都转送到本来的对象那里去。这里使用的是 Ruby method_   missing 方法。

          Ruby中对对象 A 调用它所不知道的方法的时候, A method_missing 方法就会被调用。传递给 method_mis sing 的参数是在原来调 用方法的参数之前加上不存在的方法名。利用这一框架就可以很简单地实现Proxy 模式( 参见 4-7 )。

         怎么样,真的是非常简单吧。但是,这种实现方式也有不灵光的时候。Proxy 类固有的方法被调用的时候,是不会转送到 method_missing 方法的。也就是说,Proxy 类的父类 Object 类的方法是转送不了的。

4-7  使用 method_missing 方法来实现Proxy 模式的例子

         如果这样的情况也要对应的话,就会稍微麻烦一些。实际上,delegate 库除了空行和注释以外,长达 114 行。比图 4-7 要复杂得多。

         delegate库使用起来虽然很简单,但方法转送的对象仅限于既有的对象。因此,在最开始举的字处理软件例子中,要想达到延迟图像生成的目的,直接使用 delegate 是不行的。我们可以像图 4-8 那样,从Delegator 派生一个子类 ImageProxy 来达到这一目的。

    __getobj__ 方法是Delegator 对象取得方法转送对象的方法。通过 重写 这个方法,ImageProxy 会在实际访问图像对象的时候才来生成图像对象。 C++ 会用 operator-> 或者 operator* 来代替 __getobj__

4-8   Proxy 模式延迟对象生成的例子


Iterator( 迭代器 模式

         Iterator模式提供按顺序访问包含有多个对象的集合对象中各元素的方法。即使不知道对象的内部构造,也可以按顺序访问其中的每个元素。 Iterator 模式是为集合对象另外准备用来控制循环处理的对象,就像 C++ Java 一样。我们称这个循环控制对象为 Iterator 。也称为光标。

         图 4-9 Iterator 模式的类构成图。调用集合对象(图 4-9 Iteratable )的 Create Iterator() 方法,就会返回自己对应的Iterator 对象。 Iterator 对象会记住现在所指向的 Iteratable 元素,调用 Next() 方法可以返回集合的下一个元素。要想知道集合中是否还有别的元素,可以调用 IsDone() 方法来确认。图 4-10 是利用Iterator 模式的程序示例。 Iterator 模式实现的是所谓外部迭代器的循环控制抽象化。

4-9   J ava Iterator 模式的类构成图

4-10   Java 版外部迭代器的用法

         而Ruby 是用块来对集合的各元素进行循环处理的。作为设计模式,使用块进行循环的抽象化属于 Visitor (访问者)模式。但因为语言本身就支持这样的循环,所以也就不需要 Iterator 这样的对象了。这实在是太基本的东西了,也许都不应该称之为设计模式了。

这篇关于Ruby中的设计模式——《松本行弘的程序世界》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/939949

相关文章

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

EMLOG程序单页友链和标签增加美化

单页友联效果图: 标签页面效果图: 源码介绍 EMLOG单页友情链接和TAG标签,友链单页文件代码main{width: 58%;是设置宽度 自己把设置成与您的网站宽度一样,如果自适应就填写100%,TAG文件不用修改 安装方法:把Links.php和tag.php上传到网站根目录即可,访问 域名/Links.php、域名/tag.php 所有模板适用,代码就不粘贴出来,已经打

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

这些心智程序你安装了吗?

原文题目:《为什么聪明人也会做蠢事(四)》 心智程序 大脑有两个特征导致人类不够理性,一个是处理信息方面的缺陷,一个是心智程序出了问题。前者可以称为“认知吝啬鬼”,前几篇文章已经讨论了。本期主要讲心智程序这个方面。 心智程序这一概念由哈佛大学认知科学家大卫•帕金斯提出,指个体可以从记忆中提取出的规则、知识、程序和策略,以辅助我们决策判断和解决问题。如果把人脑比喻成计算机,那心智程序就是人脑的

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:'error'是设置我们失败的logo 设置的文字上限是7个文字,如果需要设置的提示文字过长就需要设置icon并给

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于