Patrón Factory
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 43 de 57.
El patrón de fábrica concentra la creación de objetos en un solo lugar. Los llamadores solicitan lo que necesitan, a menudo por nombre, y reciben un objeto listo sin saber qué clase se creó:
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).inspectSalida:
9
nilUn hash que asigna nombres a clases hace que la fábrica sea más corta y fácil de ampliar. Las clases son objetos, por lo que pueden almacenarse en un hash y recibir 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
endSalida:
Meow
unknown animal: cowUna fábrica también puede permitir que otro código registre nuevos tipos durante la ejecución, de modo que añadir un tipo no implique editar la fábrica:
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.namesSalida:
zipping
["zip"]Los invocadores dependen únicamente de lo que los objetos pueden hacer, aquí area o speak, nunca de las clases concretas. Una nueva forma significa una clase nueva y una nueva entrada en la fábrica, sin cambios en ningún otro lugar:
shape = ShapeFactory.create(kind, size) # Square, Circle, ...
puts shape.area # el llamador nunca nombra una claseDesafío
FácilCompleta las formas y ShapeFactory.create(kind, size). Square, Circle y Triangle (equiláteras) comparten la clase base Shape, cuyo to_s devuelve square 3: area 9.00, con el nombre de la clase en minúsculas, el tamaño y el área con dos decimales. Usa 3.14159 para pi y Math.sqrt(3) / 4 * size**2 para el triángulo. La fábrica busca el tipo en una constante de hash congelada KINDS y devuelve nil para un tipo desconocido.
El código proporcionado lee líneas square 3, solicita a la fábrica cada forma y la imprime, o unknown shape: hexagon.
Tu código va en shape.rb, square.rb, circle.rb, triangle.rb y shape_factory.rb. main.rb contiene el código de entrada/salida proporcionado y no se puede editar.
Pruébalo tú mismo
require_relative 'shape'
require_relative 'square'
require_relative 'circle'
require_relative 'triangle'
require_relative 'shape_factory'
# Código de entrada/salida suministrado: déjalo tal como está
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
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesVariables de instanciaMétodos y selfto_s e inspectRepaso: tarjeta de biblioteca4Encapsulación
Métodos privadosMétodos protegidosAsignadores privadosProtección del estadoRepaso: máquina expendedora7Polimorfismo y tipado pato
PolimorfismoTipado patoMétodos abstractoscase y clasesRepaso: métodos de pago2Accesores y self
Lectores y escritoresSetters personalizadosself en los métodosIdentidad e igualdadRepaso: lista de contactos5Herencia
SubclasesSobrescritura de métodosLlamar a superis_a? y ancestrosRepaso - Nómina del personal8Métodos especiales
Igualdad y hashMétodos de operadoresIndexación y adiciónColecciones personalizadasRepaso: fracciones11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de Ruby online