`
jlaky
  • 浏览: 42038 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Design Patterns in Ruby [Digest 3] Strategy

阅读更多

The Template method is build around inheritance, the inheritance has the nature born relationship.

So the Strategy give a delegate solution.

 

So we use the strategy implementation:

 

 

class Formatter
	def output_report( title, text )
	raise 'Abstract method called'
	end
end

class HTMLFormatter < Formatter
	def output_report( title, text )
		puts('<html>')
		puts(' <head>')
		puts(" <title>#{title}</title>")
		puts(' </head>')
		puts(' <body>')
		text.each do |line|
			puts(" <p>#{line}</p>" )
		end
		puts(' </body>')
		puts('</html>')
	end
end

class PlainTextFormatter < Formatter
	def output_report(title, text)
		puts("***** #{title} *****")
		text.each do |line|
		puts(line)
		end
	end
end

 

So the Report is much simpler:

 

 

class Report
	attr_reader :title, :text
	attr_accessor :formatter
	def initialize(formatter)
		@title = 'Monthly Report'
		@text = [ 'Things are going', 'really, really well.' ]
		@formatter = formatter
	end
	def output_report
		@formatter.output_report( @title, @text )
	end
end

 

Usage is as below:

 

report = Report.new(HTMLFormatter.new)
report.output_report

 

The key idea of Strategy is to define a family of strategy objects those are used by the context class,

its use composition and delegation rather than inheritance, it is easy to switch strategies at runtime

 

 

there is a problem about sharing data between context and strategies,

the writer gives a example as below:

 

class Report
	attr_reader :title, :text
	attr_accessor :formatter

	def initialize(formatter)
		@title = 'Monthly Report'
		@text = ['Things are going', 'really, really well.']
		@formatter = formatter
	end

	def output_report
		@formatter.output_report(self)
	end
end
class Formatter
	def output_report(context)
		raise 'Abstract method called'
	end
end

class HTMLFormatter < Formatter
	def output_report(context)
		puts('<html>')
		puts(' <head>')
		puts(" <title>#{context.title}</title>")
		puts(' </head>')
		puts(' <body>')
		context.text.each do |line|
			puts(" <p>#{line}</p>")
		end
		puts(' </body>')
		puts('</html>')
	end
end

 

This technique simplifies the data flow but increases the coupling.

 

 

Then Ruby Duck Typing philosophy shows that we don't need the Formatter class any more. 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics