书里让我脑残的文法:
But Ruby programs do not crash with any-
thing like the frequency that you might expect given the lengths that statically typed
languages go to in to avoid even the remote poss
ibility of type errors.
我怀疑自己的英语是不是退步太多了...Orz
开篇总结思想:
隔离变化的和不变的
对接口编程
组合优于继承
用委托
然后讲具体的pattern:
template method讲的是一个类,abstract method(hook method)占位,
这个父类派生出一堆具体的子类用concrete method来填充那些方法
但是这个模式是基于继承的,依赖父类不太好
于是讲到用委托,把那些concrete method封装到一个个单独的类里面
这个就叫strategy,template是通过选一个子类来选择具体的方案,strategy是选一个策略类...
ruby这里的动态绑定优势就是如果用stragegy方法,不需要一个基类了...
class Report
attr_reader :title, :text
attr_accessor :formatter
def output_report()
@formatter.output_report(self)
end
end
class PlainTextFormatter
def output_report(context)
puts("***** #{context.title} *****")
end
end
更进一步,ruby能传block...简单情况下class都不用写了...
比如
a = ['russell', 'mike', 'john', 'dan', 'rob']
a.sort{|a,b|a.length<=>b.length}
其实就是传递了一个代码块作为一个strategy,因为ruby语法层面的支持显得"呼吸一样"自然
本来java之类的写法应该是
lengthStragegy extends abstractStrategy{
blablabla;
...
}
a = new sort();
a.setStrategy(lengthStragegy);
a.sort(data);
30%的文章就讲了以上这么一点点...老外的书有点絮絮叨叨碎碎念...
observer...就是在建立一个需要监听的队列,每次有修改就通知他们...
比如每次更改薪水的时候...通知observer队列...
def salary=(new_salary)
@salary = new_salary
notify_observers
end
def notify_observers
@observers.each do |observer|
observer.update(self)
end
但是如果把observer作为继承得到的一个特性就不好了,
ruby可以用module mixin...结果就是这样:
--------------------------------
require 'observer'
class Employee
include Observable
attr_reader :name, :address
attr_reader :salary
def initialize( name, title, salary)
@name = name
@title = title
@salary = salary
end
def salary=(new_salary)
@salary = new_salary
changed
notify_observers(self)
end
end
class Bb
def update(b)
puts 'get update'
end
end
a = Employee.new('22','33',44)
c = Bb.new
a.add_observer(c)
a.salary=22
接下来讲到observer通知多个事件的处理方法:
fred.salary = 1000000
fred.title = 'Vice President of Sales'
# Now inform the observers!
fred.changes_complete
这算是一组事件完成后给一个notify而不是单个事件完成就通知...
然后是component方法...用于处理有相似行为特征的树形结构...
class Task
attr_reader :name
def initialize(name)
@name = name
end
def get_time_required
0.0
end
end
class MakeBatterTask < Task
def initialize
super('Make batter')
@sub_tasks = []
add_sub_task( AddDryIngredientsTask.new )
add_sub_task( AddLiquidsTask.new )
add_sub_task( MixTask.new )
end
def add_sub_task(task)
@sub_tasks << task
end
def remove_sub_task(task)
@sub_tasks.delete(task)
end
def get_time_required
time=0.0
@sub_tasks.each {|task| time += task.get_time_required}
time
end
end
然后是iterator...这个在ruby中相当容易
[3,4,5].each{|i| xxx}
如果要让一个类也有each的方法,只要mixin enumerable module:
class Portfolio
include Enumerable
def initialize
@accounts = []
end
def each(&block)
@accounts.each(&block)
end
def add_account(account)
@accounts << account
end
end
a = Portfolio.new
a.add_account(2)
a.add_account(3)
a.each{|i|puts i}
这里讲到interator的常见问题是迭代过程中如果删除一个元素,会漏掉一个...
array=['red', 'green', 'blue', 'purple']
array.each do | color |
puts(color)
array.delete(color) if color == 'green'
end
输出是:
red
green
purple(漏掉了一个...)
...书中提出的一个解决办法是初始化的时候复制一份原来的array...
然后是command...
这里讲到了一个design pattern滥用的问题
class FileDeleteCommand
def initialize(path)
@path = path
end
def execute
File.delete(@path)
end
end
fdc = FileDeleteCommand.new('foo.dat')
fdc.execute
其实以上只要一句话File.delete('foo.dat')....用了command反而繁琐...
But Ruby programs do not crash with any-
thing like the frequency that you might expect given the lengths that statically typed
languages go to in to avoid even the remote poss
ibility of type errors.
我怀疑自己的英语是不是退步太多了...Orz
开篇总结思想:
隔离变化的和不变的
对接口编程
组合优于继承
用委托
然后讲具体的pattern:
template method讲的是一个类,abstract method(hook method)占位,
这个父类派生出一堆具体的子类用concrete method来填充那些方法
但是这个模式是基于继承的,依赖父类不太好
于是讲到用委托,把那些concrete method封装到一个个单独的类里面
这个就叫strategy,template是通过选一个子类来选择具体的方案,strategy是选一个策略类...
ruby这里的动态绑定优势就是如果用stragegy方法,不需要一个基类了...
class Report
attr_reader :title, :text
attr_accessor :formatter
def output_report()
@formatter.output_report(self)
end
end
class PlainTextFormatter
def output_report(context)
puts("***** #{context.title} *****")
end
end
更进一步,ruby能传block...简单情况下class都不用写了...
比如
a = ['russell', 'mike', 'john', 'dan', 'rob']
a.sort{|a,b|a.length<=>b.length}
其实就是传递了一个代码块作为一个strategy,因为ruby语法层面的支持显得"呼吸一样"自然
本来java之类的写法应该是
lengthStragegy extends abstractStrategy{
blablabla;
...
}
a = new sort();
a.setStrategy(lengthStragegy);
a.sort(data);
30%的文章就讲了以上这么一点点...老外的书有点絮絮叨叨碎碎念...
observer...就是在建立一个需要监听的队列,每次有修改就通知他们...
比如每次更改薪水的时候...通知observer队列...
def salary=(new_salary)
@salary = new_salary
notify_observers
end
def notify_observers
@observers.each do |observer|
observer.update(self)
end
但是如果把observer作为继承得到的一个特性就不好了,
ruby可以用module mixin...结果就是这样:
--------------------------------
require 'observer'
class Employee
include Observable
attr_reader :name, :address
attr_reader :salary
def initialize( name, title, salary)
@name = name
@title = title
@salary = salary
end
def salary=(new_salary)
@salary = new_salary
changed
notify_observers(self)
end
end
class Bb
def update(b)
puts 'get update'
end
end
a = Employee.new('22','33',44)
c = Bb.new
a.add_observer(c)
a.salary=22
接下来讲到observer通知多个事件的处理方法:
fred.salary = 1000000
fred.title = 'Vice President of Sales'
# Now inform the observers!
fred.changes_complete
这算是一组事件完成后给一个notify而不是单个事件完成就通知...
然后是component方法...用于处理有相似行为特征的树形结构...
class Task
attr_reader :name
def initialize(name)
@name = name
end
def get_time_required
0.0
end
end
class MakeBatterTask < Task
def initialize
super('Make batter')
@sub_tasks = []
add_sub_task( AddDryIngredientsTask.new )
add_sub_task( AddLiquidsTask.new )
add_sub_task( MixTask.new )
end
def add_sub_task(task)
@sub_tasks << task
end
def remove_sub_task(task)
@sub_tasks.delete(task)
end
def get_time_required
time=0.0
@sub_tasks.each {|task| time += task.get_time_required}
time
end
end
然后是iterator...这个在ruby中相当容易
[3,4,5].each{|i| xxx}
如果要让一个类也有each的方法,只要mixin enumerable module:
class Portfolio
include Enumerable
def initialize
@accounts = []
end
def each(&block)
@accounts.each(&block)
end
def add_account(account)
@accounts << account
end
end
a = Portfolio.new
a.add_account(2)
a.add_account(3)
a.each{|i|puts i}
这里讲到interator的常见问题是迭代过程中如果删除一个元素,会漏掉一个...
array=['red', 'green', 'blue', 'purple']
array.each do | color |
puts(color)
array.delete(color) if color == 'green'
end
输出是:
red
green
purple(漏掉了一个...)
...书中提出的一个解决办法是初始化的时候复制一份原来的array...
然后是command...
这里讲到了一个design pattern滥用的问题
class FileDeleteCommand
def initialize(path)
@path = path
end
def execute
File.delete(@path)
end
end
fdc = FileDeleteCommand.new('foo.dat')
fdc.execute
其实以上只要一句话File.delete('foo.dat')....用了command反而繁琐...