Dichiarazione di non responsabilità: scriverò in Python e nel contesto dello sviluppo web con Django, ma questa domanda non è linguistica né specifica di un framework.
Diciamo che ho una classe PizzaManager
che funge da strumento di utilità per selezionare pizze in un menu Restaurant
. Il gestore pizza utilizza i dati che restaurant
deve eseguire le sue diverse azioni:
pizza_manager = PizzaManager(restaurant)
Il PizzaManager
funge da filtro su un elenco specifico di pizze. Il gestore si occupa di diversi elenchi di pizze alla volta in diversi scenari. Quindi lo stesso gestore di pizze potrebbe funzionare con all_pizzas
in un determinato livello e con pepperoni_pizzas
in un altro stadio. Poiché la pizza sorgente è una variabile variabile, abbiamo deciso di passarla attraverso il metodo di concatenamento, piuttosto che usare un setter tradizionale:
pizza_manager.with_pizzas(all_pizzas)
pizza_manager.with_pizzas(pepperoni_pizzas)
pizza_manager.with_pizzas(pizzas_of_the_year)
Essenzialmente, il metodo with_pizzas
funziona come segue:
def with_pizzas(self, pizzas):
self.pizzas = pizzas
return self
Come ho detto, il compito principale del manager è applicare i filtri alle pizze passate. Ad esempio, supponiamo di definire un metodo cheap_pizzas
che seleziona le pizze economiche dall'elenco self.pizzas
:
def cheap_pizzas():
self.filtered_pizzas = [pizza for pizza in self.pizzas if pizza.price <= self.threshold_price]
return self
all_pizzas = restaurant.pizza_set.all()
pizza_manager.with_pizzas(all_pizzas ).cheap_pizzas()
Possiamo continuare a filtrare concatenando un altro metodo:
pizza_manager.with_pizzas(all_pizzas).cheap_pizzas().top_pizzas()
Infine, per recuperare l'elenco delle pizze filtrate, eseguiamo solo il metodo get()
:
def get(self):
return self.pizzas
best_pizzas = pizza_manager.with_pizzas(restaurant.pizza_set.all()).cheap_pizzas().top_pizzas().get()
C'è comunque un avvertimento: non è possibile eseguire nessuno dei metodi di filtraggio a meno che non si sia passati prima nell'elenco pizza. Questo può sembrare ovvio, dal momento che il gestore non può operare su un elenco non esistente di pizze, ma questo può essere un errore quando si programma e si può commettere un errore in qualche modo facilmente. Non puoi farlo:
# we are going to get a TypeError here since self.pizzas is None at this point
PizzaManager(restaurant).cheap_pizzas()
Quindi sostanzialmente la mia domanda è come affrontare questa situazione. Come posso gestire correttamente l'accoppiamento dei metodi con i metodi concatenati allo stesso tempo? Come posso chiarire, da un punto di vista progettuale, che devi specificare l'elenco di pizze su cui il gestore sta per agire prima di eseguire uno qualsiasi dei metodi di filtraggio?
Si noti che il solo passaggio dell'elenco di pizze nel costruttore non è un'opzione valida, non voglio istanziare un singolo gestore ogni volta che voglio usare un elenco diverso di pizze.