Padrão Factory
Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 43 de 57.
O padrão factory coloca a criação de objetos em um só lugar. Os chamadores solicitam o que precisam, geralmente pelo nome, e recebem um objeto pronto sem saber qual classe foi construída:
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).inspectSaída:
9
nilUm hash de nomes para classes torna a fábrica mais curta e fácil de estender. Classes são objetos, então podem ser armazenadas em um hash e receber 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
endSaída:
Meow
unknown animal: cowUma fábrica também pode permitir que outro código registre novos tipos em tempo de execução, portanto adicionar um tipo não significa editar a 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.namesSaída:
zipping
["zip"]Os chamadores dependem apenas do que os objetos podem fazer, neste caso area ou speak, nunca das classes concretas. Uma nova forma significa uma nova classe e uma nova entrada na fábrica, sem nenhuma alteração em outro lugar:
shape = ShapeFactory.create(kind, size) # Square, Circle, ...
puts shape.area # o chamador nunca nomeia uma classeDesafio
FácilComplete as formas e ShapeFactory.create(kind, size). Square, Circle e Triangle (equilátero) compartilham a classe base Shape, cujo to_s retorna square 3: area 9.00, com o nome da classe em minúsculas, o tamanho e a área com duas casas decimais. Use 3.14159 para pi e Math.sqrt(3) / 4 * size**2 para o triângulo. A fábrica procura o tipo em uma constante de hash congelada KINDS e retorna nil para um tipo desconhecido.
O código fornecido lê linhas square 3, solicita à fábrica cada forma e a imprime, ou unknown shape: hexagon.
Seu código deve ficar em shape.rb, square.rb, circle.rb, triangle.rb e shape_factory.rb. main.rb contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
require_relative 'shape'
require_relative 'square'
require_relative 'circle'
require_relative 'triangle'
require_relative 'shape_factory'
# Código de entrada/saída fornecido: mantenha-o 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 lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesVariáveis de InstânciaMétodos e selfto_s e inspectRevisão - Cartão da Biblioteca4Encapsulamento
Métodos privadosMétodos protegidosSetters privadosProtegendo o estadoRevisão - Máquina de venda automática7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMétodos Abstratoscase e ClassesRevisão - Métodos de Pagamento2Acessores e self
Leitores e GravadoresSetters Personalizadosself nos MétodosIdentidade e IgualdadeRecapitulação - Lista de Contatos5Herança
SubclassesSobrescrita de métodosChamando superis_a? e ancestraisRevisão - Folha de pagamento da equipe8Métodos Especiais
Igualdade e hashMétodos de OperadoresIndexação e AdiçãoColeções PersonalizadasRevisão - Frações11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de Ruby online