From: Hideto ISHIBASHI Date: 2000-03-28T19:44:35+09:00 Subject: [ruby-list:21671] GoF's Flyweight Pattern ----Next_Part(Tue_Mar_28_19:24:26_2000_809)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit 石橋秀仁です。 "Gang of Four"の"Flyweight"というデザインパターンを試しに 実装してみました。まだいろいろと問題がありそうなので、 御意見ください。 (注)Flyweight Patternとは(引用) 「多数の細かいオブジェクトを効率良くサポートするために共有を利用する」 # ほんとは共有しているobjectを、変更される直前にcloneできれば。 # 複数のオブジェクトから参照されている場合の、副作用の心配が # 無くなります。例の「dup問題」も解決します。 # インスタンス変数にtrace_varのような操作はできないのでしょうか? また、これを使ってRuby本のlifegame.rbとgeometry.rbを書換えてみました。 Ruby本p.272の「#(A')@neighborsの初期化」のように(素直に)記述しても、 「配列が余分にコピーされ」なくなります。 # そのパッチを流してもよろしいですか?>著者様 -- Hideto "rubyholic" ISHIBASHI ----Next_Part(Tue_Mar_28_19:24:26_2000_809)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=flyweight.rb # GoF's FLYWEIGHT PATTERN # Copyright (c) 2000 Hideto ISHIBASHI # # Flyweight module that enables a large number of small objects to be shared. # # 1) It uses parameters of the `initialize' as hash keys. # 2) Objects created by direct call of "Class#new" are not shared. # 3) Attributes of flyweights should not be changed after creation. # Remember all the objects that have the same key are shared. # # The followings are defined in a class/module that includes Flyweight. # class instance variable: @__pool__ # class methods: __create_flyweight__, __remove_flyweight__, # alias_create_flyweight, alias_remove_flyweight module Flyweight def Flyweight.append_features(klass) klass.instance_eval %{ @__pool__ = {} def __create_flyweight__(*key) if @__pool__.has_key?(key) @__pool__[key] else @__pool__[key] = new_obj = new(*key) new_obj end end def __remove_flyweight__(*key) @__pool__.delete(key) end } ["create", "remove"].each {|method_name| klass.instance_eval %{ def alias_#{method_name}_flyweight(alias_name) alias_name = alias_name.id2name if alias_name.kind_of?(Integer) instance_eval %{ alias #\{alias_name\} __#{method_name}_flyweight__ } end } } end end if __FILE__ == $0 def ok?(condition) raise "NG!" unless condition end class Foo include Flyweight alias_create_flyweight :create alias_remove_flyweight :remove def initialize(str) @str = str end attr_accessor :str # DANGER! Attributes should not be changed. # attr_reader :str # This is ok. end foo = Foo.create("foo") foo2 = Foo.create("foo") foo3 = Foo.new("foo") ok? foo.str == foo2.str ok? foo.equal?(foo2) ok? foo.str == foo3.str #ok? foo.equal?(foo3) # NG (foo3 is created by Class#new) # 2 way to change foo2.str => "foofoo" begin foo2.str = "foofoo" # (*a) DANGER! ok? foo.str == "foo" # (*b) NG (foo is changed unexpectedly) rescue foo.str = "foo" end # again with a safe manner ok? foo.str == foo2.str foo2 = Foo.create("foofoo") # (*a) SAFE ok? foo.str == "foo" # (*b) OK end ----Next_Part(Tue_Mar_28_19:24:26_2000_809)----