Menu
Coddy logo textTech

Fabrika Deseni

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 43 / 57.

fabrika deseni, nesne oluşturmayı tek bir yerde toplar. Çağıranlar genellikle adını belirterek ihtiyaç duydukları şeyi ister ve hangi sınıfın oluşturulduğunu bilmeden hazır bir nesne alır:

class Square
  def initialize(side)
    @side = side
  end

  def area
    @side * @side
  end
end

class Circle
  def initialize(r)
    @r = r
  end

  def area
    (3.14159 * @r * @r).round(2)
  end
end

class ShapeFactory
  def self.create(kind, size)
    case kind
    when "square" then Square.new(size)
    when "circle" then Circle.new(size)
    end
  end
end

puts ShapeFactory.create("square", 3).area
puts ShapeFactory.create("hexagon", 3).inspect

Çıktı:

9
nil

İsimlerden sınıflara eşleme, factory'yi daha kısa ve genişletilmesi daha kolay hâle getirir. Sınıflar nesnedir; bu nedenle bir hash içinde saklanabilir ve new gönderilebilir:

class Dog
  def speak
    "Woof"
  end
end

class Cat
  def speak
    "Meow"
  end
end

class AnimalFactory
  KINDS = { "dog" => Dog, "cat" => Cat }.freeze

  def self.create(kind)
    klass = KINDS.fetch(kind) { raise ArgumentError, "unknown animal: #{kind}" }
    klass.new
  end
end

puts AnimalFactory.create("cat").speak
begin
  AnimalFactory.create("cow")
rescue ArgumentError => e
  puts e.message
end

Çıktı:

Meow
unknown animal: cow

Bir fabrika, diğer kodların çalışma zamanında yeni türleri kaydetmesine de olanak tanıyabilir; böylece bir tür eklemek, fabrikayı düzenlemek anlamına gelmez:

class Plugins
  @kinds = {}

  class << self
    def register(name, klass)
      @kinds[name] = klass
    end

    def build(name)
      @kinds.fetch(name).new
    end

    def names
      @kinds.keys.sort
    end
  end
end

class Zip
  def run
    "zipping"
  end
end

Plugins.register("zip", Zip)
puts Plugins.build("zip").run
p Plugins.names

Çıktı:

zipping
["zip"]

Çağıranlar yalnızca nesnelerin ne yapabildiğine, burada area veya speak işlevlerine bağlıdır; somut sınıflara asla bağlı değildir. Yeni bir şekil, bir yeni sınıf ve fabrikaya bir yeni giriş anlamına gelir; başka hiçbir yerde değişiklik yapılmaz:

shape = ShapeFactory.create(kind, size)   # Square, Circle, ...
puts shape.area                           # çağıran asla bir sınıf adı vermez
challenge icon

Görev

Kolay

Şekilleri ve ShapeFactory.create(kind, size) işlevini tamamla. Square, Circle ve Triangle (eşkenar), temel Shape sınıfını paylaşır; bu sınıfın to_s metodu, sınıf adını küçük harfle, boyutu ve alanı iki ondalık basamakla göstererek square 3: area 9.00 döndürür. Pi için 3.14159 ve üçgen için Math.sqrt(3) / 4 * size**2 kullan. Fabrika, türü dondurulmuş bir hash sabiti olan KINDS içinde arar ve bilinmeyen bir tür için nil döndürür.

Sağlanan kod square 3 satırlarını okur, her şekil için fabrikaya başvurur ve şekli yazdırır veya unknown shape: hexagon yazdırır.

Kodun shape.rb, square.rb, circle.rb, triangle.rb ve shape_factory.rb dosyalarında yer almalıdır. main.rb sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'shape'
require_relative 'square'
require_relative 'circle'
require_relative 'triangle'
require_relative 'shape_factory'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input = []
while (line = gets)
  input << line.chomp
end
input.each do |line|
  kind, size = line.split
  shape = ShapeFactory.create(kind, size.to_f)
  puts shape || "unknown shape: #{kind}"
end
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi