執行個體講解Ruby使用設計模式中的裝飾器模式的方法_ruby專題

來源:互聯網
上載者:User

概述
       若你從事過物件導向開發,實現給一個類或對象增加行為,使用繼承機制,這是所有物件導向語言的一  個基本特性。如果已經存在的一個類缺少某些方法,或者須要給方法添加更多的功能(魅力),你也許會僅僅繼承這個類來產生一個新類—這建立在額外的代碼上。
      通過繼承一個現有類可以使得子類在擁有自身方法的同時還擁有父類的方法。但是這種方法是靜態,使用者不能控制增加行為的方式和時機。如果  你希望改變一個已經初始化的對象的行為,你怎麼辦?或者,你希望繼承許多類的行為,改怎麼辦?前一個,只能在於運行時完成,後者顯然時可能的,但是可能會導致產生大量的不同的類—可怕的事情。
問題
      你如何組織你的代碼使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不額外的代碼寫在你的類的內部?

解決方案

  •        動態地給一個對象添加一些額外的職責或者行為。就增加功能來說, Decorator模式相比產生子類更為靈活。
  •        提供了改變子類的靈活方案。裝飾器模式在不必改變原類檔案和使用繼承的情況下,動態擴充一個對象的功能。它是通過建立一個封裝對象,也就是裝飾來包裹真實的對象。
  •        當用於一組子類時,裝飾器模式更加有用。如果你擁有一族子類(從一個父類派生而來),你需要在與子類獨立使用方式下添加額外的特性,你可以使用裝飾器模式,以避免代碼重複和具體子類數量的增加。

 適用性

       以下情況使用Decorator模式

  •       在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
  •       處理那些可以撤消的職責。
  •       當不能採用產生子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充,

      為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。

      另一種情況可能是因為類定義被隱藏,或類定義不能用於產生子類。
 
執行個體

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") 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.