Wzorzec fabryki
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 43 z 57.
Wzorzec fabryki umieszcza tworzenie obiektów w jednym miejscu. Kod wywołujący prosi o to, czego potrzebuje, często po nazwie, i otrzymuje gotowy obiekt, nie wiedząc, która klasa została utworzona:
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).inspectWynik:
9
nilHasz odwzorowujący nazwy na klasy sprawia, że fabryka jest krótsza i łatwiejsza do rozszerzenia. Klasy są obiektami, więc można je przechowywać w haszu i wysyłać do nich 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
endWynik:
Meow
unknown animal: cowFabryka może również pozwolić innemu kodowi rejestrować nowe rodzaje w czasie działania, dzięki czemu dodanie rodzaju nie wymaga edytowania fabryki:
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.namesWynik:
zipping
["zip"]Wywołujący zależą tylko od tego, co obiekty potrafią robić — tutaj od area lub speak — nigdy od konkretnych klas. Nowy kształt oznacza jedną nową klasę i jeden nowy wpis w fabryce, bez żadnych zmian w innych miejscach:
shape = ShapeFactory.create(kind, size) # Square, Circle, ...
puts shape.area # kod wywołujący nigdy nie podaje nazwy klasyWyzwanie
ŁatwyUzupełnij klasy figur oraz ShapeFactory.create(kind, size). Square, Circle i Triangle (równoboczny) dziedziczą po klasie bazowej Shape, której metoda to_s zwraca square 3: area 9.00, z nazwą klasy zapisaną małymi literami, rozmiarem i polem z dokładnością do dwóch miejsc po przecinku. Użyj 3.14159 jako wartości pi oraz Math.sqrt(3) / 4 * size**2 dla trójkąta. Fabryka wyszukuje rodzaj w zamrożonej stałej haszującej KINDS i zwraca nil dla nieznanego rodzaju.
Dostarczony kod odczytuje wiersze square 3, prosi fabrykę o utworzenie każdej figury i ją wyświetla albo unknown shape: hexagon.
Twój kod umieść w plikach shape.rb, square.rb, circle.rb, triangle.rb i shape_factory.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'shape'
require_relative 'square'
require_relative 'circle'
require_relative 'triangle'
require_relative 'shape_factory'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasZmienne instancjiMetody i selfto_s i inspectPowtórzenie – karta biblioteczna4Hermetyzacja
Metody prywatneMetody chronionePrywatne setteryOchrona stanuPowtórzenie – automat vendingowy7Polimorfizm i typowanie kacze
PolimorfizmTypowanie kaczeMetody abstrakcyjnecase i klasyPowtórzenie – metody płatności10Wzorce projektowe, część 2
Delegowanie z ForwardableWzorzec dekoratoraWzorzec budowniczegoWzorzec stanu2Metody dostępowe i self
Gettery i setteryWłasne setteryself w metodachTożsamość i równośćPowtórzenie – lista kontaktów5Dziedziczenie
PodklasyNadpisywanie metodWywoływanie superis_a? i przodkowiePowtórka – lista płac pracowników8Metody specjalne
Równość i hashMetody operatorówIndeksowanie i dodawanieWłasne kolekcjePowtórka – ułamki11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Kompilator Ruby online