From: Hideto ISHIBASHI Date: 2000-03-29T20:14:09+09:00 Subject: [ruby-list:21688] Re: GoF's Flyweight Pattern ----Next_Part(Wed_Mar_29_20:02:57_2000_809)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit 石橋秀仁です。 問題ないということなので、"lifegame.rb"のパッチを流します。 # ありがとうございます > まつもとさん 添付の original-patch は、272ページの変更そのものです(比較のため)。 flyweight-patch は、"[ruby-list:21671] GoF's Flyweight Pattern" にある flyweight.rb をrequireします。singleton-patch は、 (ほぼ)同じことの汎用性の無いやり方による実装です。 パッチをあてるには、"geometry.rb"と"lifegame.rb"のあるディレクトリで、 patch -p1 < xxx-patch としてください。 (以下はゴミ) ほんとうは singleton-patch の方法に汎用性を持たせたものを、 flyweight.rb として実現したかったのですが、ぼくには無理でした (^^;;; メソッド(DefaultCompetitionArea.find_all)の「返り値」も共有するための、 汎用的な方法がありそうなのですが・・・、あまり汚なく無い方法で。 あと、ArrayにFlyweightをインクルードできませんでした。なぜでしょうか? どこかで「組み込みクラスへのインクルードは云々」と聞いたような・・・ ちなみに、flyweight-patchの中の、geometry.rbの変更はオマケです。 Geometryインスタンスはそれほど多くならないので、実際は必要ないかと。 -- Hideto "rubyholic" ISHIBASHI ----Next_Part(Wed_Mar_29_20:02:57_2000_809)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=original-patch diff -Ncr lifegame.orig/lifegame.rb lifegame/lifegame.rb *** lifegame.orig/lifegame.rb Mon Mar 27 04:47:59 2000 --- lifegame/lifegame.rb Mon Mar 27 04:59:11 2000 *************** *** 33,51 **** for y in 0..height - 1 @neighbors[y] = a = Array.new(width) ! if y == 0 ! competition_area = DefaultCompetitionArea.find_all{|geom| geom.y >= 0} ! elsif y == height - 1 ! competition_area = DefaultCompetitionArea.find_all{|geom| geom.y <= 0} ! else ! competition_area = DefaultCompetitionArea end - - a[0] = competition_area.find_all{|geom| geom.x >= 0} - for x in 1.. width - 2 - a[x] = competition_area - end - a[width - 1] = competition_area.find_all{|geom| geom.x <= 0} end #(B) 最初の生物の設定 --- 33,44 ---- for y in 0..height - 1 @neighbors[y] = a = Array.new(width) ! for x in 0.. width - 1 ! a[x] = DefaultCompetitionArea.find_all{|geom| ! y + geom.y >= 0 and y + geom.y < height and ! x + geom.x >= 0 and x + geom.x < width ! } end end #(B) 最初の生物の設定 ----Next_Part(Wed_Mar_29_20:02:57_2000_809)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=flyweight-patch diff -cr lifegame.orig/geometry.rb lifegame/geometry.rb *** lifegame.orig/geometry.rb Mon Mar 27 04:48:05 2000 --- lifegame/geometry.rb Mon Mar 27 21:20:22 2000 *************** *** 1,10 **** # 座標クラス class Geometry ! ! #座標[y,x]の生成 ! def Geometry.[](y,x) ! new(y, x) ! end # 初期化 def initialize(y, x) --- 1,9 ---- + require "flyweight" + # 座標クラス class Geometry ! include Flyweight ! alias_create_flyweight :[] # 初期化 def initialize(y, x) diff -cr lifegame.orig/lifegame.rb lifegame/lifegame.rb *** lifegame.orig/lifegame.rb Mon Mar 27 19:45:19 2000 --- lifegame/lifegame.rb Mon Mar 27 21:20:50 2000 *************** *** 1,4 **** --- 1,6 ---- require "geometry" + require "delegate" + require "flyweight" #-- # *************** *** 10,20 **** # # ライフゲーム本体 class LifeGame ! DefaultCompetitionArea = [ Geometry[-1, -1], Geometry[-1, 0], Geometry[-1, 1], Geometry[0, -1], Geometry[0, 1], Geometry[1, -1], Geometry[1, 0], Geometry[1, 1] ! ] InitialPositionOffset = [ [-1, 0], [-1, 1], --- 12,28 ---- # # ライフゲーム本体 class LifeGame ! class CompetitionArea < DelegateClass(Array) ! include Enumerable ! include Flyweight ! alias_create_flyweight :create ! end ! ! DefaultCompetitionArea = CompetitionArea.create([ Geometry[-1, -1], Geometry[-1, 0], Geometry[-1, 1], Geometry[0, -1], Geometry[0, 1], Geometry[1, -1], Geometry[1, 0], Geometry[1, 1] ! ]) InitialPositionOffset = [ [-1, 0], [-1, 1], *************** *** 33,51 **** for y in 0..height - 1 @neighbors[y] = a = Array.new(width) ! if y == 0 ! competition_area = DefaultCompetitionArea.find_all{|geom| geom.y >= 0} ! elsif y == height - 1 ! competition_area = DefaultCompetitionArea.find_all{|geom| geom.y <= 0} ! else ! competition_area = DefaultCompetitionArea ! end ! ! a[0] = competition_area.find_all{|geom| geom.x >= 0} ! for x in 1.. width - 2 ! a[x] = competition_area end - a[width - 1] = competition_area.find_all{|geom| geom.x <= 0} end #(B) 最初の生物の設定 --- 41,54 ---- for y in 0..height - 1 @neighbors[y] = a = Array.new(width) ! for x in 0.. width - 1 ! a[x] = CompetitionArea.create( ! DefaultCompetitionArea.find_all {|geom| ! y + geom.y >= 0 and y + geom.y < height and ! x + geom.x >= 0 and x + geom.x < width ! } ! ) end end #(B) 最初の生物の設定 ----Next_Part(Wed_Mar_29_20:02:57_2000_809)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=singleton-patch diff -cr lifegame.orig/lifegame.rb lifegame/lifegame.rb *** lifegame.orig/lifegame.rb Mon Mar 27 19:45:19 2000 --- lifegame/lifegame.rb Wed Mar 29 19:45:34 2000 *************** *** 15,20 **** --- 15,30 ---- Geometry[0, -1], Geometry[0, 1], Geometry[1, -1], Geometry[1, 0], Geometry[1, 1] ] + DefaultCompetitionArea.instance_eval %{ + @__pool__ = {} + def find_all(*args, &blk) + ary = super + unless @__pool__.has_key?(ary) + @__pool__[ary] = ary + end + @__pool__[ary] + end + } InitialPositionOffset = [ [-1, 0], [-1, 1], *************** *** 33,51 **** for y in 0..height - 1 @neighbors[y] = a = Array.new(width) ! if y == 0 ! competition_area = DefaultCompetitionArea.find_all{|geom| geom.y >= 0} ! elsif y == height - 1 ! competition_area = DefaultCompetitionArea.find_all{|geom| geom.y <= 0} ! else ! competition_area = DefaultCompetitionArea ! end ! ! a[0] = competition_area.find_all{|geom| geom.x >= 0} ! for x in 1.. width - 2 ! a[x] = competition_area end - a[width - 1] = competition_area.find_all{|geom| geom.x <= 0} end #(B) 最初の生物の設定 --- 43,54 ---- for y in 0..height - 1 @neighbors[y] = a = Array.new(width) ! for x in 0.. width - 1 ! a[x] = DefaultCompetitionArea.find_all {|geom| ! y + geom.y >= 0 and y + geom.y < height and ! x + geom.x >= 0 and x + geom.x < width ! } end end #(B) 最初の生物の設定 ----Next_Part(Wed_Mar_29_20:02:57_2000_809)----