Wzorzec projektowy interpreter

Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 3295 razy

Opis wzorca projektowego interpreter

Wzorzec projektowy interpreter należy do czynnościowych wzorców projektowych. Jego zadaniem jest podział zadań interpretacji składni prostych wyrażeń arytmetycznych. Główna klasa parsuje dane przygotowując je dla podklas np. w przypadku interpretacji wyrażenia matematycznego: 5+2.5*3+5/5-5 główna instancja interpretera sparsuje to wyrażenie do postaci listy:

Następnie poszczególne instancje klas wykonają działania:

Przykładowy diagram UML wzorca projektowego interpreter

Użytkownik (program) tworzy instancję klasy Interpreter, która agreguje obiekty klas:

Przykład diagramu UML dla wzorca projektowego interpreter
Rys. 1
Przykład diagramu UML dla wzorca projektowego interpreter

Przykład implementacji wzorca projektowego interpreter w C++

#include <iostream> #include <string> #include <vector> const std::string operators("*/+-"); class Multiply; class Divided; class Add; class Subtract; class Interpreter{ protected: std::vector<std::string> equation; std::vector<std::string>::iterator findOperator(std::vector<std::string> &equation, std::string operatorName){ for(std::vector<std::string>::iterator i = equation.begin(); i < equation.end(); i++){ if((*i) == operatorName) return i; } return equation.end(); } void parseString(std::string equation){ std::string::size_type index = equation.find_first_of(operators); while(index != std::string::npos){ if(index != 0){ this->equation.push_back(equation.substr(0, index)); equation.erase(0, index); } this->equation.push_back(equation.substr(0, 1)); equation.erase(0, 1); index = equation.find_first_of(operators); } if(!equation.empty()){ this->equation.push_back(equation); } } virtual void interprete(std::vector<std::string> & equation){} Interpreter* multiplyOperation; Interpreter* divideOperation; Interpreter* addOperation; Interpreter* subtractOperation; public: Interpreter(std::string equation); Interpreter(){ multiplyOperation = divideOperation = addOperation = subtractOperation = NULL; } virtual ~Interpreter(){ if(multiplyOperation){ delete multiplyOperation; multiplyOperation = NULL; } if(divideOperation){ delete divideOperation; divideOperation = NULL; } if(addOperation){ delete addOperation; addOperation = NULL; } if(subtractOperation){ delete subtractOperation; subtractOperation = NULL; } } }; class Multiply : public Interpreter{ protected: std::vector<std::string>::iterator findMultiplyOperator(std::vector<std::string> &equation){ return findOperator(equation, "*"); } std::string calculate(std::string left, std::string right){ double l = atof(left.c_str()); double r = atof(right.c_str()); char value[100]; gcvt(l * r, 10, value); return std::string(value); } virtual void interprete(std::vector<std::string> &equation){ std::vector<std::string>::iterator operatorPointer = findMultiplyOperator(equation); while(operatorPointer != equation.end()){ int pos = (int)(operatorPointer - equation.begin()); std::string value = calculate(*(operatorPointer - 1), *(operatorPointer + 1)); equation.insert(operatorPointer - 1, value); equation.erase(equation.begin() + pos, equation.begin() + pos + 3); operatorPointer = findMultiplyOperator(equation); } } }; class Divide : public Interpreter{ protected: std::vector<std::string>::iterator findDivideOperator(std::vector<std::string> &equation){ return findOperator(equation, "/"); } std::string calculate(std::string left, std::string right){ double l = atof(left.c_str()); double r = atof(right.c_str()); char value[100]; gcvt(l / r, 10, value); return std::string(value); } virtual void interprete(std::vector<std::string> &equation){ std::vector<std::string>::iterator operatorPointer = findDivideOperator(equation); while(operatorPointer != equation.end()){ int pos = (int)(operatorPointer - equation.begin()); std::string value = calculate(*(operatorPointer - 1), *(operatorPointer + 1)); equation.insert(operatorPointer - 1, value); equation.erase(equation.begin() + pos, equation.begin() + pos + 3); operatorPointer = findDivideOperator(equation); } } }; class Add : public Interpreter{ protected: std::vector<std::string>::iterator findAddOperator(std::vector<std::string> &equation){ return findOperator(equation, "+"); } std::string calculate(std::string left, std::string right){ double l = atof(left.c_str()); double r = atof(right.c_str()); char value[100]; gcvt(l + r, 10, value); return std::string(value); } virtual void interprete(std::vector<std::string> &equation){ std::vector<std::string>::iterator operatorPointer = findAddOperator(equation); while(operatorPointer != equation.end()){ int pos = (int)(operatorPointer - equation.begin()); std::string value = calculate(*(operatorPointer - 1), *(operatorPointer + 1)); equation.insert(operatorPointer - 1, value); equation.erase(equation.begin() + pos, equation.begin() + pos + 3); operatorPointer = findAddOperator(equation); } } }; class Subtract : public Interpreter{ protected: std::vector<std::string>::iterator findSubtractOperator(std::vector<std::string> &equation){ return findOperator(equation, "-"); } std::string calculate(std::string left, std::string right){ double l = atof(left.c_str()); double r = atof(right.c_str()); char value[100]; gcvt(l - r, 10, value); return std::string(value); } virtual void interprete(std::vector<std::string> &equation){ std::vector<std::string>::iterator operatorPointer = findSubtractOperator(equation); while(operatorPointer != equation.end()){ int pos = (int)(operatorPointer - equation.begin()); std::string value = calculate(*(operatorPointer - 1), *(operatorPointer + 1)); equation.insert(operatorPointer - 1, value); equation.erase(equation.begin() + pos, equation.begin() + pos + 3); operatorPointer = findSubtractOperator(equation); } } }; int main(){ Interpreter interpreter("5+2.5*3+5/5-5"); std::cin.get(); return 0; } Interpreter::Interpreter(std::string equation){ std::cout << "Parse equation: " << equation << std::endl; parseString(equation); for(std::vector<std::string>::iterator i = this->equation.begin(); i < this->equation.end(); i++){ std::cout << *i << std::endl; } multiplyOperation = new Multiply; multiplyOperation->interprete(this->equation); std::cout << "After multiply:" << std::endl; for(std::vector<std::string>::iterator i = this->equation.begin(); i < this->equation.end(); i++){ std::cout << *i << std::endl; } divideOperation = new Divide; divideOperation->interprete(this->equation); std::cout << "After divided:" << std::endl; for(std::vector<std::string>::iterator i = this->equation.begin(); i < this->equation.end(); i++){ std::cout << *i << std::endl; } divideOperation = new Add; divideOperation->interprete(this->equation); std::cout << "After added:" << std::endl; for(std::vector<std::string>::iterator i = this->equation.begin(); i < this->equation.end(); i++){ std::cout << *i << std::endl; } subtractOperation = new Subtract; subtractOperation->interprete(this->equation); std::cout << "Calculated:" << std::endl; for(std::vector<std::string>::iterator i = this->equation.begin(); i < this->equation.end(); i++){ std::cout << *i << std::endl; } }

Wynik działania powyższego kodu:

Parse equation: 5+2.5*3+5/5-5
5
+
2.5
*
3
+
5
/
5
-
5
After multiply:
5
+
7.5
+
5
/
5
-
5
After divided:
5
+
7.5
+
1.
-
5
After added:
13.5
-
5
Calculated:
8.5
Strony powiązane
strony powiązane
  1. sourcemaking.com/design_patterns/interpreter - strona opisująca wzorzec projektowy interpreter [En]
  2. pl.wikipedia.org - opis tego wzorca na stronie Wikipedii
Propozycje książek