この記事は何
デザインパターンについて、Rubyでどのような使い方ができるかをまとめた記事です。
デザインパターン自体の解説は詳しく行いません。
Builerパターンとは
Builderパターンとは、生成するインスタンスへ渡すパラメータを段階的に組み立てることで、複雑なオブジェクトの生成を容易にするデザインパターンです。
詳しくはこちらをご覧ください。
Rubyでのコード例
以下のように、生成したいクラスの定義と、そのクラスを生成するBuilderクラスの実装を行います。
それぞれのメソッドでself
を返すようにすることで、メソッドチェーンでメソッドを書けるようにすることも可能です。
class Computer
def initialize(cpu:, ram:, storage:)
@cpu = cpu
@ram = ram
@storage = storage
end
def to_s
"CPU: #{@cpu}, RAM: #{@ram}, Storage: #{@storage}"
end
end
class ComputerBuilder
def initialize
@cpu = ''
@ram = ''
@storage = ''
end
def add_cpu(cpu)
@cpu = cpu
self
end
def add_ram(ram)
@ram = ram
self
end
def add_storage(storage)
@storage = storage
self
end
def build
Computer.new(cpu: @cpu, ram: @ram, storage: @storage)
end
end
builder = ComputerBuilder.new
computer = builder.add_cpu('Intel i9')
.add_ram('32GB')
.add_storage('1TB SSD')
.build
puts computer
実行結果
CPU: Intel i9, RAM: 32GB, Storage: 1TB SSD
どのような時に使えるか
以下のようなときにBuilderパターンは便利です。
- コンストラクタの種類が多く、コンストラクタに渡す値自体の計算が複雑な場合
- 最終的に生成するオブジェクトを不変にしたい場合
例えば、以下のように与えられた辺の長さを元に、表面積や体積などの値を保持したデータオブジェクトを生成する場合などにBuilderパターンは有効に活用できます。
class Box
attr_reader :length, :width, :height, :volume, :surface_area
def initialize(length:, width:, height:, volume:, surface_area:)
@length = length
@width = width
@height = height
@volume = volume
@surface_area = surface_area
end
def to_s
"Length: #{@length}, Width: #{@width}, Height: #{@height}, Volume: #{@volume}, Surface Area: #{@surface_area}"
end
end
class BoxBuilder
def initialize
@length = 0
@width = 0
@height = 0
end
def set_length(length)
@length = length
self
end
def set_width(width)
@width = width
self
end
def set_height(height)
@height = height
self
end
def calculate_volume
@length * @width * @height
end
def calculate_surface_area
2 * (@length * @width + @width * @height + @height * @length)
end
def build
volume = calculate_volume
surface_area = calculate_surface_area
Box.new(length: @length, width: @width, height: @height, volume: volume, surface_area: surface_area)
end
end
builder = BoxBuilder.new
box = builder.set_length(10)
.set_width(5)
.set_height(2)
.build
puts box
実行結果
Length: 10, Width: 5, Height: 2, Volume: 100, Surface Area: 160