Ruby裝飾模式應用技巧分享
在Ruby語言中,是一種比較簡便的編程語言。我們可以通過它在編程中獲得很大的快樂感。在這里我們會未大家介紹一下Ruby裝飾模式的相關(guān)應用技巧。#t#
Ruby裝飾模式是設計模式之一,它允許你在運行時動態(tài)地為一個存在的對象添加特性.在一個對象有很多種可以有不同方式組合的可以影響其特性的
變量時特別有用(dingsea:沒看懂?翻譯這段比較YY,以上大概是出版社的風格,其實用例子比較容易理解,向下看)
這個短小精悍的Ruby裝飾模式實現(xiàn),總結(jié)了這個星球上我***的最火的動態(tài)語言.
我從Eric Freeman, Elisabeth Freeman, Kathy Sierra, 和Bert Bates他們寫的杰出的Head First Design Patterns 一書中借取一個例子.
假設你要計算一杯咖啡的價錢.你有一個實現(xiàn)了cost()方法的咖啡類.此例中我們出于示例目的硬編碼其價格:
- class Coffee
- def cost
- 2
- end
- end
很好.不過如果我們要知道一杯加奶的咖啡多少錢怎么辦?我們有一個新類:
- class WhiteCoffee
- def cost
- 2.4
- end
- end
好,但是現(xiàn)在我們要加奶油的咖啡怎么辦?再要撒些東西在上邊呢?(原文"And sprinkles",個人理解,歡迎討論).明顯地,不停地創(chuàng)建新類會導致在應用中出現(xiàn)類爆炸.為不同的咖啡和其調(diào)料(糖,奶...)組合創(chuàng)建新類是不現(xiàn)實的,這樣會變糟糕--如果我們有不同種類的咖啡怎么辦?然后我們
還不得不加一些調(diào)料在這些不同的咖啡中.這不是一個好辦法.下面進入Ruby裝飾模式.像本文題目提到的那樣,這就是Ruby的8行代碼實現(xiàn):
- module Decorator
- def initialize(decorated)
- @decorateddecorated = decorated
- end
- def method_missing
(method, *args)- args.empty? ? @decorated.send
(method) : @decorated.send
(method, args)- end
- end
這就是你所要的.你可以在任何你想要裝飾的類中包含以上module.然后你可以使用這個裝飾者就像直接使用裝飾好的對象一樣,默認地,所有傳到裝飾者的信息都會被轉(zhuǎn)到被裝飾的對象那兒.你可以根據(jù)需要裝飾你的方法用來擴展:
- class Milk
- include Decorator
- def cost
- @decorated.cost + 0.4
- end
- end
那么怎樣解決我們剛開頭的咖啡問題呢?Ruby裝飾模式在實戰(zhàn)中的強大之處就在于他們可以像被裝飾的對象一樣工作(dingsea:嗯,大概是說,類A,被裝飾過后,客戶代碼認為它還是A,呵呵).通過更進一步,你可以裝飾其它的裝飾者,只要它們有同樣的接口.通過為不同的"擴展"創(chuàng)建裝飾者,我們可以使用組合的裝飾者創(chuàng)建咖啡類并計算此咖啡的總價.
- class Whip
- include Decorator
- def cost
- @decorated.cost + 0.2
- end
- end
- class Sprinkles
- include Decorator
- def cost
- @decorated.cost + 0.3
- end
- end
- Whip.new(Coffee.new).cost
- #=> 2.2
- Sprinkles.new(Whip.new
(Milk.new(Coffee.new))).cost- #=> 2.9
當然,為方便著想我們情不自禁創(chuàng)建幾個工廠方法:
- class CoffeeFactory
- def self.latte
- SteamedMilk.new(Espresso.new)
- end
- def self.cappuccino
- Sprinkles.new(Cream.new
(Milk.new(Coffee.new)))- end
- end
- order = Order.new
- order.add(Coffee.new)
- order.add(CoffeeFactory
.cappuccino)- puts order.total
由于Ruby的高動態(tài)語言特性,裝飾模式并不是在運行時擴展類的唯一方法,當然,我只是喜歡ruby中用如此簡單的方法實現(xiàn)一個模式.在ruby中有關(guān)裝飾模式的更多信息和實現(xiàn),包括generic decorators和可選擇的傳統(tǒng)裝飾模式,請參考DecoratorPattern page at the RubyGarden.
***,在使用Ruby裝飾模式時保持某些恒等性是很好的.上邊提到的RubyGarden的網(wǎng)頁里是其中一種方法.同時我們沒有使用繼承,保留繼承這一特性是很好的:
- CoffeeFactory.
cappucino.kind_of? Coffee- #=> true