LoginSignup
0
2

More than 5 years have passed since last update.

Rubyデザインパターン - 生成に関するパターン

Last updated at Posted at 2017-04-02

Singleton

概要

そのクラスのインスタンスが一つしかないことを保証する
オブジェクトを外部から直接生成させることを防ぎ、クラス自体に同時に生成できるオブジェクトの数を管理させる

使い道

常に同じオブジェクトをプログラム内で扱いたい
DBのコネクション数を制限したい

require 'singleton'
class SingletonObject
  # instanceメソッドが定義され、newメソッドがprivateに設定される
  include Singleton
  attr_accessor :counter, :name
  def initialize
    @counter = 0
    @name = "Singleton"
  end
end

obj1 = SingletonObject.instance
obj1.counter += 1
p "--- #{obj1.name} ---"
p obj1.counter

obj2 = SingletonObject.instance
obj2.counter += 1
obj2.name = "UpdatedName"
p "--- #{obj1.name} ---"
p obj2.counter
p obj1.equal?(obj2)

# "--- Singleton ---"
# 1
# "--- UpdatedName ---"
# 2
# true

Builder

概要

複雑なインスタンスの生成を他のオブジェクト(Director)にまかせる
Builderが作業を担当
Directorが作業過程を担当

# ConcreteBuilder
class SaltWater
  attr_accessor :water, :salt, :color
  def initialize(water, salt, color)
    @water = water
    @salt = salt
    @color = color
  end

  def add_material(salt_amount)
    @salt += salt_amount
  end

  def update_color
    @color = "blue"
  end
end

# ConcreteBuilder
class SugarWater
  attr_accessor :water, :sugar, :color
  def initialize(water, sugar, color)
    @water = water
    @sugar = sugar
    @color = color
  end

  def add_material(sugar_amount)
    @sugar += sugar_amount
  end

  def update_color
    @color = "red"
  end
end

# Builder
class WaterWithMaterialBuilder
  attr_reader :water_with_material
  def initialize(class_name)
    @water_with_material = class_name.new(0,0, "white")
  end

  def add_material(material_amount)
    @water_with_material.add_material(material_amount)
  end

  def add_water(water_amount)
    @water_with_material.water += water_amount
  end

  def update_color
    @water_with_material.update_color
  end

  def result
    @water_with_material
  end
end

# Director
class Director
  attr_reader :builder
  def initialize(builder)
    @builder = builder
  end

  def magic
    @builder.add_water(150)
    @builder.add_material(90)
    @builder.add_material(35)
    @builder.update_color()
  end
end

builder = WaterWithMaterialBuilder.new(SugarWater)
director = Director.new(builder)
director.magic
p builder.result
p director.builder.water_with_material.color
# #<SugarWater:0x007fed55824b10 @water=150, @sugar=125, @color="red">
# "red"

builder = WaterWithMaterialBuilder.new(SaltWater)
director = Director.new(builder)
director.magic
p builder.result
p director.builder.water_with_material.color
# #<SaltWater:0x007fed5582fe98 @water=150, @salt=125, @color="blue">
# "blue"

Abstract Factory

概要

関連し合うオブジェクトの集まりを生成することができる
矛盾のないオブジェクトの生成を行うため

class DinnaerFactory
  def initialize
  end
  def createDinner
    return [createAppetizer,createMain]
  end
  def createMain
  end
  def createAppetizer
  end
end

class Soup
  def initialize
  end
end

class Rice
  def initialize
  end
end

class Salad
  def initialize
  end
end

class Pizza
  def initialize
  end
end

class JapaneseFactory < DinnaerFactory
  def createMain
    Rice.new
  end
  def createAppetizer
    Soup.new
  end
end

class ItalyFactory < DinnaerFactory
  def createMain
    Pizza.new
  end
  def createAppetizer
    Salad.new
  end
end

japanese = JapaneseFactory.new
puts japanese.createDinner

italy = ItalyFactory.new
puts italy.createDinner

Factory Method

概要

インスタンスの生成をサブクラスに任せる
インスタンスの生成部分を切り離すことで、結合度を下げて追加・変更・保守を容易に

class Saxophone
  def initialize(name)
    @name = name
  end
  def play
    puts "#{self.class} #{@name} is being played!"
  end
end

class Trumpet
  def initialize(name)
    @name = name
  end
  def play
    puts "#{self.class} #{@name} is being played!"
  end
end

class InstrumentFactory
  def initialize(number_instruments)
    @instruments = []
    number_instruments.times do |i|
      instrument = new_instrument("No.#{i + 1}")
      @instruments << instrument
    end
  end
  def ship_out
    @tmp = @instruments.dup
    @instruments = []
    @tmp
  end
end

class SaxophoneFactory < InstrumentFactory
  def new_instrument(name)
    Saxophone.new(name)
  end
end

class TrumpetFactory < InstrumentFactory
  def new_instrument(name)
    Trumpet.new(name)
  end
end

factory = SaxophoneFactory.new(3)
saxophones = factory.ship_out
saxophones.each { |saxophone| saxophone.play }

factory = TrumpetFactory.new(2)
trumpets = factory.ship_out
trumpets.each { |trumpet| trumpet.play }
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2