Introducción
El patrón de diseño Interpreter es un patrón de comportamiento que proporciona una forma de evaluar o interpretar sentencias en un lenguaje. Este patrón es útil cuando se necesita interpretar un lenguaje específico, como un lenguaje de comandos, un lenguaje de programación o un lenguaje de consulta.
Objetivos del Módulo
- Comprender el propósito y la estructura del patrón Interpreter.
- Aprender a implementar el patrón Interpreter en un ejemplo práctico.
- Identificar situaciones en las que el patrón Interpreter es útil.
¿Qué es el Patrón Interpreter?
El patrón Interpreter define una representación gramatical para un lenguaje y un intérprete que utiliza esta representación para interpretar sentencias en el lenguaje.
Componentes Clave
- Contexto: Contiene información global que el intérprete necesita.
- Expresión Abstracta: Declara una interfaz para interpretar el contexto.
- Expresión Terminal: Implementa una operación interpretativa para símbolos terminales en la gramática.
- Expresión No Terminal: Implementa una operación interpretativa para símbolos no terminales en la gramática.
Diagrama de Clases
+----------------+ +------------------+ | Context |<------| AbstractExpression| +----------------+ +------------------+ / \ / \ / \ +----------------+ +----------------+ | TerminalExpression | | NonTerminalExpression | +----------------+ +----------------+
Ejemplo Práctico
Vamos a implementar un intérprete simple para una expresión matemática que solo maneja sumas y restas.
Paso 1: Definir el Contexto
El contexto contiene información que es global para el intérprete.
class Context: def __init__(self): self.variables = {} def get_value(self, variable): return self.variables.get(variable, 0) def set_value(self, variable, value): self.variables[variable] = value
Paso 2: Definir la Expresión Abstracta
La expresión abstracta declara una interfaz para interpretar el contexto.
from abc import ABC, abstractmethod class Expression(ABC): @abstractmethod def interpret(self, context): pass
Paso 3: Definir Expresiones Terminales
Las expresiones terminales implementan operaciones interpretativas para símbolos terminales.
class Number(Expression): def __init__(self, number): self.number = number def interpret(self, context): return self.number class Variable(Expression): def __init__(self, name): self.name = name def interpret(self, context): return context.get_value(self.name)
Paso 4: Definir Expresiones No Terminales
Las expresiones no terminales implementan operaciones interpretativas para símbolos no terminales.
class Add(Expression): def __init__(self, left, right): self.left = left self.right = right def interpret(self, context): return self.left.interpret(context) + self.right.interpret(context) class Subtract(Expression): def __init__(self, left, right): self.left = left self.right = right def interpret(self, context): return self.left.interpret(context) - self.right.interpret(context)
Paso 5: Uso del Patrón Interpreter
Ahora podemos usar el patrón Interpreter para evaluar una expresión.
# Crear el contexto context = Context() context.set_value('x', 5) context.set_value('y', 10) # Crear la expresión: x + y - 3 expression = Subtract(Add(Variable('x'), Variable('y')), Number(3)) # Interpretar la expresión result = expression.interpret(context) print(f"Resultado: {result}") # Resultado: 12
Ejercicio Práctico
Ejercicio
Implementa un intérprete para una expresión que incluya multiplicación y división.
- Define las clases
Multiply
yDivide
que extiendan la claseExpression
. - Implementa el método
interpret
para cada una de estas clases. - Crea una expresión que combine suma, resta, multiplicación y división y evalúala.
Solución
class Multiply(Expression): def __init__(self, left, right): self.left = left self.right = right def interpret(self, context): return self.left.interpret(context) * self.right.interpret(context) class Divide(Expression): def __init__(self, left, right): self.left = left self.right = right def interpret(self, context): return self.left.interpret(context) / self.right.interpret(context) # Crear el contexto context = Context() context.set_value('x', 6) context.set_value('y', 3) # Crear la expresión: (x * y) / 2 + 4 - 1 expression = Subtract(Add(Divide(Multiply(Variable('x'), Variable('y')), Number(2)), Number(4)), Number(1)) # Interpretar la expresión result = expression.interpret(context) print(f"Resultado: {result}") # Resultado: 10.0
Conclusión
El patrón Interpreter es útil para definir una gramática y un intérprete para un lenguaje específico. Aunque no es uno de los patrones más comunes, es extremadamente útil en situaciones donde se necesita interpretar o evaluar sentencias en un lenguaje específico. En este módulo, hemos aprendido a implementar el patrón Interpreter y hemos visto un ejemplo práctico de su uso.
Curso de Patrones de Diseño de Software
Módulo 1: Introducción a los Patrones de Diseño
- ¿Qué son los Patrones de Diseño?
- Historia y Origen de los Patrones de Diseño
- Clasificación de los Patrones de Diseño
- Ventajas y Desventajas de Usar Patrones de Diseño
Módulo 2: Patrones Creacionales
- Introducción a los Patrones Creacionales
- Singleton
- Factory Method
- Abstract Factory
- Builder
- Prototype
Módulo 3: Patrones Estructurales
Módulo 4: Patrones de Comportamiento
- Introducción a los Patrones de Comportamiento
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Módulo 5: Aplicación de Patrones de Diseño
- Cómo Seleccionar el Patrón Adecuado
- Ejemplos Prácticos de Uso de Patrones
- Patrones de Diseño en Proyectos Reales
- Refactorización Usando Patrones de Diseño
Módulo 6: Patrones de Diseño Avanzados
- Patrones de Diseño en Arquitecturas Modernas
- Patrones de Diseño en Microservicios
- Patrones de Diseño en Sistemas Distribuidos
- Patrones de Diseño en Desarrollo Ágil