Ruby 享元模式讲解和代码示例
享元是一种结构型设计模式, 它允许你在消耗少量内存的情况下支持大量对象。
模式通过共享多个对象的部分状态来实现上述功能。 换句话来说, 享元会将不同对象的相同数据进行缓存以节省内存。
复杂度:
流行度:
使用示例: 享元模式只有一个目的: 将内存消耗最小化。 如果你的程序没有遇到内存容量不足的问题, 则可以暂时忽略该模式。
识别方法: 享元可以通过构建方法来识别, 它会返回缓存对象而不是创建新的对象。
概念示例
本例说明了享元设计模式的结构并重点回答了下面的问题:
- 它由哪些类组成?
- 这些类扮演了哪些角色?
- 模式中的各个元素会以何种方式相互关联?
main.rb: 概念示例
require 'json' # The Flyweight stores a common portion of the state (also called intrinsic # state) that belongs to multiple real business entities. The Flyweight accepts # the rest of the state (extrinsic state, unique for each entity) via its method # parameters. class Flyweight # @param [String] shared_state def initialize(shared_state) @shared_state = shared_state end # @param [String] unique_state def operation(unique_state) s = @shared_state.to_json u = unique_state.to_json print "Flyweight: Displaying shared (#{s}) and unique (#{u}) state." end end # The Flyweight Factory creates and manages the Flyweight objects. It ensures # that flyweights are shared correctly. When the client requests a flyweight, # the factory either returns an existing instance or creates a new one, if it # doesn't exist yet. class FlyweightFactory # @param [Hash] initial_flyweights def initialize(initial_flyweights) @flyweights = {} initial_flyweights.each do |state| @flyweights[get_key(state)] = Flyweight.new(state) end end # Returns a Flyweight's string hash for a given state. def get_key(state) state.sort.join('_') end # Returns an existing Flyweight with a given state or creates a new one. def get_flyweight(shared_state) key = get_key(shared_state) if !@flyweights.key?(key) puts "FlyweightFactory: Can't find a flyweight, creating new one." @flyweights[key] = Flyweight.new(shared_state) else puts 'FlyweightFactory: Reusing existing flyweight.' end @flyweights[key] end def list_flyweights puts "FlyweightFactory: I have #{@flyweights.size} flyweights:" print @flyweights.keys.join("\n") end end # @param [FlyweightFactory] factory # @param [String] plates # @param [String] owner # @param [String] brand # @param [String] model # @param [String] color def add_car_to_police_database(factory, plates, owner, brand, model, color) puts "\n\nClient: Adding a car to database." flyweight = factory.get_flyweight([brand, model, color]) # The client code either stores or calculates extrinsic state and passes it to # the flyweight's methods. flyweight.operation([plates, owner]) end # The client code usually creates a bunch of pre-populated flyweights in the # initialization stage of the application. factory = FlyweightFactory.new([ %w[Chevrolet Camaro2018 pink], ['Mercedes Benz', 'C300', 'black'], ['Mercedes Benz', 'C500', 'red'], %w[BMW M5 red], %w[BMW X6 white] ]) factory.list_flyweights add_car_to_police_database(factory, 'CL234IR', 'James Doe', 'BMW', 'M5', 'red') add_car_to_police_database(factory, 'CL234IR', 'James Doe', 'BMW', 'X1', 'red') puts "\n\n" factory.list_flyweights output.txt: 执行结果
FlyweightFactory: I have 5 flyweights: Camaro2018_Chevrolet_pink C300_Mercedes Benz_black C500_Mercedes Benz_red BMW_M5_red BMW_X6_white Client: Adding a car to database. FlyweightFactory: Reusing existing flyweight. Flyweight: Displaying shared (["BMW","M5","red"]) and unique (["CL234IR","James Doe"]) state. Client: Adding a car to database. FlyweightFactory: Can't find a flyweight, creating new one. Flyweight: Displaying shared (["BMW","X1","red"]) and unique (["CL234IR","James Doe"]) state. FlyweightFactory: I have 6 flyweights: Camaro2018_Chevrolet_pink C300_Mercedes Benz_black C500_Mercedes Benz_red BMW_M5_red BMW_X6_white BMW_X1_red