strategy source software patterns pattern method making book python oop design-patterns architecture class-factory

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:

  1. Ponga ese código dentro de un método de clase Result , digamos parse_rules . Result constructor de Result tomaría como argumento un objeto de rules y lo pasaría a self.parse_rules .

  2. 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 toma rules como argumento y devuelve un objeto de result 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 las Rules que los generan (y tal vez incluso a los Data originales).
  • Cada subclase de Rules puede personalizar su creación de Result .
  • Se siente natural (para mí): Rules aplicadas al Result rendimiento de Data .
  • 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 de Result 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.

Efectos secundarios:

  • Acoplamiento : elevará el acoplamiento entre Rules y Data :
    • 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á.

¿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.