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程序打包exe,单文件和多文件方式

《Python程序打包exe,单文件和多文件方式》:本文主要介绍Python程序打包exe,单文件和多文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python 脚本打成exe文件安装Pyinstaller准备一个ico图标打包方式一(适用于文件较少的程

Python程序的文件头部声明小结

《Python程序的文件头部声明小结》在Python文件的顶部声明编码通常是必须的,尤其是在处理非ASCII字符时,下面就来介绍一下两种头部文件声明,具有一定的参考价值,感兴趣的可以了解一下... 目录一、# coding=utf-8二、#!/usr/bin/env python三、运行Python程序四、

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

SpringBoot后端实现小程序微信登录功能实现

《SpringBoot后端实现小程序微信登录功能实现》微信小程序登录是开发者通过微信提供的身份验证机制,获取用户唯一标识(openid)和会话密钥(session_key)的过程,这篇文章给大家介绍S... 目录SpringBoot实现微信小程序登录简介SpringBoot后端实现微信登录SpringBoo

uniapp小程序中实现无缝衔接滚动效果代码示例

《uniapp小程序中实现无缝衔接滚动效果代码示例》:本文主要介绍uniapp小程序中实现无缝衔接滚动效果的相关资料,该方法可以实现滚动内容中字的不同的颜色更改,并且可以根据需要进行艺术化更改和自... 组件滚动通知只能实现简单的滚动效果,不能实现滚动内容中的字进行不同颜色的更改,下面实现一个无缝衔接的滚动

Java使用WebView实现桌面程序的技术指南

《Java使用WebView实现桌面程序的技术指南》在现代软件开发中,许多应用需要在桌面程序中嵌入Web页面,例如,你可能需要在Java桌面应用中嵌入一部分Web前端,或者加载一个HTML5界面以增强... 目录1、简述2、WebView 特点3、搭建 WebView 示例3.1 添加 JavaFX 依赖3

防止SpringBoot程序崩溃的几种方式汇总

《防止SpringBoot程序崩溃的几种方式汇总》本文总结了8种防止SpringBoot程序崩溃的方法,包括全局异常处理、try-catch、断路器、资源限制、监控、优雅停机、健康检查和数据库连接池配... 目录1. 全局异常处理2. 使用 try-catch 捕获异常3. 使用断路器4. 设置最大内存和线

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序