¿Existen patrones de diseño conocidos para implementar modelos de descuento?
Por modelos de descuento, me refiero a lo siguiente:
Si un cliente compra el Producto X, el Producto Y y el Producto Z, obtiene un descuento del 10% o $ 100.
Si un cliente compra 100 unidades de Producto X, obtiene un descuento del 15% o $ 500
Si un cliente ha traído en el último año más de $ 100K, obtiene un descuento fijo del 20%
Si un cliente ha comprado 2 unidades de Producto X, obtiene 1 unidad de Producto X (o Producto Y) gratis.
...
¿Existe un patrón genérico que se pueda aplicar para manejar todos los escenarios anteriores? Estoy pensando en algunos modelos, pero no puedo encontrar uno genérico.
design
design-patterns
financial
Kanini
fuente
fuente
Respuestas:
Si el problema es que necesita aplicar múltiples descuentos, en determinadas circunstancias, es posible que desee considerar el patrón de la Cadena de responsabilidad .
En pocas palabras, pasa la información que desea procesar al primer procesador y, a partir de ahí, decide si la pasa a otros procesadores antes de devolver el resultado.
De esta manera, puede cambiar la estructura y la secuencia de los procesadores sin cambiar el código de llamada.
fuente
Los patrones de estrategia, decorador y estado se destacan para mí como posibles puntos de partida. El estado puede ser particularmente útil para 2 o 3, ya que 2 depende del estado del pedido y 3 depende del estado del cliente dentro de un período de tiempo. Estrategia y Decorador se destacan para los demás, ya que puede usar la estrategia para implementar múltiples algoritmos de cálculo de precio de pedido y decorador para agregar nuevos descuentos al pedido.
Sin embargo, recuerde que los patrones de diseño son solo modelos. Puede que no se aplique un solo patrón, sino más bien un sistema de patrones. También considere realizar modificaciones en los modelos descritos para que se adapten mejor a su solución. Es mejor tener un buen diseño que forzar un patrón donde no necesariamente ayuda solo por el hecho de poder decir que tiene un patrón.
fuente
Bueno, diseñaría un modelo de descuento como un par "Precondición" y "Descuento", donde "Precondición" es una clase con métodos
o y
y el descuento tiene un método
void ApplyTo(Customer c)
. Esto le brinda la capacidad de combinar cualquier tipo de condición previa con cualquier tipo de descuento (creo que esta es una forma de "patrón de puente").Si tiene un número fijo de condiciones previas, puede resolver el problema creando subtipos específicos (patrón de estrategia). Sin embargo, cuando se permite que sus condiciones previas sean muy complejas, con declaraciones lógicas como AND, OR y NOT, puede implementar mejor algún tipo de intérprete de reglas para las condiciones. Las reglas pueden ser una cadena de texto sin formato escrita en un simple "lenguaje específico de dominio".
Lo mismo ocurre con la clase "Descuento", puede tener algunos subtipos para diferentes tipos de descuentos, o un enfoque general donde las reglas de descuento se dan en forma de texto, evaluadas por algún intérprete.
fuente
Probablemente necesite una interfaz IDiscount ya que todos los diferentes descuentos son lo mismo, y queremos tratarlos conceptualmente como descuentos genéricos.
La clase "pedido de este cliente" probablemente necesite una colección de Descuentos. ¿Lista? ¿Picadillo? ¿Lista enlazada? No me importa todavía. ¡Se aplican descuentos a la compra, no al cliente!
Mantenga la construcción de instancias de descuento separada del cliente, el carrito de compras, el historial, etc. Cambiará mucho, como señaló @jfrankcarr.
Probablemente una clase diferente para cada descuento, ya que el algoritmo y los parámetros para cada descuento varían enormemente e impredeciblemente.
Veo un gran manejo de eventos, ya que el cálculo del descuento responde a los cambios del carrito de compras, y viceversa.
Aplicación de patrón de diseño
strategy pattern
. IDiscount es la interfaz para implementar diferentes algoritmos de descuento.Veo a
factory
. Ciertamente, no unaabstract factory pattern
clase completa , sino una sola clase en este punto del análisis. Razonablemente, debe haber un solo lugar donde haya suficiente contexto para decidir qué descuentos se aplican y luego crearlos. Una clase. Si las reglas para aplicar los descuentos explotan más tarde debido a una seta del Departamento de Marketing, cualquier lógica adicional de Construcción de descuentos aún debe fusionarse en esta clase base de fábrica, creo.Puedo ver
Chain of Responsibility
. Esto no es mutuamente exclusivo de lafactory
idea. En lugar de repetir una colección de descuentos, cada descuento llama al siguiente tipo. La clase "pedido del cliente" no tiene una colección de descuentos en este caso.El factor "hmmmm ..." en la Cadena de responsabilidad, creo, es que cada descuento tiene una referencia a la siguiente. La implicación es que el orden importa. Que no es el caso. Además, el concepto que representa el CDR es que un objeto no puede manejar la solicitud, por lo que se pasa "a la siguiente autoridad superior". Nuestro modelo es diferente. La única solicitud es calcular. Todo descuento hace esto. La salida o el efecto puede ser nulo pero se calcula cada descuento. Me inclino instintivamente hacia una mayor fidelidad en el mundo real.
Supuestos
¿Qué cambia, qué permanece igual?
Los descuentos son muy diferentes. Diferentes números y tipos de parámetros para formar cada regla.
Los argumentos para los descuentos que califican cambian a medida que cambia el carrito de compras.
El número de descuentos disponibles cambia
Los descuentos que este cliente califica para cambios a medida que cambia su carrito de compras.
El historial de compras no cambia en el contexto de esta compra
El costo total cambia dinámicamente en función de las líneas de compra y los descuentos aplicados.
Después de la aplicación inicial, la salida de un descuento puede cambiar, ya que la cantidad de compra cambia, por ejemplo.
fuente
Lógicamente, un modelo de descuento puede ser cualquier cosa , por lo que no puede suponer que puede programar todos los casos por adelantado. Tampoco nadie que responda su pregunta puede estar completamente seguro de lo que realmente necesita. Sin embargo, suponiendo que obtenga los tipos habituales de descuentos que se encuentran en el mundo real ...
Una gran pregunta es si los descuentos se programarán o si desea que los usuarios los ingresen. Como se mencionó anteriormente, nunca se puede programar, pero generalmente el objetivo es tratar de hacer que ingrese más datos como en casos comunes, en lugar de programarlos a todos. Esto se aplica en cierta medida, incluso si los programadores se utilizan para crear todos los descuentos.
Martin Fowler menciona "Método de instancia individual" en "Patrones de análisis: modelos de objetos reutilizables" como parte de cómo implementar "Reglas de contabilización" para sistemas de contabilidad, pero las reglas parecen bastante similares a las suyas. Daría más detalles pero es un trabajo protegido por derechos de autor y
Para una interfaz de usuario, debe encontrar casos de uso que sean bastante simples o crear un intérprete y un generador de consultas. Posiblemente ambos, uno para casos simples y otro más avanzado. Si escribe un intérprete, es probable que este sea un caso bastante bueno para usar el patrón Intérprete, ya que es relativamente simple de codificar en comparación con un generador de analizador, y el tiempo de análisis más lento probablemente no importará realmente. (Si te gusta el uso de generadores de analizadores sintácticos no dejar que te detenga).
No trate de hacer todo con un intérprete, aunque - en algún momento usted está programando en su propio idioma de mala muerte, por lo que también podría utilizar una de verdad. Si su lenguaje interpretado es compatible con funciones (que probablemente debería apoyar llamándolos - definirlos es dudosa) las que se pueden codificar en un lenguaje real. No ir más lejos por este camino que tiene que hacerlo.
No importa lo que hagas, eventualmente alguien va a querer que el descuento se basará en si ha comprado un plazo de 30 días hábiles de una promoción - donde cuentan días laborales solamente si no hay vacaciones en la región definida por cualquiera código postal de la tienda o las del cliente código postal. Así que no se trata de diseñar el sistema perfecto de antemano - asuma que ocasiones deberá escribir el código para los nuevos tipos de descuentos y diseño en consecuencia.
fuente
Es que no hay ningún punto está preguntando si hay un patrón útil para esto? ¿Qué tipo de patrón se requiere: estructural o de comportamiento?
Idealmente, si tuviera que escribir un software para esto, todo lo que se necesita es un algoritmo . Una función simple que calcula el descuento total de la siguiente manera:
¡No necesitas nada más que esto!
Para aclarar: entiendo que habrá muchas reglas: la más básica de dicha representación debe tener la forma de una base de reglas (conjunto de atributos de datos y el descuento resultante contra ella) y la función como la anterior la iteraría para calcularla. Si las reglas se agregan o eliminan, no debería terminar cambiando el código, solo cambie la base de la regla.
Se requerirá un patrón solo si necesitamos diferentes objetos para acceder a las API de cada uno o comunicarnos para establecer una tarea.
PD: Piénselo: cuando el cortafuegos procesa paquetes y los pasa o los rechaza (o los modifica), ¿qué patrón de diseño utiliza? ¡La respuesta es NINGUNA de las descritas anteriormente!
fuente