模板模式固然不错,但其还是有一些缺陷的。比如其实现依赖于继承并且缺足够的灵活性。在这时候我们就需要找到一个更加优化的解决方案——策略模式。
下面是使用策略模式实现的Report模板
1 # 策略1 2 class HTMLFormatter 3 def output_report title, text 4 puts ‘<html>‘ 5 puts ‘ <head>‘ 6 puts ‘ <title>‘ + title + ‘</title>‘ 7 puts ‘ </head>‘ 8 puts ‘ <body>‘ 9 text.each do |line| 10 puts "<p>#{line}</p>" 11 end 12 puts ‘ </body>‘ 13 puts ‘</html>‘ 14 end 15 end 16 17 # 策略2 18 class PlainTextFormatter 19 def output_report title, text 20 puts ‘******** ‘ + title + ‘ ********‘ 21 text.each do |line| 22 puts line 23 end 24 end 25 end 26 27 # 环境 28 class Reporter 29 attr_reader :title, :text 30 attr_accessor :formater 31 32 def initialize formater 33 @title = ‘My Report‘ 34 @text = [‘This is my report‘, ‘Please see the report‘, ‘It is ok‘] 35 @formater = formater 36 end 37 38 # 可以把指向自己的引用传入策略中,这样做虽然简化了数据流动,但是增加了环境和策略之间的耦合 39 def output_report 40 @formater.output_report @title, @text 41 # @formater.output_report self 42 end 43 44 end 45 46 Reporter.new(HTMLFormatter.new).output_report 47 Reporter.new(PlainTextFormatter.new).output_report 48 49 # 再来回头说模板方法模式, 50 # 模板方法模式,是寻找共同,然后提取出模板 51 # 策略模式,是将不同的方法封装成一个策略,这些策略不尽相同,难以提取共同部分 52 53 # 如果策略足够简单,仅有一个方法,那么可以通过代码块传递 54 class ProcReporter 55 attr_reader :title, :text 56 attr_accessor :formatter 57 58 def initialize &formatter 59 @title = ‘My Report‘ 60 @text = [‘This is my report‘, ‘Please see the report‘, ‘It is ok‘] 61 @formatter = formatter 62 end 63 64 # 可以把指向自己的引用传入策略中,这样做虽然简化了数据流动,但是增加了环境和策略之间的耦合 65 def output_report 66 @formatter.call self 67 end 68 69 end 70 71 report_html = ProcReporter.new do |context| 72 puts ‘<html>‘ 73 puts ‘ <head>‘ 74 puts ‘ <title>‘ + context.title + ‘</title>‘ 75 puts ‘ </head>‘ 76 puts ‘ <body>‘ 77 context.text.each do |line| 78 puts "<p>#{line}</p>" 79 end 80 puts ‘ </body>‘ 81 puts ‘</html>‘ 82 end 83 p report_html.output_report 84 85 # 一个简单的轻量级策略对象的好例子 86 a = [‘1‘,‘12‘,‘123‘,‘6234567‘,‘3‘,‘13‘] 87 p a.sort 88 p a.sort {|a, b| a.length <=> b.length }
时间: 2024-10-10 07:14:11