python - source - pros y contras de usar fábrica vs constructor regular
python software patterns (5)
(Usando Python 3.2, aunque dudo que importe).
Tengo class Data
, class Rules
clase y Result
clase. Uso minúsculas para denotar una instancia de la clase.
Un objeto de rules
contiene reglas que, si se aplican a un objeto de data
, pueden crear un objeto de result
.
Estoy decidiendo dónde colocar el código (bastante complicado y evolutivo) que realmente aplica las reglas a los datos. Puedo ver dos opciones:
Ponga ese código dentro de un método de clase
Result
, digamosparse_rules
.Result
constructor deResult
tomaría como argumento un objeto derules
y lo pasaría aself.parse_rules
.Pon ese código dentro de una nueva clase
ResultFactory
.ResultFactory
sería una clase singleton, que tiene un método, por ejemplo,build_result
, que tomarules
como argumento y devuelve un objeto deresult
recién creado.
¿Cuáles son los pros y los contras de los dos enfoques?
Tercer escenario:
Es posible que desee considerar un tercer escenario:
- Coloque el código dentro del método
Rules.__call__
.
Result
creación de instancias como:result = rules(data)
Pros:
-
Result
pueden ser totalmente ajenos a lasRules
que los generan (y tal vez incluso a losData
originales). - Cada subclase de
Rules
puede personalizar su creación deResult
. - Se siente natural (para mí):
Rules
aplicadas alResult
rendimiento deData
. - Y tendrá un par de principios de GRASP de su parte:
- Creador : las instancias de las
Rules
tienen la información de inicialización para instancias deResult
y la pasan a la creación. - Information Expert : Information Expert llevará a colocar la responsabilidad en la clase con la mayor cantidad de información requerida para cumplirla.
- Creador : las instancias de las
Efectos secundarios:
- Acoplamiento : elevará el acoplamiento entre
Rules
yData
:- Debe pasar todo el conjunto de datos a todas las
Rules
- Lo que significa que cada una de las
Rules
debería poder decidir sobre qué datos se aplicará.
- Debe pasar todo el conjunto de datos a todas las
¿Por qué no poner las reglas en sus propias clases? Si crea una clase RuleBase, cada regla puede derivarse de ella. De esta forma, el polimorfismo se puede usar cuando los datos necesitan reglas aplicadas. Los datos no necesitan saber ni preocuparse de qué instancias de reglas se aplicaron (a menos que los datos sean los únicos que conozcan qué reglas se deben aplicar).
Cuando se deben invocar reglas, una instancia de datos puede usar RuleBase.ExecuteRules () y pasar como un argumento. La subclase correcta de la regla se puede elegir directamente de los datos, si los datos saben qué regla es necesaria. O puede usarse algún otro patrón de diseño, como Chain of Responsibility, donde Data invoca el patrón y permite que un resultado regrese.
Esto sería una gran discusión en la pizarra.
¿Se puede hacer que ResultFactory sea una función pura? No es útil crear un objeto singleton si todo lo que necesita es una función.
Bueno, el segundo es francamente tonto, especialmente con toda la singularidad. Si el Result
requiere Rules
para crear una instancia y no puede crear una sin ella, debe tomar eso como argumento para __init__
. No es necesario comprar patrones.
Los principios de diseño de GRASP proporcionan pautas para asignar responsabilidad a clases y objetos en el diseño orientado a objetos. Por ejemplo, el patrón del Creador sugiere: En general, una clase B debería ser responsable de crear instancias de clase A si se aplica uno, o preferiblemente más de lo siguiente:
- Las instancias de B contienen o agregan compuestas instancias de A
- Instancias de instancias de registro B de A
- Las instancias de B usan de cerca las instancias de A
- Las instancias de B tienen la información de inicialización para las instancias de A y la pasan a la creación.
En su ejemplo, tiene un código complicado y en evolución para aplicar reglas a los datos. Eso sugiere el uso del patrón de fábrica .
Poner el código en los resultados está contraindicado porque 1) los resultados no crean resultados, y 2) los resultados no son los expertos en información (es decir, no tienen la mayor parte del conocimiento que se necesita).
En resumen, ResultFactory parece un lugar razonable para concentrar el conocimiento de cómo aplicar reglas a los datos para generar resultados . Si tratara de aplicar toda esta lógica en los constructores de la clase para los resultados o las reglas, conduciría a un acoplamiento cerrado y a la pérdida de cohesión.