Menu
CoddyTech

Pola Factory

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Ruby di Coddy. Pelajaran 43 dari 57.

Pola factory menempatkan pembuatan object di satu tempat. Pemanggil meminta yang mereka butuhkan, sering kali berdasarkan nama, lalu menerima object siap pakai tanpa mengetahui class mana yang dibuat:

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

Output:

9
nil

Hash yang memetakan nama ke class membuat factory lebih singkat dan lebih mudah dikembangkan. Class adalah object, jadi class dapat disimpan dalam hash dan dikirim ke new:

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

Output:

Meow
unknown animal: cow

Factory juga dapat mengizinkan kode lain untuk mendaftarkan jenis baru saat program berjalan, sehingga menambahkan jenis tidak berarti mengedit factory:

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

Output:

zipping
["zip"]

Pemanggil hanya bergantung pada hal yang dapat dilakukan object, dalam kasus ini area atau speak, bukan pada class konkret. Bentuk baru berarti satu class baru dan satu entri baru di factory, tanpa perubahan di bagian lain:

shape = ShapeFactory.create(kind, size)   # Square, Circle, ...
puts shape.area                           # pemanggil tidak pernah menyebut nama class
challenge icon

Tantangan

Mudah

Lengkapi bentuk-bentuk dan ShapeFactory.create(kind, size). Square, Circle, dan Triangle (sama sisi) menggunakan class dasar Shape, yang to_s-nya mengembalikan square 3: area 9.00, dengan nama class dalam huruf kecil, ukuran, dan luas dengan dua angka desimal. Gunakan 3.14159 untuk pi dan Math.sqrt(3) / 4 * size**2 untuk segitiga. Factory mencari jenis bentuk dalam konstanta hash beku KINDS dan mengembalikan nil untuk jenis bentuk yang tidak dikenal.

Kode yang disediakan membaca baris square 3, meminta factory membuat setiap bentuk, lalu mencetaknya, atau unknown shape: hexagon.

Tuliskan kodemu di shape.rb, square.rb, circle.rb, triangle.rb, dan shape_factory.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

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

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Ruby online