0

我必须用 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))) 

我该如何设计这样的课程?哪些工具?哪种设计模式?

4

5 回答 5

2

您只需要适当地实施每个运营toStringeval。然后,在应用他们自己的部分之前,根据需要进行每个调用toString或对每个组件进行调用。eval

所以Addition.eval()会执行return left.eval() + right.eval();

同样,Addition.toString()将执行return "(" + left.toString() + " + " + right.toString() + ")";

为了实现这一点,您将使用 Rob 建议的复合模式接口来构建覆盖这些方法的适当类。

于 2013-01-25T01:02:57.150 回答
2

希望这可以帮助

设置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()));
    }
}

请评论是否需要做任何事情来比这种方式做得更好快乐编码

于 2014-02-28T15:21:20.520 回答
2

我该如何设计这样的课程?

好吧,在您获得的黑盒示例代码中有很多线索。

  • 你需要一个interface(或者可能是一个abstract class)被调用Expression的有一个eval方法的。该eval方法需要返回某种数字类型——Double这是一个不错的选择,但还有其他选择。

  • 您需要一些表达式类(实现或扩展表达式),例如Multiplication,AdditionUnaryMinus. 这些需要提供eval方法的实现。他们还需要覆盖默认toString()方法来打印表达式。

  • 表达式类还需要具有示例所暗示的参数类型的构造函数。

要弄清楚如何处理这两个问题,需要一些思考

new Multiplication( 
    new Addition( 
        new Double(2.5), 
        new Double(3.5)), 
    new UnaryMinus( 
        new Integer(5))); 

new Multiplication( 
    new Double(2.5), 
    new Double(3.5)); 

...但那是你的工作。并通过自己解决来学习。(或者也许不打扰,因为严格来说,实现您向我们展示的示例并不是必需的。)

哪些工具?

不需要...除了 Java JDK 安装(显然)。使用您最喜欢/推荐的 Java IDE,或简单的文本编辑器和 JDK 命令行工具。

哪种设计模式?

不需要。只是一点“普通或花园品种”多态性。常规的 OO 类和接口。

于 2013-01-25T01:40:59.617 回答
1

你需要一个Expression类,然后是 aCompoundExpression和 a TerminalExpression。这听起来像什么模式?复合。然后,您可以根据需要使用 Visitor 进行解析。

当您提供一种小语言时,无论是算术还是其他解释的命令集,都会有复合命令,例如表达式 4 + (5 * 2) 将被解析为多个命令并添加到 CompoundExpression,其中,当您调用 eval 时,它将遍历其表达式树以计算答案。(顺便说一句,设计模式对你有好处,学习它们会让你成为一个更好的程序员。)

于 2013-01-25T00:57:32.640 回答
1

如果允许您稍微修改一下黑盒的使用,那么构建器模式可能是一个不错的方法。它可能看起来更像:

Builder builder = new MathBuilder(); 表达式 e = builder.add(new Double(2.5)).add(new Double(3.5).multiply(-5);

您必须弄清楚操作顺序的细节,但总的来说,这似乎是对模式的很好利用。快速搜索会找到很多例子。

于 2013-01-25T01:11:09.753 回答