Is an if-else tree the best way to go in the following case?
What I'm doing:
I'm creating a simple calculator in Java, that reads a string that has been written using postfix notation (for example: 3 4 +). It then takes the string and starts reading it from left to right. It stores each number it finds and then applies the following operat开发者_如何学运维or. For example: 3 4 + --> store 3, store 4, run 3 + 4 and store result.
What I need help with:
In what way characters should be checked against pre-defined operators (if(c == '/') etc). What alternatives are there in my case to an if-else tree, and which one should I choose if I want to be able to add new operators with minimum effort (and minimum toll on performance). What is generally considered good practice?
If this is a calculator for humans to use, stop thinking about performance (as in execution speed). No human will ever come close to noticing the difference between an if-tree and any other implementation.
That said, you might want to try implementing some kind of Operator class, that knows how to apply itself to arguments, and then use a hash from the operator name (strings like "+", "-", "*" and so on) to an appropriate instance.
If you encapsulate your operations as objects, you can often use a data structure to replace a switch
-like statement and hopefully will simply adding operations in the future.
For example, this is one approach for encapsulating operations as objects: using an Enum to represent the operations:
http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html
public enum Operation {
PLUS { double eval(double x, double y) { return x + y; } },
MINUS { double eval(double x, double y) { return x - y; } },
TIMES { double eval(double x, double y) { return x * y; } },
DIVIDE { double eval(double x, double y) { return x / y; } };
// Do arithmetic op represented by this constant
abstract double eval(double x, double y);
}
You could extend this example to associate a symbol with each operation and provide a static method to look up the operation associated with symbol. [[ I'm torn about this mixing UI/view code with the logic/domain code, but you mentioned you want simple, so perhaps this is okay for your program.]]
If you encapsulate your operations as objects, then you can consider a data structure to replace switch-like code:
if there will be a lot of operations, consider building a hashmap to map symbols to operations.
if there are a small number of operations, it may be cheap enough to have a collection of all operations and simply iterate through all operations to ask each if they act on the user-provided symbol and use the first found.
I wouldn't worry about performance as the computer can parse/calculate the data 1 million times faster than you can type the formula (and that is not an exaguration)
The way I would approach it is to use if/else or use a switch statement
switch(ch) {
case '+':
break;
case '-':
break;
// etc.
}
What you are looking for is the Command Pattern implemented by a map with Character
objects as key and instances implementing a handling interface as values.
I would do it by creating an Operator superclass, which is extended by single operations, follows an example (forgive me for errors, I'm not trying this).
abstract class Operator {
String simbol;
abstract Double calculate(Double firstOperand, Double secondOperand)
}
class Sum extends Operator {
simbol = "+";
Double calculate(Double firstOperand, Double secondOperand){
return firstOperand + secondOperand;
}
}
class OperatorRecognizer {
List<Operator> operators;
public Operator recognize(String readOperator){
for(Operator operator : operators){
if(operator.getSymbol().equals(readOperator)){
return operator;
}
}
}
}
While reading a line I would do it this way:
OperatorFactory.recognize(readOperator).calculate(firstOperand, secondOperand);
This way when you have to add a single operation you just add one class.
EDIT: lol ok, it seems others have said this same thing, I'll leave this here anyway ^^"
Interesting question. Like many people here, micro optimization causes more evil than good. But without throwing any design patten at you or idea for optimization, this is what I would do.
I will create am Enum for all operations. I will also create a member function in this enum that takes a var args parameter and a operation enum and iteratively apply the enum operation on the arguements.
I will also create an String utility class (for input processing), that Iterates thro all the operation enum values and performs a regular expression check on input string to identify the operation specified by a given string ( regex because I want to make sure of Postfix notation). Once it identifies the operation, then it delegates to the enum's member function to perform the operation.
精彩评论