目录搜索
Ruby用户指南3、开始4、简单的例子5、字符串6、正则表达式7、数组8、回到那些简单的例子9、流程控制10、迭代器11、面向对象思维12、方法13、类14、继承15、重载方法16、访问控制17、单态方法18、模块19、过程对象20、变量21、全局变量22、实变量23、局部变量24、类常量25、异常处理:rescue26、异常处理:ensure27、存取器28、对象的初始化29、杂项RGSS入门教程1、什么是RGSS2、开始:最简单的脚本3、数据类型:数字4、数据类型:常量与变量5、数据类型:字符串6、控制语句:条件分歧语句7、控制语句:循环8、函数9、对象与类10、显示图片11、数组12、哈希表(关联数组)13、类14、数据库15、游戏对象16、精灵的管理17、窗口的管理18、活动指令19、场景类Programming Ruby的翻译Programming Ruby: The Pragmatic Programmer's Guide前言RoadmapRuby.new类,对象和变量容器Containers,块Blocks和迭代Iterators标准类型深入方法表达式Expressions异常,捕捉和抛出(已经开始,by jellen)模块基本输入输出线程和进程当遭遇挫折Ruby和它的世界Ruby和Web开发Ruby TkRuby 和微软的 Windows扩展RubyRuby语言 (by jellen)类和对象 (by jellen)Ruby安全反射Reflection内建类和方法标准库OO设计网络和Web库Windows支持内嵌文档交互式Ruby Shell支持Ruby参考手册Ruby首页卷首语Ruby的启动环境变量对象执行结束时的相关处理线程安全模型正则表达式字句构造程序变量和常数字面值操作符表达式控制结构方法调用类/方法的定义内部函数内部变量内部常数内部类/模块/异常类附加库Ruby变更记录ruby 1.6 特性ruby 1.7 特性Ruby术语集Ruby的运行平台pack模板字符串sprintf格式Marshal格式Ruby FAQRuby的陷阱
文字

Object-Oriented Design Libraries



One of the interesting things about Ruby is the way it blurs the distinction between design and implementation. Ideas that have to be expressed at the design level in other languages can be implemented directly in Ruby.

To help in this process, Ruby has support for some design-level strategies.

  • The Visitor pattern (Design Patterns, ) is a way of traversing a collection without having to know the internal organization of that collection.
  • Delegation is a way of composing classes more flexibly and dynamically than can be done using standard inheritance.
  • The Singleton pattern is a way of ensuring that only one instantiation of a particular class exists at a time.
  • The Observer pattern implements a protocol allowing one object to notify a set of interested objects when certain changes have occurred.

Normally, all four of these strategies require explicit code each time they're implemented. With Ruby, they can be abstracted into a library and reused freely and transparently.

Before we get into the proper library descriptions, let's get the simplest strategy out of the way.

The Visitor Pattern

It's the method each.

Library: delegate

Object delegation is a way of composing objects---extending an object with the capabilities of another---at runtime. This promotes writing flexible, decoupled code, as there are no compile-time dependencies between the users of the overall class and the delegates.

The Ruby Delegator class implements a simple but powerful delegation scheme, where requests are automatically forwarded from a master class to delegates or their ancestors, and where the delegate can be changed at runtime with a single method call.

The delegate.rb library provides two mechanisms for allowing an object to forward messages to a delegate.

  1. For simple cases where the class of the delegate is fixed, arrange for the master class to be a subclass of DelegateClass, passing the name of the class to be delegated as a parameter (Example 1). Then, in your class's initialize method, you'd call the superclass, passing in the object to be delegated. For example, to declare a class Fred that also supports all the methods in Flintstone, you'd write

    class Fred < DelegateClass(Flintstone)
      def initialize
        # ...
        super(Flintstone.new(...))
      end
      # ...
     end
    
    This is subtly different from using subclassing. With subclassing, there is only one object, which has the methods and the defined class, its parent, and their ancestors. With delegation there are two objects, linked so that calls to one may be delegated to the other.

  2. For cases where the delegate needs to be dynamic, make the master class a subclass of SimpleDelegator (Example 2). You can also add delegation capabilities to an existing object using SimpleDelegator (Example 3). In these cases, you can call the __setobj__ method in SimpleDelegator to change the object being delegated at runtime.

Example 1. Use the DelegateClass method and subclass the result when you need a class with its own behavior that also delegates to an object of another class. In this example, we assume that the @sizeInInches array is large, so we want only one copy of it. We then define a class that accesses it, converting the values to feet.

require 'delegate'

sizeInInches = [ 10, 15, 22, 120 ]

class Feet < DelegateClass(Array)   def initialize(arr)     super(arr)   end   def [](*n)     val = super(*n)     case val.type     when Numeric; val/12.0     else;         val.collect {|i| i/12.0}     end   end end

sizeInFeet = Feet.new(sizeInInches)
sizeInInches[0..3]
上一篇:下一篇: