设计模式中的模板方法模式在Ruby中的应用实例两则

2019-09-25 09:38:37王旭

调用代码如下:

book = Book.new 
book.book_name = "Programming Ruby" 
book.pages = 830 
book.price = 45 
book.author = "Dave Thomas" 
book.isbn = "9787121038150" 
formatter = Formatter.new 
result = formatter.format_book(book, :xml) 
puts result 
result = formatter.format_book(book, :json) 
puts result 

再次运行程序,得到了以下结果。

2016316160047870.png (358×292)

项目经理看到运行结果后开心地说:“太好了,这正是我想要的!”
可是你这次却没有那么开心,你觉得代码已经有些混乱了,XML格式的逻辑和JSON格式的逻辑混淆在一起,非常不利于阅读,而且如果以后还需要扩展功能也会非常困难。好在传输格式一般也就XML和JSON了,应该不会再有什么扩展了,你这样安慰自己道。
但幻想总会被现实打破,“我最近听说有个YAML格式挺好玩的.......” 项目经理说道。这个时候你已经有想打人的冲动了!!!

很多时候就是这样,在公司里写的代码乱七八糟,质量极差,很大一部分原因就是因为需求变来变去。我们不断在原有代码基础上补充各种后续加入的情况,在一行行新增的if语句下面,我们的代码变得不堪入目。当然,我们作为程序员,对于需求这种东西没有太多的话语权,在这方面我们无能为力。但是我们可以尽量地把程序的架构设计好,让我们写出的代码更具有扩展性,这样就可以应对各种需求变更了。

下面你将要使用23种设计模式中的模板方法来改进以上程序。
首先要定义专门的子类来处理每种传输格式的具体逻辑,这样不同传输格式的逻辑可以从一个方法里分离开,明显便于阅读和理解。
定义类XMLFormatter继承自Formatter,里面加入处理XML格式的具体逻辑:

class XMLFormatter < Formatter 
 
 def formating(book) 
  result = "<book_name>#{book.book_name}</book_name>n" 
  result += "<pages>#{book.pages}</pages>n" 
  result += "<price>#{book.price}</price>n" 
  result += "<author>#{book.author}</author>n" 
  result += "<isbn>#{book.isbn}</isbn>n" 
 end 
 
end 

定义类JSONFormatter继承自Formatter,里面加入处理JSON格式的具体逻辑:

class JSONFormatter < Formatter 
  
 def formating(book) 
  result = "{n" 
  result += ""book_name" : "#{book.book_name}",n" 
  result += ""pages" : "#{book.pages}",n" 
  result += ""price" : "#{book.price}",n" 
  result += ""author" : "#{book.author}",n" 
  result += ""isbn" : "#{book.isbn}",n" 
  result += '}' 
 end 
  
end 

然后将Formatter中的代码进行修改,如下所示:

class Formatter 
 
 def format_book(book) 
  before_format 
  result = formating(book) 
  after_format 
  result 
 end 
  
 def before_format 
  puts "format begins" 
 end 
  
 def formating(book) 
  raise "You should override this method in subclass." 
 end 
  
 def after_format 
  puts "format finished" 
 end 
 
end