用 Ruby 踩踩四人帮
来源:互联网 发布:大兴灭门案 知乎 编辑:程序博客网 时间:2024/06/05 16:27
上上周在书店看到一本《Ruby设计模式》,捡起来 10 分钟看完,扔了(别问我为什么……)
下面用 Ruby 写写设计模式,顺便批一批 Java 和 Gof。
1.Factory 和 Abstract Factory
class Factory attr_accessor :product def produce @product.new endendclass Product #..endfac = Factory.newfac.product = Productfac.produce
Java写的工厂有这么简单,这么容易重用么?
2.Builder
# 工头class Director def build_with builderacc = ''[:header, :body, :footer].each do |m| acc += builder.__send__ m if builder.respond_to? mendacc endend# 工人class HTMLBuilder def header; '<html><title>html builder</title>';end def body; '<body>html builder</body>' ;end def footer; '</html>' ;endendclass XMLBuilder def header; '<?xml version="1.0" charset="utf-8">';end def body; '<root>xml builder</root>' ;endendd = Director.newputs(d.build_with HTMLBuilder.new)puts(d.build_with XMLBuilder.new)
注意:Ruby的工序并不依赖于Builder的类,只要有方法签名就行了。
interface 这种束手束脚,加强耦合的东西完全不需要~
3.Prototype
依样画葫芦。
这里用一点 trick (evil ruby):
require 'evil'class Prototype # ...endclass Concrete include Prototype.as_moduleend
4.Adapter
Ruby 包装方法易如反掌:
class Adaptee def talk; puts 'Adaptee';endendclass Adapter < Adaptee alias talkee talk def talkputs 'before Adaptee'talkeeputs 'after Adaptee' endendAdapter.new.talk
很多没学过设计模式的 Ruby 程序员天天用 adapter……
5.Composite
这个 pattern 是给没有多重继承又没法 mixin 的语言用的。
Ruby 只需要 include module。
6.Decorator
module Colorful attr_acessor :colorendclass Widgetendw = Widget.new # w 作为 Widget 的实例,没有 color 方法w.color = 'blue' rescue puts 'w has no color'w.extend Colorful # 现在 w 有 color 方法了w.color = 'blue'puts w.color
可怜的 Java 程序员需要学习设计模式才能写出 decorator。
7.Flyweight
# 重量级对象的瘦身法:如果创建参数相同,则返回同一个对象class FlyweightFactory class Glyphdef initialize key @key = key sleep 1 # 睡一秒,以体现这个对象创建的“重量级” @square = key ** 2 @cubic = key ** 3endattr_reader :key, :square, :cubic end def produce key@glyphs ||= {} @glyphs[key] || (@glyphs[key] = Glyph.new key) endendff = FlyweightFactory.newg1 = ff.produce 2g2 = ff.produce 2puts (g1.object_id == g2.object_id)
不得不说 || 是很爽的语法。
另外 Ruby 的 Hash 可以用数组作 key,如果 Glyph 的构造函数需要更多参数,只需要把 produce 里的 key 改成 *key
8.Proxy
Proxy 和 Adapter 的区别只在接口上,它们在 Ruby 中是一样的。
这说明了:1.大道至简; 2.Gof 模式的语言局限性。
9.Chain of Responsibility
如果没有 proc,代码是做不到这么清晰简洁的:
class Chain def initialize@chain = [] end def add_handler &block@chain << block end def handle req@chain.each do |e| # 如果handler返回 false(未处理),则让下一个处理 result = e[req] return result if resultendfalse endendc = Chain.newc.add_handler {|req| req == 1 ? "1:handled" : puts "1:not my responsibility" }c.add_handler {|req| req == 2 ? "2:handled" : puts "2:not my responsibility" }puts(c.handle 1)puts(c.handle 2)
10.Command
本质:一次调用可以同时执行多个方法。GUI 编程中处理事件很常用。
因为 Java 不能直接传递方法,所以把简单的问题复杂化了……
btw:真不理解 swing 优美在哪里……
class Command def initialize@executors = [] end # 另一种方法是让 executors 保存一组对象,每个都带 execute 方法 # ——但是这么简单的事情就需要一组接口,一组实现? def add_executor &block@executors << block end def execute@executors.each {|x| x.call } endendc = Command.newc.add_executor{ puts 'executor 1' }c.add_executor{ puts 'executor 2' }c.execute
Command 是和 Chain 很相似的东西,可能某天会有人写一本 "Pattern of Patterns" 吧。
11.Template Method
Java 一说模板,C++ 和 Ruby 就笑了。
例(偷懒“重用”一下写过的代码):
# 穷举法检验 de Morgan 定理class Fixnum %w[a1 a2 a3 b1 b2 b3].each_with_index do |name, idx| define_method name, do self & (1<<idx) == 0 ? false : true end endend0b1000000.times do |n| n.instance_eval %q[ if !((a1&&b1) || (a2&&b2) || (a3&&b3)) != !(a1&&b1) && !(a2&&b2) && !(a3&&b3) puts 'blah' end ]end
12.Iterator 和 Visitor
这些模式还是作古吧。
有太多简单的方式进行迭代(map, inject, each, each_with_index,sort ...)
关键点还是语言对泛型和匿名函数的支持。
13.Mediator
将各个类的相互依赖性扔到一个中介类之中。
老老实实的写个中介类?大概会像这样:
class Mediator def initialize seller, buyer@seller = seller@buyer = buyer end def sell@seller.sell end def buy@buyer.buy endend
发现问题了吗? Mediator 出现的根源还是静态类型(是不会推断的那种)带来的耦合。
Duck Typing (check respond_to? instead of class) 早已解耦,根本不需要中介。
14.Strategy
提供运行时选择策略(算法)的可能。
假设 Array 有两种方法:bubble_sort 和 quick_sort
按照 Gof 的教诲,我们可能会这样想:
class Array def sort optionsif options[:strategy].to_sym == :bubble_sort bubble_sort() elsif options[:strategy].to_sym == :quick_sort quick_sort()end endendarr.sort :strategy => strategy
根本就是没事找事……看看 Ruby 动态选择调用方法多简单:
arr.__send__ strategy
15.Singleton
module SingletonClass class << self# methods endend
听说有人用两百行实现了严格的 singleton,膜拜中。
结论:
如果没有类型声明和继承,很多依赖性都会消失无踪,接口也无用武之地了。
设计模式大都是 Interface Hack 汇总,枯燥无味、思想僵化、限制创造力,早该下架了。
学设计模式不如学 Ruby Python。
Java 语言(注意不是平台)的弱点导致大量的冗余代码。
所谓从善如流,有功夫写冗余代码不如多写几个测试。
Java 语言(注意不是平台)的历史意义在于:将程序员从过早考虑效率的传统中解放了出来,现在也该功成身退了。
- 用 Ruby 踩踩四人帮
- 踩踩
- 踩踩踩踩
- 踩踩踩
- 踩踩图片
- 悠纸读巢赵磷脑惹捌号饺尘郊踩踩
- 四人帮重聚首...^^
- 设计模式四人帮
- 大家多来踩踩
- 欢迎大家来踩踩
- 方正“四人帮”是何许人也?
- 新手,希望常来踩踩!
- 新来咋到,欢迎朋友们来踩踩
- 好久没有来踩踩了
- 欢迎大家多来踩踩~
- 促成华国锋和叶剑英联手粉碎四人帮?
- 方正李友“四人帮”的覆没记
- 方正“四人帮”打造校内“利益生态圈”
- overflow hidden td
- 演练:使用 XCOPY 部署 ASP.NET Web 应用程序
- 修改PhpMyAdmin数据导入大小限制
- XMLHttpRequest跨浏览器问题
- 65个源代码网站
- 用 Ruby 踩踩四人帮
- BUG: Internet Explorer Fails to Set the innerHTML Property of the Select Object
- BUFFER CACHE和SHARED POOL原理--《深入浅出ORACLE第五章》
- 模糊查询, ], [, 中括号, square bracket
- 硬件知识——CPU
- 43 Web Design Mistakes You Should Avoid By Jay White
- ZOJ题目分类 pku题目分类
- Mozilla DPI-related Font Size Issues on Unix
- RedHat平台下pureftpd搭建