@smilence
2020-02-28T10:23:09.000000Z
字数 2438
阅读 831
Ruby
SDE-Foundations
Instance method必须要新建instance, 必须每次新建一个instance = Class.new()
, 需要在内存当中存储这个instance的variable 以及 method的代码。有多少个instance就有多少这些东西。
有一类class可以被认为是一个globally共享的toolbox,大家都可以用,没有必要每次都新建一个,逻辑对每个人都是一样的,那么内存中只需要存一开始的那段代码即可。
还是那个例子,我们想拿所有的Sticker, 我们一定要用instance method的话,我们也可以去class Sticker
以外新建一个类,专门负责这件事情:
class StickerInventory
def initialize()
end
def getAllStickers()
...
end
end
inventory_for_april = StickerInventory.new() #内存里增加了一个object
april_stickers = inventory_for_april.getAllStickers
...
# 可能在下一层函数里
inventory_for_james = StickerInventory.new() #内存里又增加了一个object
james_stickers = inventory_for_james.getAllStickers
# 当然你可以用inventory = StickerInventory.new() 然后一直用同一个,但是需要传来传去会很麻烦
...
相比之下,
class Sticker
self.getAllStickers(userid)
...
end
end
# 每次都用内存中存储的同样一段代码
inventory_for_april = Sticker.getAllStickers()
inventory_for_james = Sticker.getAllStickers()
所以前者不仅要多写了一个class,而且运行效率还更低。
# 创建一个class负责统一create payment,因为用户输入的时候不会自己选择是新建哪种
class PaymentFactory
def self.createPayment(senderId, receiverId, currency, amount, item = nil)
if item != nil
return 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)
else
raise Error("Not supported")
end
end
end
# 写好这些之后,别人就不需要关心你内部是怎么分类实现的,只要用`PaymentFactory.createPayment`就是万能的
# 创建一个class作为缓存专门负责存下已经拿取过的payment,比如从payment history一个个点进payment receipt。
# 这样取过的就不需要每次都去database取。这个cache是global的。
class PaymentCache
@@cache = nil
def initialize(payments = {})
@payments = payments
end
# 无论哪里需要这个cache,都应该去拿同一个cache object
def self.get()
# 如果还没有建过的话,就新建一个cache object
if @@cache == nil
return self.new()
else
return @@cache
end
end
def self.getPayment(id)
cache = self.get()
if cache.has_key?(id)
return cache[id]
else
payment = get_payment_from_database(id)
cache[id] = payment_obj
return payment
end
end
end
# 用这个class的人不需要担心自己去新建PaymentCache 然后传来传去
p1 = PaymentCache.getPayment(1) # 去database拿了放进cache
p2 = PaymentCache.getPayment(2) # 去database拿了放进cache
....
# 下次再想拿1对应的payment
p1 = 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
来保存。