Ruby装饰模式应用技巧分享

开发 开发工具
Ruby装饰模式是设计模式的一种。在实际应用中可以像被装饰的对象一下工作,并且其保持某些恒等性是非常好的。不过它并不是在运行时唯一的方法。

Ruby语言中,是一种比较简便的编程语言。我们可以通过它在编程中获得很大的快乐感。在这里我们会未大家介绍一下Ruby装饰模式的相关应用技巧。#t#

Ruby装饰模式是设计模式之一,它允许你在运行时动态地为一个存在的对象添加特性.在一个对象有很多种可以有不同方式组合的可以影响其特性的

变量时特别有用(dingsea:没看懂?翻译这段比较YY,以上大概是出版社的风格,其实用例子比较容易理解,向下看)

这个短小精悍的Ruby装饰模式实现,总结了这个星球上我***的最火的动态语言.
我从Eric Freeman, Elisabeth Freeman, Kathy Sierra, 和Bert Bates他们写的杰出的Head First Design Patterns 一书中借取一个例子.

假设你要计算一杯咖啡的价钱.你有一个实现了cost()方法的咖啡类.此例中我们出于示例目的硬编码其价格:

 

  1. class Coffee  
  2. def cost  
  3. 2  
  4. end  
  5. end 

很好.不过如果我们要知道一杯加奶的咖啡多少钱怎么办?我们有一个新类:

 

  1. class WhiteCoffee  
  2. def cost  
  3. 2.4  
  4. end  
  5. end 

好,但是现在我们要加奶油的咖啡怎么办?再要撒些东西在上边呢?(原文"And sprinkles",个人理解,欢迎讨论).明显地,不停地创建新类会导致在应用中出现类爆炸.为不同的咖啡和其调料(糖,奶...)组合创建新类是不现实的,这样会变糟糕--如果我们有不同种类的咖啡怎么办?然后我们

还不得不加一些调料在这些不同的咖啡中.这不是一个好办法.下面进入Ruby装饰模式.像本文题目提到的那样,这就是Ruby的8行代码实现:

  1. module Decorator  
  2. def initialize(decorated)  
  3. @decorateddecorated = decorated  
  4. end  
  5. def method_missing
    (method, *args)  
  6. args.empty? ? @decorated.send
    (method) : @decorated.send
    (method, args)  
  7. end  
  8. end 

 

这就是你所要的.你可以在任何你想要装饰的类中包含以上module.然后你可以使用这个装饰者就像直接使用装饰好的对象一样,默认地,所有传到装饰者的信息都会被转到被装饰的对象那儿.你可以根据需要装饰你的方法用来扩展:

 

  1. class Milk  
  2. include Decorator  
  3. def cost  
  4. @decorated.cost + 0.4  
  5. end  
  6. end 

那么怎样解决我们刚开头的咖啡问题呢?Ruby装饰模式在实战中的强大之处就在于他们可以像被装饰的对象一样工作(dingsea:嗯,大概是说,类A,被装饰过后,客户代码认为它还是A,呵呵).通过更进一步,你可以装饰其它的装饰者,只要它们有同样的接口.通过为不同的"扩展"创建装饰者,我们可以使用组合的装饰者创建咖啡类并计算此咖啡的总价.

 

  1. class Whip  
  2. include Decorator  
  3. def cost   
  4. @decorated.cost + 0.2  
  5. end  
  6. end  
  7. class Sprinkles  
  8. include Decorator  
  9. def cost  
  10. @decorated.cost + 0.3  
  11. end  
  12. end  
  13. Whip.new(Coffee.new).cost  
  14. #=> 2.2  
  15. Sprinkles.new(Whip.new
    (Milk.new(Coffee.new))).cost  
  16. #=> 2.9 

 

当然,为方便着想我们情不自禁创建几个工厂方法:

  1. class CoffeeFactory  
  2. def self.latte  
  3. SteamedMilk.new(Espresso.new)  
  4. end  
  5.  
  6. def self.cappuccino  
  7. Sprinkles.new(Cream.new
    (Milk.new(Coffee.new)))  
  8. end  
  9. end  
  10.  
  11. order = Order.new  
  12. order.add(Coffee.new)  
  13. order.add(CoffeeFactory
    .cappuccino)  
  14. puts order.total 

 

由于Ruby的高动态语言特性,装饰模式并不是在运行时扩展类的唯一方法,当然,我只是喜欢ruby中用如此简单的方法实现一个模式.在ruby中有关装饰模式的更多信息和实现,包括generic decorators和可选择的传统装饰模式,请参考DecoratorPattern page at the RubyGarden.

***,在使用Ruby装饰模式时保持某些恒等性是很好的.上边提到的RubyGarden的网页里是其中一种方法.同时我们没有使用继承,保留继承这一特性是很好的:

 

  1. CoffeeFactory.
    cappucino.kind_of? Coffee  
  2. #=> true 

 

责任编辑:曹凯 来源: 博客园
相关推荐

2009-12-15 10:23:23

Ruby应用技巧

2009-12-15 18:24:02

Ruby连接到orac

2009-12-15 18:15:24

Ruby连接到LDAP

2009-12-16 10:10:16

Ruby打开关闭文件

2009-12-17 10:18:17

Ruby创建构造器

2009-12-18 14:10:29

Ruby访问剪贴板

2009-12-16 11:04:51

Ruby操作文件权限

2009-12-15 14:51:50

Ruby继承

2009-12-17 17:37:42

Ruby on Rai

2009-12-16 15:46:41

Ruby on rai

2009-12-15 09:56:51

Ruby流程控制

2009-12-16 10:49:42

Ruby操作二进制文件

2009-12-30 18:23:13

Silverlight

2009-12-29 17:56:47

Silverlight

2010-01-25 11:09:58

Android Htt

2010-02-01 11:13:00

C++ Traits

2009-12-29 16:08:41

Silverlight

2010-01-25 16:08:37

Android ADB

2009-12-31 17:00:40

Silverlight

2010-01-25 17:21:34

Android Act
点赞
收藏

51CTO技术栈公众号