我必须用Java编写一个类,它支持用2个方法表示算术表达式 - eval和toString,使用以下黑盒:
Expression e =
new Multiplication(
new Addition(
new Double(2.5),
new Double(3.5)),
new UnaryMinus(
new Integer(5)));
System.out.println(e.eval()); // should print out -30.0
System.out.println(e.toString()); // should print out ((2.5 + 3.5) * (-(5)))
我该如何设计这样的课程?哪些工具?哪种设计模式?
答案 0 :(得分:2)
您只需要适当地实现每个运营商的toString
和eval
。然后,在应用自己的部分之前,根据需要在每个组件上调用toString
或eval
。
因此Addition.eval()
将执行return left.eval() + right.eval();
同样,Addition.toString()
将执行return "(" + left.toString() + " + " + right.toString() + ")";
为了实现这一目标,您将使用Rob建议的Composite模式的接口来构建覆盖这些方法的适当类。
答案 1 :(得分:2)
我如何设计这样的课程?
在你给出的黑匣子示例代码中有很多线索。
您需要一个名为interface
的{{1}}(或可能abstract class
},其Expression
方法。 eval
方法需要返回某种数字类型 - eval
是一个不错的选择,但还有其他选项。
您需要一些表达式类(实现或扩展表达式),例如Double
,Multiplication
和Addition
。这些需要提供UnaryMinus
方法的实现。他们还需要覆盖默认的eval
方法来打印表达式。
表达式类还需要具有隐含的参数类型的构造函数。
需要一点思考才能弄清楚如何处理这两个问题
toString()
和
new Multiplication(
new Addition(
new Double(2.5),
new Double(3.5)),
new UnaryMinus(
new Integer(5)));
......但是你可以解决这个问题。并通过自己解决来学习。 (或者可能不会打扰,因为严格来说,实施你向我们展示过的例子并不重要。)
哪些工具?
没有必要......除了Java JDK安装(显然)。使用您最喜欢/推荐的Java IDE,或简单的文本编辑器和JDK命令行工具。
哪种设计模式?
无要求。只是一点点"普通或花园品种"多态性。常规OO类和接口。
答案 2 :(得分:2)
希望这有帮助
setp 1:
public abstract class Expression
{
public abstract decimal Evaluate();
public abstract string toString();
}
第2步:
public abstract class ValueNode:Expression
{
public int intvalue;
public decimal decvalue;
public abstract decimal TEvaluate();
public abstract string TtoString();
public override decimal Evaluate()
{
return TEvaluate();
}
public override string toString()
{
return TtoString();
}
}
步骤2.1:
public abstract class OperationNode:Expression
{
public Expression left;
public Expression right;
public override decimal Evaluate()
{
return this.EEvaluate();
}
public override string toString()
{
return this.EtoString();
}
public abstract decimal EEvaluate();
public abstract string EtoString();
}
第3步:
public class UnaryMinus:OperationNode
{
public UnaryMinus(Expression Left)
{
this.left = Left;
}
public override decimal EEvaluate()
{
return -(this.left.Evaluate());
}
public override string EtoString()
{
return string.Format("(-({0}))",left.toString()); ;
}
}
第4步:
public class DecimalClass:ValueNode
{
public DecimalClass(decimal decimalValue)
{
this.decvalue = decimalValue;
}
public override decimal TEvaluate()
{
return this.decvalue;
}
public override string TtoString()
{
return this.decvalue.ToString();
}
}
第5步:
public class Integer : ValueNode
{
public Integer(int decimalValue)
{
this.intvalue = decimalValue;
}
public override decimal TEvaluate()
{
return this.intvalue;
}
public override string TtoString()
{
return this.intvalue.ToString();
}
}
第6步:
public class Addition:OperationNode
{
public Addition(Expression Left, Expression Right)
{
this.left = Left;
this.right = Right;
}
public override decimal EEvaluate()
{
return left.Evaluate()+ right.Evaluate();
}
public override string EtoString()
{
return string.Format("({0}+{1})",left.toString(),right.toString()); ;
}
}
第7步:
public class Multiplication : OperationNode
{
public Multiplication(Expression Left, Expression Right)
{
this.left = Left;
this.right = Right;
}
public override decimal EEvaluate()
{
return left.Evaluate()* right.Evaluate();
}
public override string EtoString()
{
return string.Format("({0}*{1})",left.toString(),right.toString()); ;
}
}
第8步:
public class Substraction:OperationNode
{
public Substraction(Expression Left, Expression Right)
{
this.left = Left;
this.right = Right;
}
public override decimal EEvaluate()
{
return left.Evaluate()- right.Evaluate();
}
public override string EtoString()
{
return string.Format("({0}-{1})",left.toString(),right.toString()); ;
}
}
第9步:
public class Division: OperationNode
{
public Division(Expression Left, Expression Right)
{
this.left = Left;
this.right = Right;
}
public override decimal EEvaluate()
{
return left.Evaluate()/ right.Evaluate();
}
public override string EtoString()
{
return string.Format("({0}/{1})",left.toString(),right.toString()); ;
}
}
第10步:
class Program
{
static void Main(string[] args)
{
callComposit();
Console.ReadKey();
}
private static void callComposit()
{
//Expression ((2.5+3.5)*(-(5)))
Multiplication multiplication = new Multiplication(new Addition(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication.toString(), multiplication.Evaluate()));
//Expression (5/6)
Division division = new Division(new Integer(5), new Integer(6));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", division.toString(), division.Evaluate()));
//Expression ((2.5-3.5)*(-(5)))
Multiplication multiplication2 = new Multiplication(new Substraction(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication2.toString(), multiplication2.Evaluate()));
//Expression ((2.5/3.5)*(-(5)))
Multiplication multiplication3 = new Multiplication(new Division(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication3.toString(), multiplication3.Evaluate()));
//Expression ((2.5/3.5)*(-(5))* 3.5)
Multiplication multiplication4 = new Multiplication(new Multiplication(new Division(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5))), new DecimalClass(3.5m));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication4.toString(), multiplication4.Evaluate()));
//Expression ( 3.5*(2.5/3.5)*(-(5)))
Multiplication multiplication5 = new Multiplication(new Multiplication(new DecimalClass(3.5m), new Division(new DecimalClass(2.5m), new DecimalClass(3.5m))), new UnaryMinus(new Integer(5)));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication5.toString(), multiplication5.Evaluate()));
//Expression ( 3.5*(2.5/3.5)+ 3.5 *(-(5)))
Multiplication multiplication6 = new Multiplication(new Addition(new Multiplication(new DecimalClass(3.5m), new Division(new DecimalClass(2.5m), new DecimalClass(3.5m))), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication6.toString(), multiplication6.Evaluate()));
}
}
请评论是否需要做任何事情来做得比这更好 快乐的编码
答案 3 :(得分:1)
您需要Expression
课程,然后是CompoundExpression
和TerminalExpression
。听起来像什么样的模式? Composite。然后,如果您愿意,可以使用访问者进行解析。
当你提供一种语言时,无论是算术还是其他一些解释的命令,都会有复合命令,例如:表达式4 +(5 * 2)将被解析为多个命令并添加到CompoundExpression中,当您调用eval时,它将遍历其表达式树来计算答案。 (设计模式对你有好处,顺便说一下,学习它们会让你成为一个更好的编码器。)
答案 4 :(得分:1)
如果允许修改黑盒子的使用,那么构建器模式可能是一个很好的方法。它看起来更像是:
Builder builder = new MathBuilder(); 表达式e = builder.add(new Double(2.5))。add(new Double(3.5).multiply(-5);
你必须围绕操作顺序计算细节,但总的来说,它似乎很好地利用了模式。快速搜索会出现很多例子。