Strategiemuster
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 45 von 57.
Das Strategie-Muster verlagert einen Teil eines Algorithmus in ein eigenes Objekt und lässt das Hauptobjekt an dieses delegieren. Durch den Austausch der Strategie ändert sich das Verhalten, ohne dass die Hauptklasse geändert werden muss:
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.costAusgabe:
8.0
21Die Strategien haben nur einen Methodennamen gemeinsam, daher funktioniert jedes Objekt mit cost: wieder Duck-Typing. Eine neue Versandart hinzuzufügen bedeutet, eine Klasse hinzuzufügen, nicht einen weiteren Zweig in Shipment:
class Pickup
def cost(_kg)
0
end
end
shipment.strategy = Pickup.new # Shipment bleibt unverändertIn Ruby ist eine Strategie oft ein Lambda. Alles, worauf call angewendet werden kann, lässt sich speichern und aufrufen, egal ob es sich um ein Lambda, ein Methodenobjekt oder ein Objekt deiner eigenen Klasse handelt:
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)Ausgabe:
RUBY IS GREAT
Ruby Is Great
**** is *****Wähle eine Strategie statt Unterklassen, wenn ein Objekt sein Verhalten während der Laufzeit des Programms ändern muss oder wenn die Variation aus einem einzelnen Schritt besteht. Eine Unterklasse legt das Verhalten für die gesamte Lebensdauer des Objekts fest:
# Unterklassenbildung: bei der Erstellung festgelegt
ExpressShipment.new(2)
# Strategie: kann später geändert werden
shipment = Shipment.new(2, Standard.new)
shipment.strategy = Express.newAufgabe
EinfachVervollständige die Versandstrategien und ShippingCalculator. Standard#cost(kg) beträgt 5 plus 1.50 pro kg, Express#cost(kg) beträgt 15 plus 3 pro kg und Pickup#cost(kg) beträgt 0. Der Rechner wird mit einer Strategie erstellt, kann sie mit strategy= ändern, und quote(kg) gibt 2.5 kg by Express: 22.50 zurück, wobei der Klassenname der Strategie verwendet wird.
Der bereitgestellte Code beginnt mit Standard und liest Befehle wie use express, use pickup, use standard oder quote 2.5 ein und gibt jedes Angebot aus.
Dein Code gehört in standard.rb, express.rb, pickup.rb und shipping_calculator.rb. main.rb enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
require_relative 'standard'
require_relative 'express'
require_relative 'pickup'
require_relative 'shipping_calculator'
# Vorgegebener Ein-/Ausgabecode: unverändert lassen
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
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Klassen und Objekte
Arbeiten mit DateienKlassen definierenInstanzvariablenMethoden und selfto_s und inspectRückblick – Bibliotheksausweis4Kapselung
Private MethodenGeschützte MethodenPrivate SetterZustand schützenRückblick – Verkaufsautomat7Polymorphismus und Duck Typing
PolymorphismusDuck TypingAbstrakte MethodenFälle und KlassenRückblick – Zahlungsmethoden2Getter und Setter sowie self
Leser und SchreiberBenutzerdefinierte Setterself in MethodenIdentität und GleichheitWiederholung – Kontaktliste5Vererbung
UnterklassenMethoden überschreibensuper aufrufenis_a? und VorfahrenRückblick – Gehaltsabrechnung des Personals8Spezielle Methoden
Gleichheit und HashOperator-MethodenIndexieren und AnhängenBenutzerdefinierte CollectionsRückblick – Brüche11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Online-Ruby-Compiler