この記事は何
デザインパターンについて、Rubyでどのような使い方ができるかをまとめた記事です。
デザインパターン自体の解説は詳しく行いません。
Prototypeパターンとは
Prototypeパターンとは, オブジェクトを複製することで新しいインスタンスを生成するデザインパターンです。
詳しくはこちらをご覧ください。
Rubyでのコード例
以下のようにmodule
を用いてインターフェースの定義を行なっていきます。
module Prototype
def create_clone
clone()
end
end
class ConcreatePrototype1
include Prototype
def call
"Prototype1"
end
end
class ConcreatePrototype2
include Prototype
def call
"Prototype2"
end
end
class PrototypeManager
def initialize
@prototypes = {}
end
def register(key, instance)
@prototypes[key] = instance
end
def get_clone(key)
prototype = @prototypes[key]
prototype && prototype.create_clone
end
end
manager = PrototypeManager.new
manager.register(:prototype1, ConcreatePrototype1.new)
manager.register(:prototype2, ConcreatePrototype2.new)
prototype1 = manager.get_clone(:prototype1)
puts prototype1.call
prototype2 = manager.get_clone(:prototype2)
puts prototype2.call
実行結果
Prototype1
Prototype2
どのような時に使えるか
Prototypeパターンはインスタンス生成のコストが大きいインスタンスを複数用意する場合などに有効なデザインパターンです。
以下のように最初のインスタンス生成に時間はかかりますが、Prototypeパターンを適用することではじめ以外のインスタンスの作成は高速化することが可能です。
module Prototype
def create_clone
clone()
end
end
class HeavyInitializer
include Prototype
attr_accessor :name
def initialize
sleep(4)
puts 'Initialized'
@name = nil
end
end
class PrototypeManager
def initialize
@prototypes = {}
end
def register(key, instance)
@prototypes[key] = instance
end
def get_clone(key)
prototype = @prototypes[key]
prototype && prototype.create_clone
end
end
manager = PrototypeManager.new
manager.register(:heavy_initializer, HeavyInitializer.new)
instances = []
10.times do |i|
instance = manager.get_clone(:heavy_initializer)
instance.name = "Name #{i}"
instances << instance
end
puts instances.map(&:name)
実行結果
Initialized
Name 0
Name 1
Name 2
Name 3
Name 4
Name 5
Name 6
Name 7
Name 8
Name 9