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

相关文章

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

【网络安全的神秘世界】搭建dvwa靶场

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 下载DVWA https://github.com/digininja/DVWA/blob/master/README.zh.md 安装DVWA 安装phpstudy https://editor.csdn.net/md/?articleId=1399043

C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录 一,指针的回忆杀1,指针的概念2,指针的声明和赋值3,指针的使用3.1 直接给指针变量赋值3.2 通过*运算符读写指针指向的内存3.2.1 读3.2.2 写 二,二级指针详解1,定义2,示例说明3,二级指针与一级指针、普通变量的关系3.1,与一级指针的关系3.2,与普通变量的关系,示例说明 4,二级指针的常见用途5,二级指针扩展到多级指针 小结 C语言的学习之旅中,二级

美容美发店营销版微信小程序源码

打造线上生意新篇章 一、引言:微信小程序,开启美容美发行业新纪元 在数字化时代,微信小程序以其便捷、高效的特点,成为了美容美发行业营销的新宠。本文将带您深入了解美容美发营销微信小程序,探讨其独特优势及如何助力商家实现业务增长。 二、微信小程序:美容美发行业的得力助手 拓宽客源渠道:微信小程序基于微信社交平台,轻松实现线上线下融合,帮助商家快速吸引潜在客户,拓宽客源渠道。 提升用户体验:

程序人生--拔丝地瓜

一个会享受生活的人,难免会执迷于探索“三餐茶饭,四季衣裳”的朴素涵义。如今在这繁杂喧闹、竞争激烈的社会环境里,如何才能从周而复始的生活中挖掘出一点儿期待!这是一个仁者见仁智者见智的开放性话题。对于大部分的人来说,看电影、运动、旅游、美食、加班....是假日的备选安排。 春节临走之前,再次尝试“拔丝地瓜”,为何要强调“再次”二字?因为这道甜菜我已经尝试过很多次,失败与成功都经历过。十几年的烧饭经历

每日一练:攻防世界:5-1 MulTzor

一、XorTool 基于 XOR(异或)运算实现。它可以帮助您快速地对文本、二进制文件进行加密解密操作。 认识XorTool工具: 让我们先去认识一下工具: xortool.py 是基于 python 的脚本,用于完成一些 xor 分析,包括: 猜想 key 的长度 猜想 key 的值 解密一些经过 xoe 加密的文件 也就是说当遇到不知道文件类型的文件,可以尝试去看看它是否被xo

vscode python pip : 无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

在vscode中控制台运行python文件出现:无法将"pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 使用vscode开发python,需要安装python开发扩展: 本文已经安装,我们需要找的是python安装所在目录,本文实际路径如下: 如果在本文路径中没有此目录,请尝试在C盘中搜索 python,搜索到相关python目录后,点击Python 3.9进入目录,