@smilence
2020-02-28T02:23:09.000000Z
字数 2438
阅读 1170
Ruby SDE-Foundations
Instance method必须要新建instance, 必须每次新建一个instance = Class.new(), 需要在内存当中存储这个instance的variable 以及 method的代码。有多少个instance就有多少这些东西。
有一类class可以被认为是一个globally共享的toolbox,大家都可以用,没有必要每次都新建一个,逻辑对每个人都是一样的,那么内存中只需要存一开始的那段代码即可。
还是那个例子,我们想拿所有的Sticker, 我们一定要用instance method的话,我们也可以去class Sticker以外新建一个类,专门负责这件事情:
class StickerInventorydef initialize()enddef getAllStickers()...endendinventory_for_april = StickerInventory.new() #内存里增加了一个objectapril_stickers = inventory_for_april.getAllStickers...# 可能在下一层函数里inventory_for_james = StickerInventory.new() #内存里又增加了一个objectjames_stickers = inventory_for_james.getAllStickers# 当然你可以用inventory = StickerInventory.new() 然后一直用同一个,但是需要传来传去会很麻烦...
相比之下,
class Stickerself.getAllStickers(userid)...endend# 每次都用内存中存储的同样一段代码inventory_for_april = Sticker.getAllStickers()inventory_for_james = Sticker.getAllStickers()
所以前者不仅要多写了一个class,而且运行效率还更低。
# 创建一个class负责统一create payment,因为用户输入的时候不会自己选择是新建哪种class PaymentFactorydef self.createPayment(senderId, receiverId, currency, amount, item = nil)if item != nilreturn CommercePayment.new(senderId, receiverId, currency, amount, item)elseif currency == 'USD'return USTransfer.new(senderId, receiverId, amount)elseif currency == 'GBP'return GBTransfer.new(senderId, receiverId, amount)elseraise Error("Not supported")endendend# 写好这些之后,别人就不需要关心你内部是怎么分类实现的,只要用`PaymentFactory.createPayment`就是万能的
# 创建一个class作为缓存专门负责存下已经拿取过的payment,比如从payment history一个个点进payment receipt。# 这样取过的就不需要每次都去database取。这个cache是global的。class PaymentCache@@cache = nildef initialize(payments = {})@payments = paymentsend# 无论哪里需要这个cache,都应该去拿同一个cache objectdef self.get()# 如果还没有建过的话,就新建一个cache objectif @@cache == nilreturn self.new()elsereturn @@cacheendenddef self.getPayment(id)cache = self.get()if cache.has_key?(id)return cache[id]elsepayment = get_payment_from_database(id)cache[id] = payment_objreturn paymentendendend# 用这个class的人不需要担心自己去新建PaymentCache 然后传来传去p1 = PaymentCache.getPayment(1) # 去database拿了放进cachep2 = PaymentCache.getPayment(2) # 去database拿了放进cache....# 下次再想拿1对应的paymentp1 = PaymentCache.getPayment(1) # 从cache里而不是database拿出来,因为已经有1这个key了
如果每次都新建一个cache, 那么每次都是空的,不会有之前的数据。如果第一次建了之后就到处传,则显得非常乱,给每一层函数都增加了一个参数。更不用说下层函数无法给上层传。我们希望用class variable去document一个唯一的instance,是所有人所共享的。
当然,我们可以只用class method和class variable,连这个唯一的instance都不需要,我们可以只用一个@@payments作为class variable。但那样在实际运用时候的缺点在于,如果我们需要多个继承PaymentCache的class,我们又不希望他们把东西都放在一起,那么我们就需要每个class对应一个object。否则的话,所有的child class都会用同一个@@payments来保存。