Definition: Definieren Sie bei einer Sprache eine Darstellung seiner Grammatik und definieren Sie einen Dolmetscher, der die Darstellung verwendet, um Sätze in der Sprache zu interpretieren.
Typ: Verhaltensmuster
Klassendiagramm:
Der Interpreter -Modus ist ein relativ selten verwendeter Modus, und ich habe diesen Modus noch nie verwendet. Schauen wir uns den Interpreter -Modus an.
Struktur des Interpretermodus
Abstract Interpreter: Deklarieren Sie eine abstrakte Schnittstelle (oder eine abstrakte Klasse), an die alle konkreten Ausdrücke implementiert werden sollen. Die Schnittstelle ist hauptsächlich eine Interpret () -Methode, die als Erläuterungsoperation bezeichnet wird. Die spezifische Interpretationsaufgabe wird durch ihre verschiedenen Implementierungsklassen abgeschlossen, und der spezifische Interpreter wird durch den Terminator-Interpreter-Terminalpression bzw. der nicht terminalen Interpreter-Non-terminalexpression abgeschlossen.
Terminator Expression: Implementiert Interpretationsoperationen, die mit Elementen in der Grammatik verbunden sind. Normalerweise gibt es in einem Interpreter -Muster nur einen Terminator -Expression, aber es gibt mehrere Instanzen, die verschiedenen Terminatoren entsprechen. Die Hälfte des Terminators ist eine Betriebseinheit in der Grammatik. Zum Beispiel gibt es eine einfache Formel R = R1+R2, wobei R1 und R2 Terminatoren sind, und die entsprechenden Dolmetscher, die R1 und R2 analysieren, sind Terminatoren.
Nicht terminale Expression: Jede Regel in der Grammatik entspricht einer nicht terminalen Expression. Nicht terminale Ausdrücke sind im Allgemeinen Operatoren oder andere Schlüsselwörter in der Grammatik. Beispielsweise ist in der Formel R = R1 + R2 ein nicht terminaler Zeichen, und der Interpreter von Parsing + ist ein nicht terminaler Charakter. Nicht terminale Ausdrücke nehmen nach der Komplexität der Logik zu, und im Prinzip entspricht jede Grammatikregel einer nicht terminalen Expression.
Umgebungsrolle: Die Aufgabe dieser Rolle wird im Allgemeinen verwendet, um die spezifischen Werte zu speichern, die jedem Terminator in der Grammatik entsprechen, z. B. r = R1+R2. Wir weisen 100 bis R1 und 200 bis R2 zu. Diese Informationen müssen in der Umweltrolle gespeichert werden. In vielen Fällen verwenden wir MAP, um als Umweltrolle zu dienen.
Beispiel
Geben wir ein Beispiel für Addition, Subtraktion, Multiplikation und Abteilung. Die Implementierungsidee stammt aus dem Beispiel in "Java und Muster". Die Funktionen jeder Rolle werden gemäß den oben genannten Spezifikationen implementiert.
// Kontext (Umgebung) Rolle, verwenden Sie HashMap, um die numerischen Werte zu speichern, die Variablen -Klassenkontext entsprechen {private map valuemap = new Hashmap (); public void addValue (Variable x, int y) {Integer yi = new Integer (y); valuemap.put (x, yi); } public int LookupValue (Variable x) {int i = ((Integer) Valuemap.get (x)). IntValue (); kehre I zurück; }} // Abstract Expression -Rolle können Sie auch Schnittstellen verwenden, um die abstrakte Klassenexpression zu implementieren. } // Terminator Expression Rolle Klasse Konstante Erweitert Ausdruck {private int i; public Constant (int i) {this.i = i; } public int interpretieren (context con) {return i; }} Klasse Variable erweitert den Ausdruck {public int interpretieren (context con) {// Dies ist ein variables Objekt, das die Interpretation der Methode return con.lookupValue (this); }} // Nicht -Terminator -Expression Rollenklasse Class erweitert Expression {private Expression links, rechts; öffentliche Adresse (Ausdruck links, Ausdruck rechts) {this.left = links; this.Right = rechts; } public int interpretieren (context con) {links zurückkehren.interpret (con) + rechts.interpret (con); }} class subtract erweitert den Ausdruck {privater Ausdruck links, rechts; public subtract (Expression links, Ausdruck rechts) {this.left = links; this.Right = rechts; } public int interpretieren (context con) {links zurückkehren.interpret (con) - rechts.interpret (con); }} class multiply erweitert den Ausdruck {privater Ausdruck links, rechts; public multiply (Expression links, Ausdruck rechts) {this.left = links; this.Right = rechts; } public int interpretieren (context con) {links zurückkehren.interpret (con) * rechts.interpret (con); }} Klasse Division erweitert den Ausdruck {privater Ausdruck links, rechts; Public Division (Ausdruck links, Ausdruck rechts) {this.left = links; this.Right = rechts; } public int interpretieren (context con) {try {return links.interpret (con) / rechts.interpret (con); } catch (AritheMeticexception ae) {System.out.println ("Divorc ist 0!"); Return -11111; }}} // Testen Sie das Programm, berechnen Sie (a*b)/(a-b+2) public class Test {private statische Ausdruck ex; privater statischer Kontextkontext; public static void main (String [] args) {con = new context (); // Variablen und Konstanten variable a = new Variable () festlegen; Variable b = neue Variable (); Konstante c = neue Konstante (2); // die variable con.addValue (a, 5) zuweisen; con.addValue (b, 7); // Betrieb analysieren wir die Struktur des Satzes selbst, konstruieren ex = neue Division (neuer Multiplikum (a, b), neu add (neuer Subtrahieren (A, B), c)); System.out.println ("Das Betriebsergebnis ist:"+ex.interpret (con)); }} Vor- und Nachteile des Interpreter -Modus
Der Dolmetscher ist ein einfaches Tool zur Syntaxanalyse. Sein wichtigster Vorteil ist seine Erweiterbarkeit. Das Ändern der Syntaxregeln erfordert nur die Änderung der entsprechenden nicht terminalen Zeichen. Wenn Sie die Syntax erweitern, müssen Sie nur einen nicht terminalen Charakter hinzufügen.
Das Interpreter-Muster wird jedoch veranlassen, dass sich die Klasse erweitert und jede Syntax einen nicht terminalen Expression erzeugen. Wenn die Syntax -Regeln relativ komplex sind, kann eine große Anzahl von Klassendateien generiert werden, was den Wartungswartung zu großen Problemen bringt. Gleichzeitig kümmert sich jeder nicht terminale Ausdruck, da die rekursive Anrufmethode angewendet wird, nur um die Ausdrücke, die mit sich selbst zusammenhängen. Jeder Ausdruck muss das Endergebnis kennen und rekursiv sein. Unabhängig davon, ob es sich um eine objektorientierte Sprache oder eine prozessorientierte Sprache handelt, ist die Rekursion eine nicht empfohlene Weise. Aufgrund der Verwendung vieler Schleifen und Rekursion ist Effizienz ein Problem, das nicht ignoriert werden kann. Insbesondere bei der Interpretation eines Parsing -Komplexes, langwieriger Syntax ist die Effizienz unerträglich.
Anwendbare Szenarien für den Interpreter -Modus
Der Interpreter -Modus kann in den folgenden Fällen verwendet werden:
Es gibt eine einfache Syntaxregel, wie z. B. eine SQL -Anweisung. Wenn wir die RM -Konvertierung basierend auf SQL -Anweisungen durchführen müssen, können wir das Interpreter -Muster verwenden, um die Aussage zu interpretieren.
Einige sich wiederholende Probleme, wie die vier Operationen von Addition, Subtraktion, Multiplikation und Teilung, aber die Formeln sind jedes Mal unterschiedlich. Manchmal ist es a+bc*d, manchmal ist es a*b+cd usw. Die Formeln verändern sich ständig, aber sie sind alle mit den vier nicht terminalen Zeichen von Addition, Subtraktion, Multiplikation und Teilung verbunden. Zu diesem Zeitpunkt können wir den Interpreter -Modus verwenden.
Dinge zu beachten
Der Interpreter -Modus ist wirklich ein relativ selten verwendeter Modus, da es zu problematisch ist, ihn zu erhalten. Stellen Sie sich vor, wenn eine Reihe von nicht terminalen Dolmetschern nicht mit den Regeln der Grammatik im Voraus vertraut sind oder die Grammatik besonders einfach ist, wird es schwierig sein, seine Logik zu verstehen. Der Interpreter -Modus wird in der tatsächlichen Systementwicklung selten eingesetzt, da er Probleme wie Effizienz, Leistung und Wartung verursachen kann.