-
-
Save alexandre/5bed42f22a639559fe14 to your computer and use it in GitHub Desktop.
| """ | |
| Vamos supor que temos um numero X de clientes e cada cliente tem 2 tipos de | |
| fechamento diferentes: fechamento parcial e fechamento geral. | |
| Além disso, cada cliente tem um padrão para esses arquivos (cada fechamento gera um), já que esses | |
| arquivos serão utilizados em um sistema de terceiros. | |
| A principio, eu pensei que apenas o pattern strategy solucionava o problema... | |
| de acordo com o cliente eu devolvia uma classe especifica que geraria o | |
| arquivo. Mas o problema é que eu esqueci que haviam 2 tipos de fechamento. | |
| Com isso, eu pensei em utilizar herança. Por que? porque o processo básico | |
| para chamar os arquivos de fechamento (indiferente do tipo) é o mesmo. | |
| No final ficaria algo como: | |
| >>> import exporters | |
| >>> customer = Customer() | |
| >>> exporters.ExporterA(customer=customer.name) | |
| >>> exporter.generate_file() | |
| >>> # o mesmo para o segundo tipo | |
| >>> exporters.ExporterB(customer=customer.name) | |
| >>> exporter.generate_file() | |
| Obs.: Supondo que o meu entendimento do pattern strategy está correto. =] | |
| """ | |
| import collections | |
| class Exporter(): | |
| @property | |
| def default_exporter(self): | |
| raise NotImplementedError('Should have implemented this') | |
| @property | |
| def available_exporters(self): | |
| raise NotImplementedError('Should have implemented this') | |
| def __new__(cls, *args, **kwargs): | |
| if 'customer' not in kwargs.keys(): | |
| raise RuntimeError('You have to inform a customer name') | |
| exporter_type = super(Exporter, cls).__new__(cls) | |
| exporter = collections.defaultdict( | |
| lambda: exporter_type.default_exporter, exporter_type.available_exporters) | |
| return exporter[kwargs['customer']](*args, **kwargs) | |
| class ExporterA(Exporter): | |
| @property | |
| def default_exporter(self): | |
| return default_exporter_a | |
| @property | |
| def available_exporters(self): | |
| return { | |
| 'Customer_foo': exporter_a_customer_foo, | |
| 'Customer_bar': exporter_a_customer_bar, | |
| 'Customer_ble': exporter_a_customer_ble, | |
| } | |
| class ExporterB(Exporter): | |
| @property | |
| def default_exporter(self): | |
| return default_exporter_b | |
| @property | |
| def available_exporters(self): | |
| return { | |
| 'Customer_foo': exporter_b_customer_foo, | |
| 'Customer_bar': exporter_b_customer_bar, | |
| 'Customer_ble': exporter_b_customer_ble, | |
| } |
Diego,
Deve existir um gap mesmo. =]
Mas a minha dúvida e também o motivo de usar herança é que além de ter o exporter diferente (A e B), cada cliente tem uma variação do A e uma variação do B. (available_exporters)
Eu poderia usar apenas 1 função com um dict para recuperar a variação(e.g. recuperar a variação do exporter A para o cliente foo) e passar isso para o exporter (da mesma forma que vc explicou a estratégia concreta). Faz sentido?
Eu acho que agora eu consegui entender melhor... eu não preciso de uma classe para cada tipo de exporter mesmo. Eu vou separar essa parte de recuperar a "variação" e simplesmente passar ela para o "closer".
Isso ai :)
Talvez suas estratégias sejam as "variações".
@drgarcia1986 e @daniloakamine-luizalabs
Apenas um rascunho mental enquanto eu não paro para ler...
# module exporters.py
import collections
EXPORTERS_A = collections.defaultdict(
lambda: default_a_exporter,
{
'Customer_foo': exporter_a_customer_foo,
'Customer_bar': exporter_a_customer_bar,
'Customer_ble': exporter_a_customer_ble,
}
)
EXPORTERS_B = collections.defaultdict(
lambda: default_b_exporter,
{
'Customer_foo': exporter_b_customer_foo,
'Customer_bar': exporter_b_customer_bar,
'Customer_ble': exporter_b_customer_ble,
}
)
class Closer:
def __init__(self, exporter):
self.exporter = exporter
def generate_file(self, *args, **kwargs):
return self.exporter.generate_file(*args, **kwargs)customer = Customer()
# mesmo processo para o EXPORTERS_A e o EXPORTERS_B
exporter = exporters.EXPORTER_A[customer.name]()
closer = exporters.Closer(exporter)
closer.generate_file('xyz') # ... segue a vida
seguindo a ideia do Diego e o comentário sobre "trocar a estratégia em tempo de execução", essa é uma das grandes vantagens do Strategy.
o seu objeto "closer" ainda é o mesmo, não há necessidade de instancia-lo novamente para aplicar outra estratégia.