Patrón Strategy
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 45 de 57.
El patrón strategy coloca una parte de un algoritmo en su propio objeto y permite que el objeto principal delegue en él. Cambiar la estrategia modifica el comportamiento sin cambiar la clase principal:
class Standard
def cost(kg)
5 + kg * 1.5
end
end
class Express
def cost(kg)
15 + kg * 3
end
end
class Shipment
attr_writer :strategy
def initialize(kg, strategy)
@kg = kg
@strategy = strategy
end
def cost
@strategy.cost(@kg)
end
end
s = Shipment.new(2, Standard.new)
puts s.cost
s.strategy = Express.new
puts s.costSalida:
8.0
21Las estrategias solo comparten un nombre de método, así que cualquier objeto con cost funciona: tipado pato de nuevo. Añadir una nueva forma de realizar envíos significa añadir una clase, no otra rama dentro de Shipment:
class Pickup
def cost(_kg)
0
end
end
shipment.strategy = Pickup.new # Shipment no cambiaEn Ruby, una estrategia suele ser una lambda. Cualquier elemento que responda a call puede almacenarse e invocarse, ya sea una lambda, un objeto método o un objeto de tu propia clase:
class TextFormatter
def initialize(strategy)
@strategy = strategy
end
def format_all(words)
words.map { |w| @strategy.call(w) }.join(" ")
end
end
class Censor
def call(word)
word.size > 3 ? "*" * word.size : word
end
end
words = %w[ruby is great]
puts TextFormatter.new(->(w) { w.upcase }).format_all(words)
puts TextFormatter.new(:capitalize.to_proc).format_all(words)
puts TextFormatter.new(Censor.new).format_all(words)Salida:
RUBY IS GREAT
Ruby Is Great
**** is *****Elige la estrategia en lugar de las subclases cuando un objeto deba cambiar su comportamiento mientras el programa se ejecuta, o cuando la variación sea un único paso. Una subclase fija el comportamiento durante toda la vida del objeto:
# subclasificación: fijo en la creación
ExpressShipment.new(2)
# estrategia: se puede cambiar después
shipment = Shipment.new(2, Standard.new)
shipment.strategy = Express.newDesafío
FácilCompleta las estrategias de envío y ShippingCalculator. Standard#cost(kg) es 5 más 1.50 por kg, Express#cost(kg) es 15 más 3 por kg y Pickup#cost(kg) es 0. El calculador se crea con una estrategia, puede cambiarla con strategy= y quote(kg) devuelve 2.5 kg by Express: 22.50, utilizando el nombre de la clase de la estrategia.
El código proporcionado comienza con Standard y lee los comandos use express, use pickup, use standard o quote 2.5, mostrando cada cotización.
Tu código debe ir en standard.rb, express.rb, pickup.rb y shipping_calculator.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
require_relative 'standard'
require_relative 'express'
require_relative 'pickup'
require_relative 'shipping_calculator'
# Código de entrada/salida suministrado: déjalo tal como está
input = []
while (line = gets)
input << line.chomp
end
strategies = { "standard" => Standard, "express" => Express, "pickup" => Pickup }
calc = ShippingCalculator.new(Standard.new)
input.each do |line|
cmd, arg = line.split
if cmd == "use"
calc.strategy = strategies[arg].new
else
puts calc.quote(arg.to_f)
end
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