Intérprete (patrón de diseño)

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 5 de abril de 2017; las comprobaciones requieren 12 ediciones .
Interprete
Interprete
Tipo de conductual
Objetivo resuelve un problema frecuente, sujeto a cambios
Descrito en Patrones de diseño

Un intérprete es un  patrón de diseño de comportamiento que resuelve una tarea frecuente, pero sujeta a cambios. También conocido como lenguaje pequeño (pequeño)

Problema

Hay una tarea que ocurre con frecuencia, sujeta a cambios.

Solución

Cree un intérprete que resuelva este problema.

Beneficios

La gramática se vuelve fácil de ampliar y cambiar, las implementaciones de las clases que describen los nodos del árbol de sintaxis abstracta son similares (fácilmente codificadas). Puede cambiar fácilmente cómo se evalúan las expresiones.

Desventajas

Mantener una gramática con un gran número de reglas es difícil.

Ejemplo

La tarea de buscar cadenas por patrón se puede resolver creando un intérprete que defina la gramática del lenguaje. El "Cliente" construye una oración en forma de un árbol de sintaxis abstracta, en cuyos nodos hay objetos de las clases "TerminalExpression" y "NonterminalExpression" (recursivo), luego el "Cliente" inicializa el contexto y llama al Parse( Contexto) operación. Cada nodo de tipo "NonterminalExpression" define una operación Parse para cada subexpresión. Para la clase "NonTerminalExpression", la operación Parse determina la base de la recursividad. "AbstractExpression" define la operación abstracta Parse común a todos los nodos en el árbol de sintaxis abstracta. "Contexto" contiene información global para el intérprete.

C#

Texto fuente en C# utilizando el sistema ; utilizando System.Collections ; espacio de nombres DoFactory.GangOfFour.Interpreter.Structural { class Program { static void Main () { var context = new Context (); var input = new MiExpresión (); var expresión = nueva OrExpresión { Izquierda = nueva EqualsExpression { Izquierda = entrada , Derecha = nueva MiExpresión { Valor = "4" } }, Derecha = nueva EqualsExpression { Izquierda = entrada , Derecha = nueva MiExpresión { Valor = "cuatro" } } } ; // Salida: entrada verdadera . Valor = "cuatro" ; expresión _ Interpretar ( contexto ); consola _ WriteLine ( contexto.resultado.pop ( ) ) ; _ // Salida: entrada falsa . Valor = "44" ; expresión _ Interpretar ( contexto ); consola _ WriteLine ( contexto.resultado.pop ( ) ) ; _ } } contexto de clase { public Stack < string > Result = new Stack < string >(); } interfaz Expresión { void Interpretar ( Contexto contexto ); } clase abstracta OperatorExpression : Expression { public Expression Left { private get ; conjunto ; } derecho de expresión público { private get ; conjunto ; } public void Interpretar ( Contexto contextual ) { Izquierda . Interpretar ( contexto ); cadena leftValue = contexto . resultado _ estallar (); Correcto _ Interpretar ( contexto ); cadena rightValue = contexto . resultado _ estallar (); DoInterpret ( contexto , valorizquierdo , valorderecho ); } vacío abstracto protegido DoInterpret ( contexto contexto , cadena valorizquierdo , cadena valorderecho ); } class EqualsExpression : OperatorExpression { protected override void DoInterpret ( Contexto contexto , cadena valorizquierdo , cadena valorderecho ) { contexto . resultado _ Empujar ( valorizquierdo == valorderecho ? "verdadero" : "falso" ); } } class OrExpression : OperatorExpression { protected override void DoInterpret ( Contexto contexto , cadena valorizquierdo , cadena valorderecho ) { contexto . resultado _ Empujar ( valorizquierdo == "verdadero" || valorderecho == "verdadero" ? "verdadero" : "falso" ); } } clase MiExpresión : Expresión { public string Value { private get ; conjunto ; } public void Interpretar ( Contexto contexto ) { contexto . resultado _ Empuje ( Valor ); } } }

Pitón

Código fuente en Python __doc__ = ''' Un sistema para evaluar y manipular expresiones booleanas. Ejemplo de Gang of Four - "Patrones de diseño: Elementos de software orientado a objetos reutilizable" ''' de abc import ABCMeta , método abstracto Contexto de clase : """ Contexto de tiempo de ejecución del intérprete """ def __init__ ( self , variables : dict = {}) -> Ninguno : """ Constructor. :param variables: un diccionario de coincidencias entre nombres de variables y sus valores " "" self ._variables = variables clase ContextException ( Excepción ): """ Excepción lanzada en caso de trabajo incorrecto con esta clase """ pase def lookup ( self , nombre : str ) -> bool : """ Obtiene el valor de una variable por su nombre :param nombre: nombre de variable """ if nombre en self . _variables : return self . _variables [ name ] raise self . ContextException ( 'Variable desconocida {} ' . format ( name )) def asignar ( self , nombre : str , valor : bool ) -> Ninguno : """ Asigna un valor a una variable por su nombre :param nombre: nombre de variable :param valor: valor de variable " "" self ._variables [ nombre ] = valor class BooleanExp ( metaclase = ABCMeta ): """ Expresión booleana abstracta """ @abstractmethod def evaluar ( self , context : Context ) -> bool : """ Obtener el resultado de la expresión booleana """ pasar clase ConstantExp ( BooleanExp ): """ Constante booleana """ def __init__ ( self , valor : bool ): """ Constructor. :param valor: expresión valor (Verdadero o Falso) "" " self ._value = valor def evaluar ( self , context : Context ): return self . _valor class VariableExp ( BooleanExp ): """ Variable booleana (el valor de las variables se almacena en el objeto de contexto del intérprete) """ def __init__ ( self , nombre : str ) -> Ninguno : """ Constructor. :param nombre: nombre de variable " "" self ._name = nombre def evaluar ( auto , contexto : Contexto ) -> bool : devolver contexto . búsqueda ( self . _name ) class BinaryOperationExp ( BooleanExp , metaclass = ABCMeta ): """ Clase abstracta para operaciones lógicas binarias """ def __init__ ( self , izquierda : BooleanExp , derecha : BooleanExp ) -> Ninguno : """ Constructor. :param left: operando izquierdo :param right: operando derecho " " " self ._left = izquierda self ._right = derecha clase AndExp ( BinaryOperationExp ): """ Conjunción """ def evaluar ( self , context : Context ) -> bool : return self . _izquierda . evaluar ( contexto ) y auto . _bien . evaluar ( contexto ) clase OrExp ( BinaryOperationExp ): """ Disyunción """ def evaluar ( self , context : Context ) -> bool : return self . _izquierda . evaluar ( contexto ) o auto . _bien . evaluar ( contexto ) clase NotExp ( BooleanExp ): """ Negativo """ def __init__ ( self , operando : BooleanExp ) -> Ninguno : """ Constructor. :param operando: operando al que se le aplica la operación """ self . _operando = operando def evaluar ( self , context : Context ) -> bool : return not self . _operando . evaluar ( contexto ) def ejecutar_prueba ( contexto : Contexto , x : bool , y : bool ) -> Ninguno : """ Una función para realizar pruebas en nuestro intérprete de contexto """ . asignar ( 'x' , x ) contexto . asignar ( 'y' , y ) expresión = OrExp ( # (Verdadero y x) o (y y (no x)) AndExp ( ConstantExp ( True ), VariableExp ( 'x' )), AndExp ( VariableExp ( 'y' ) , NotExp ( VariableExp ( 'x' ))) ) print ( expresión . evaluar ( contexto )) if __name__ == '__main__' : print ( 'OUTPUT:' ) contexto = Contexto () ejecutar_prueba ( contexto , Verdadero , Falso ) ejecutar_prueba ( contexto , Falso , Verdadero ) ejecutar_prueba ( contexto , Falso , Falso ) ''' SALIDA: Verdadero Verdadero Falso '''

PHP

codigo fuente php <?php /** * Ejemplo de patrón de intérprete usando composición */ Clase abstracta Expresión { privado estático $_count = 0 ; privado $_clave = nulo ; función abstracta pública interpretar ( InterpreterContext $ contexto ); public function getKey () { if ( ! isset ( $this -> _key ) ) { self :: $_count ++ ; $esto -> _clave = self :: $_cuenta ; } devuelve $esto -> _clave ; } } class ExpresiónLiteral extiende Expresión { privado $_valor = nulo ; public function __construct ( $valor ) { $esto -> _valor = $valor ; } función pública interpretar ( Contexto del intérprete $contexto ) { $contexto -> reemplazar ( $esto , $esto -> _valor ); } } class VariableExpression extiende Expresión { privado $_nombre = nulo ; privado $_val = nulo ; public function __construct ( $name , $val = null ) { $this -> _name = $name ; $esto -> _val = $val ; } función pública interpretar ( InterpreterContext $contexto ) { if ( ! is_null ( $this -> _val ) ) $contexto -> replace ( $this , $this -> _val ); } public function setValue ( $valor ) { $esto -> _val = $valor ; } public function getKey () { return $this -> _name ; } } clase abstracta OperadorExpresión extiende Expresión { protegido $operandoizquierdo = nulo ; protegido $operandoderecho = nulo ; public function __construct ( Expresión $operandoizquierdo , Expresión $operandoderecho ) { $this -> operandoizquierdo = $operandoizquierdo ; $this -> rightoperand = $rightoperand ; } función pública interpretar ( InterpreterContext $ contexto ) { $ esto -> operando izquierdo -> interpretar ( $ contexto ); $this -> rightoperand -> interpret ( $context ); $resultadoizquierda = $contexto -> búsqueda ( $esto -> operando izquierdo ); $resultadoderecho = $contexto -> búsqueda ( $este -> operandoderecho ); $this -> doInterpret ( $context , $resultleft , $resultright ); } función abstracta protegida doInterpret ( InterpreterContext $context , $resultleft , $resultright ); } class EqualsExpression extiende OperatorExpression { función protegida doInterpret ( InterpreterContext $contexto , $resultadoizquierda , $resultadoderecha ) { $contexto -> reemplazar ( $esto , $resultadoizquierda == $resultadoderecha ); } } clase BooleanOrExpression extiende OperatorExpression { función protegida doInterpret ( InterpreterContext $context , $resultleft , $resultright ) { $context -> replace ( $this , $resultleft || $resultright ); } } clase BooleanAndExpression extiende OperatorExpression { función protegida doInterpret ( InterpreterContext $context , $resultleft , $resultright ) { $context -> replace ( $this , $resultleft && $resultright ); } } contexto de intérprete de clase { privado $_expressionstore = matriz (); función pública reemplazar ( Expresión $exp , $valor ) { $this -> _expressionstore [ $exp -> getKey ()] = $valor ; } búsqueda de función pública ( Expresión $exp ) { return $this -> _expressionstore [ $exp -> getKey ()]; } } $contexto = new InterpreterContext (); $entrada = new VariableExpression ( 'entrada' ); $instrucción = new BooleanOrExpression ( new EqualsExpression ( $input , new LiteralExpression ( "four" ) ), new EqualsExpression ( $input , new LiteralExpression ( "4" ) ) ); foreach ( matriz ( "cuatro" , "4" , "52" ) como $valor ) { $entrada -> establecerValor ( $valor ); imprimir " { $valor } :<br>" ; $sentencia -> interpretar ( $contexto ); imprimir $contexto -> buscar ( $estado de cuenta ) ? "Cumple<br><br>" : "No coincide<br><br>" ; } ?>

Véase también