如果您一直致力于面向對象的開發,向類或對象添加行為,并使用繼承機制,那么這是所有面向對象語言的基本特性,武林技術頻道小編今天實例講解Ruby使用設計模式中的裝飾器模式的方法。
概述
? ? ? ?如果已經存在的一個類缺少某些方法,或者須要給方法添加更多的功能(魅力),你也許會僅僅繼承這個類來產生一個新類—這建立在額外的代碼上。
????? 通過繼承一個現有類可以使得子類在擁有自身方法的同時還擁有父類的方法。但是這種方法是靜態的,用戶不能控制增加行為的方式和時機。如果? 你希望改變一個已經初始化的對象的行為,你怎么辦?或者,你希望繼承許多類的行為,改怎么辦?前一個,只能在于運行時完成,后者顯然時可能的,但是可能會導致產生大量的不同的類—可怕的事情。
問題
????? 你如何組織你的代碼使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不額外的代碼寫在你的類的內部?
解決方案
?適用性
?????? 以下情況使用Decorator模式
????? 為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。
????? 另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
?
實例
ruby.html="" tags="">ruby;">class SimpleWriter def initialize(path) @file = File.open(path,"w") end def write_line(line) @file.print(line) @file.print("/n") end #字符數 def pos @file.pos end #它將會將文件指針指向文件的開頭 def rewind @file.rewind end def close @file.colse end end sw = SimpleWriter.new("test.txt") sw.write_line("你好") puts sw.pos puts sw.rewind #基類 class WriterDecorator def initialize(real_writer) @real_writer = real_writer end def write_line @real_writer.write_line end def pos @real_writer.pos end def rewind @real_writer.rewind end def close @real_writer.close end end class NumberingWriter < WriterDecorator attr :line_number def initialize(real_writer) super(real_writer) @line_number = 1 end #實際調用的是WriterDecorator的write_line方法,只是在寫入的內容前加上了編號(裝飾) #所以說NumberingWriter對WriterDecorator的接口wirte_line進行了裝飾 # def write_line(line) @real_writer.write_line("#{@line_number}:#{line}") @line_number += 1 end end sw = SimpleWriter.new("numbering_write.txt") nw = NumberingWriter.new(sw) nw.write_line("hello,world") nw.write_line("hello,ruby") puts nw.line_number class CheckSummingWriter < WriterDecorator attr_reader :check_num def initialize(real_writer) super(real_writer) @check_num = 0 end def write_line(line) line.each_byte{|byte| @check_num += byte % 256} @real_writer.write_line(line) end end sw = SimpleWriter.new("check_num_writer.txt") csw = CheckSummingWriter.new(sw) csw.write_line("hello,world") puts csw.check_num class TimeStampingWriter < WriterDecorator def initialize(real_writer) super(real_writer) end def write_line(line) @real_writer.write_line("#{Time.now}: #{line}") end end #倒著看 #5. 實際調用的是SimpleWriter得write_line方法,將內容寫入文件 sw = SimpleWriter.new("mix.txt") #4. 實際調用的是NumberingWriter得write_line方法,對在輸入的數據前加上了編號 # 然后傳給@real_writer,此時的@real_witer為sw nw = NumberingWriter.new(sw) #3. 實際調用的是TimeStampingWriter得write_line方法,對在輸入的數據前加上了時間戳 # 然后傳給@real_writer,此時的@real_witer為nw tsw = TimeStampingWriter.new(nw) #2. 實際調用的是CheckSummingWriter得write_line方法,對輸入的數據進行了字節數的統計 # 然后傳給@real_writer,此時的@real_witer為tsw csw = CheckSummingWriter.new(tsw) #1. csw調用write_line csw.write_line("hello,world") puts csw.check_num
兩種ruby風格的裝飾模式應用
?
(1)使用extend混入模塊
class SimpleWriter def initialize(path) @file = File.open(path,"w") end def write_line(line) @file.print(line) @file.print("/n") end #字符數 def pos @file.pos end #它將會將文件指針指向文件的開頭 def rewind @file.rewind end def close @file.colse end end #使用extend方法動態的混入模塊,來進行裝飾 module TimeStampingWriter def write_line(line) super("#{Time.now}:#{line}") end end module NumberingWriter attr_reader :line_number def write_line(line) @line_number = 1 unless @line_number super("#{@line_number}:#{line}") @line_number += 1 end end
?
最后被加入的模塊,先被調用,然后通過super來調用父類的write_line方法。?
例子中先在文本的前面加上時間戳,在加入編號,最后寫入文件??
sw = SimpleWriter.new("out3.txt") sw.extend(NumberingWriter) sw.extend(TimeStampingWriter) sw.write_line("hello,ruby")
?
(2)使用alias關鍵字
class SimpleWriter def initialize(path) @file = File.open(path,"w") end def write_line(line) @file.print(line) @file.print("/n") end #字符數 def pos @file.pos end #它將會將文件指針指向文件的開頭 def rewind @file.rewind end def close @file.colse end end ruby實現裝飾模式的另一種動態方法 : 修改對象的實例方法, 所以在out1.txt文件中會加入時間戳,而不影響對象sw2,out2.txt中不會加入時間戳 。 sw1 = SimpleWriter.new("out1.txt") class << sw1 alias old_write_line write_line def write_line(line) old_write_line("#{Time.now}:#{line}") end end sw1.write_line("hello,world") sw2 = SimpleWriter.new("out2.txt") sw2.write_line("hello,world")
以上就是今天給大家分享的實例講解Ruby使用設計模式中的裝飾器模式的方法,希望可以幫助到需要的朋友,如果覺得還不錯,可以分享給身邊的朋友哦,想要了解更多,推薦大家關注js.Vevb.com。
新聞熱點
疑難解答
圖片精選