Pattern Strategy
Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 45 di 57.
Il pattern strategy mette una parte dell’algoritmo in un proprio oggetto e consente all’oggetto principale di delegare a esso. Sostituire la strategia modifica il comportamento senza modificare la classe principale:
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.costOutput:
8.0
21Le strategie condividono solo il nome di un metodo, quindi funziona qualsiasi oggetto con cost: ancora una volta, duck typing. Aggiungere un nuovo modo di spedire significa aggiungere una classe, non un altro ramo all'interno di Shipment:
class Pickup
def cost(_kg)
0
end
end
shipment.strategy = Pickup.new # Shipment rimane invariatoIn Ruby una strategia è spesso una lambda. Qualsiasi cosa risponda a call può essere memorizzata e invocata, che si tratti di una lambda, di un oggetto metodo o di un oggetto di una tua classe:
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)Output:
RUBY IS GREAT
Ruby Is Great
**** is *****Scegli la strategia invece delle sottoclassi quando un oggetto deve cambiare il proprio comportamento mentre il programma è in esecuzione, oppure quando la variazione riguarda un singolo passaggio. Una sottoclasse fissa il comportamento per l'intera durata dell'oggetto:
# creazione di sottoclassi: fissata alla creazione
ExpressShipment.new(2)
# strategia: può cambiare in seguito
shipment = Shipment.new(2, Standard.new)
shipment.strategy = Express.newSfida
FacileCompleta le strategie di spedizione e ShippingCalculator. Standard#cost(kg) è pari a 5 più 1.50 per kg, Express#cost(kg) è pari a 15 più 3 per kg e Pickup#cost(kg) è pari a 0. Il calcolatore viene creato con una strategia, può cambiarla con strategy= e quote(kg) restituisce 2.5 kg by Express: 22.50, usando il nome della classe della strategia.
Il codice fornito parte da Standard e legge i comandi use express, use pickup, use standard oppure quote 2.5, stampando ogni preventivo.
Il tuo codice va inserito in standard.rb, express.rb, pickup.rb e shipping_calculator.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
require_relative 'standard'
require_relative 'express'
require_relative 'pickup'
require_relative 'shipping_calculator'
# Codice di input/output fornito: lascialo così com'è
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
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Classi e oggetti
Lavorare con i fileDefinire le classiVariabili d'istanzaMetodi e selfto_s e inspectRipasso - Tessera della biblioteca4Incapsulamento
Metodi privatiMetodi protettiSetter privatiProteggere lo statoRiepilogo - Distributore automatico7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMetodi astratticase e classiRiepilogo - Metodi di pagamento10Pattern di progettazione Parte 2
Delegazione con ForwardablePattern DecoratorPattern BuilderPattern State2Metodi di accesso e self
Metodi di lettura e scritturaSetter personalizzatiself nei metodiIdentità e uguaglianzaRiepilogo - Elenco contatti5Ereditarietà
SottoclassiRidefinizione dei metodiChiamare superis_a? e antenatiRiepilogo - Paghe del personale8Metodi speciali
Uguaglianza e hashMetodi degli operatoriIndicizzazione e appendCollezioni personalizzateRiepilogo - Frazioni11Progetto: Gestione della biblioteca
Libri e iscrittiPrendere in prestito i libriEsercitati da solo: Compilatore Ruby online