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