`
chenjinlai
  • 浏览: 69837 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

design patterns in ruby 读书笔记二

阅读更多
传统的proxy:
class VirtualAccountProxy
    def initialize(starting_balance=0)
      @starting_balance=starting_balance
    end
    def deposit(amount)
      s = subject
      return s.deposit(amount)
    end
      def subject
      @subject || (@subject = BankAccount.new(@starting_balance))
    end
end

如果是传代码块就能把创建subject外放到创建proxy的时候...
class VirtualAccountProxy
  def initialize(&creation_block)
    @creation_block = creation_block
  end
  # Other methods omitted ...
  def subject
    @subject || (@subject = @creation_block.call)
  end
end
account = VirtualAccountProxy.new { BankAccount.new(10)}

更进一步,创建一个代理,把所有对proxy的method调用都转给subject,但是有权限访问(本质上ruby是这么调用方法的
tmm.send(:goodbye, 'cruel', 'world')--用symbol ):
class AccountProtectionProxy
  def initialize(real_account, owner_name)
    @subject = real_account
    @owner_name = owner_name
  end
  def method_missing(name, *args)
    check_access
    @subject.send( name, *args )
  end
  def check_access
    raise "Illegal access: #{Etc.getlogin} cannot access account." if Etc.getlogin != @owner_name
  end
end
这个模式要注意的就是如果用了method_missing之类的方法proxy和subject的角色,某些方法是针对proxcy的,某些是subject,容易搞混...如果是每个方法都显示的声明问题就不大了,不过那样代码量就上去了...

decorator 给一个具体的操作添加一系列的修饰,形成一系列的类:
class CheckSummingWriter < WriterDecorator
  attr_reader :check_sum
  def initialize(real_writer)
    @real_writer = real_writer
    @check_sum = 0
  end
  def write_line(line)
    line.each_byte {|byte| @check_sum = (@check_sum + byte) % 256 }
    @check_sum += "\n"[0] % 256
    @real_writer.write_line(line)
  end
end
writer = CheckSummingWriter.new(TimeStampingWriter.new(
NumberingWriter.new(SimpleWriter.new('final.txt'))))
writer.write_line('Hello out there')

还可以动态修改一个对象的类方法...
w = SimpleWriter.new('out')
class << w
  alias old_write_line write_line
  def write_line(line)
    old_write_line("#{Time.new}: #{line}")
  end
end
或者写一个module,用extend方法动态的载入这个module
module TimeStampingWriter
  def write_line(line)
    super("#{Time.new}: #{line}")
  end
end
class Writer
  def write_line(line)
    puts(line)
  end
end
w = Writer.new()
w.extend(TimeStampingWriter)
w.write_line('hello')

singleton
等同于java的static,类方法,用@@变量
class SimpleLogger
  @@instance = SimpleLogger.new
  def self.instance
    return @@instance
  end
  private_class_method :new
end
上面用了private方法屏蔽了singleton可能的new

factory...把类的创建推迟到子类
一个concrete factory有几个具体的create_product method
在abstract factory里面只是create_product占了个位
jungle_organism_factory = OrganismFactory.new(Tree, Tiger)
pond_organism_factory = OrganismFactory.new(WaterLily, Frog)
jungle = Habitat.new(1, 4, jungle_organism_factory)
jungle.simulate_one_day
pond = Habitat.new( 2, 4, pond_organism_factory)
pond.simulate_one_day

in ruby all class is constant const_get就是拿到那个变量:
class IOFactory
  def initialize(format)
    @reader_class = self.class.const_get("#{format}Reader")
    @writer_class = self.class.const_get("#{format}Writer")
  end
  def new_reader
    @reader_class.new
  end
end
html_factory = IOFactory.new('HTML')
html_reader = html_factory.new_reader

builder:
builder = ComputerBuilder.new
builder.turbo
builder.add_cd(true)
builder.add_dvd
builder.add_hard_disk(100000)
...
computer = builder.computer

interpreter
...这个东西要写好太烦琐了...
dsl
class Jungle < CompositeBase
  composite_of(:population)
end
这类composite_of方法的实现方法...(也就是activerecord里面众多has_one, belings_to)
def self.member_of(composite_name)
  code = %Q{
  attr_accessor :parent_#{composite_name}
  }
  class_eval(code)
end

最后书中特别提出了: convention over configuration
这东西还是看情况的,规定死了,默认的条条框框多了,自然乱七八糟的东西就少了
一言堂带来更高的生产力,民主导致低效...
民主是最不坏的,但不会是最有效的o(∩_∩)o...


--------------
chenjinlai
2008-04-28
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics