47

这是工作面试中使用的编程测试。我发现它有一个非常奇怪的非 OO 视角,并且想知道为什么有人会从这个视角接近构造函数。作为一个非常有经验的 Java 程序员,我立即质疑编写此代码的个人的能力以及问题的奇怪视角。

我发现这些奇怪的断章取义的面试问题令人不安。我希望得到其他有经验的 OO Java 程序员的反馈。

完成 Solver 构造函数,以便调用 solveAll 返回一个包含 2 个值的列表,包括平方根和作为参数传递的整数的倒数。

public interface MathFunction {
    double calculate(double x);
}

public class Solver {

    private List<MathFunction> functionList;

    public Solver() { 

        //Complete here

    }

    public List<Double> solveAll(double x) {
        List<Double> result = new ArrayList<Double>();
        for (MathFunction function : this.functionList) {
            result.add(new Double(function.calculate(x)));
        }

        return result;
    }
} 
4

9 回答 9

38

这是通过使用最简单的方法来测试您的设计模式。我认为这可能是策略(或其他一些行为模式)。见这些:

http://en.wikipedia.org/wiki/Strategy_pattern

http://en.wikipedia.org/wiki/Behavioral_pattern

如果您要参加 Java 面试,您应该能够识别他们暗示的设计模式,这应该可以防止您过于不安!

要回答这个问题,创建两个MathFunction根据需要实现的类,然后创建两个实例并将它们存储在functionList.

这里的重点不是“你能以这种奇怪的方式进行计算”,而是“你能识别设计模式”。

于 2012-08-21T14:51:13.747 回答
31

我同意它令人困惑和过度设计。

但我确实认为代码是合理的面向对象的。这是策略模式的一个实例。生成答案列表的代码并不关心答案是如何计算的——这两个问题是分开的,并且可以应用不同的计算策略,而无需接触生成列表的代码。

为了使类更有用,这些函数应该从外部传入(即依赖注入),而不是在构造函数中实例化。

你知道答案,我想,但它的价值...

public Solver() {
    functionList = new ArrayList<MathFunction>();

    functionList.add(new MathFunction() {

        @Override
        public double calculate(double x) {
            return 1d/x;
        }
    });

    functionList.add(new MathFunction() {

        @Override
        public double calculate(double x) {
            return Math.sqrt(x);
        }
    });
}
于 2012-08-21T15:06:53.113 回答
6

恕我直言,这确实是一种奇怪的方法。该名称Solver是通用的,默认情况下不应实现特定操作。然而,也许那是采访的一部分?第一部分:简单地完成请求。第二部分:说这样做很奇怪。

我会说一个更好的方法是有一个addMathFunction(MathFunction mf)方法。如果需要,可以创建扩展类的子Solver类并在其构造函数中添加 MathFunctions。

于 2012-08-21T14:53:18.233 回答
3

好的,我为自己的问题编写了解决方案。我认为构造函数中不应包含任何内容的直觉似乎是正确的。functionList 不是静态的,因此您需要一个实例来初始化它。它指定整数,所以我四舍五入为整数。反函数无论如何都不是高级数学。

import java.util.ArrayList;
import java.util.List;
import java.lang.Math;

public class Solver {

    private List<MathFunction> functionList = new ArrayList<MathFunction>();;

    public Solver() { 

// Complete here

    }

    public void initFunctionList() {

        MathFunction functionSquareRoot = new MathFunction(){

            @Override
            public double calculate(double x) {
                return (x<0 ? 0: Math.sqrt(x));  // maybe we need throw an exception here for negative numbers, but we'll just set it to 0
            }};

        MathFunction functionInverse = new MathFunction(){

            @Override
            public double calculate(double x) {
                return (x!=0.0 ? 1/x : 0);
            }

        };

        functionList.add(functionSquareRoot);
        functionList.add(functionInverse);

    }

    public List<Double> solveAll(double x) {
        List<Double> result = new ArrayList<Double>();

        for (MathFunction function : this.functionList) {
            result.add(new Double(function.calculate(x)));
        }

        return result;
    }

}


public interface MathFunction {
     double calculate(double x);
}


public class TestSolver {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Solver s = new Solver();
        s.initFunctionList();
        System.out.println(s.solveAll(16.0));

    }

}

我误导自己构造函数可以是

public Solver() { 

// Complete here
        MathFunction functionSquareRoot = new MathFunction(){

            @Override
            public double calculate(double x) {
                return (x<0 ? 0: Math.sqrt(x));  // maybe we need throw an exception here for negative numbers, but we'll just set it to 0
            }};

        MathFunction functionInverse = new MathFunction(){

            @Override
            public double calculate(double x) {
                return (x!=0.0 ? 1/x : 0);
            }

        };

        functionList.add(functionSquareRoot);
        functionList.add(functionInverse);

    }
于 2012-08-21T15:49:12.253 回答
3

这是我的解决方案。这是一个工厂类的简单说明。

public Solver() { 
    functionList = new ArrayList<MathFunction>();
    MathFunction sqrt = new MathFunction() {
        @Override
        public double calculate(double x) {
            return Math.sqrt(x);
        }

    };
    functionList.add(sqrt);
    MathFunction inverse = new MathFunction() {
        @Override
        public double calculate(double x) {
            return 1.0D / x;
        }

    };
    functionList.add(inverse);
}

这个问题说明了两件事:

  • 程序员是否理解数学术语,如逆。
  • 程序员是否了解接口或类的实例可以存储在列表中,并在以后进行迭代。
于 2012-08-21T14:56:42.857 回答
3

虽然我同意这可能不是最好的方式,或者大多数 OO 方式来做到这一点,但我不得不假设这个练习的重点是看看你对继承、接口和匿名内部类的理解程度。这是我唯一能想到的。

于 2012-08-21T14:52:15.047 回答
3

我认为他们希望您在功能列表中添加两项。每个都将实现 MathFunction 接口,一个用于平方根,一个用于逆。问题在于细节:

1-你有一个返回 2 个值的函数,因为它做了两件不同的事情,这很糟糕

2-如果您想拥有这个“全能”类,那么将 Mathfunctions 作为参数接收会很有趣,这样您就可以执行任何类型的 MathFunctions,MathFunctions 将是可参数化的

于 2012-08-21T14:53:36.760 回答
2

有点做作,对我来说似乎更接近装饰者模式。不确定我在面试时会说什么,但我会这样编码:

package math;

import java.util.ArrayList;
import java.util.List;

public class DecoratorMath 
{

    interface MathFunction 
    {
        double calculate(double x);
    }

    public static void main(String[] args) 
    {
        DecoratorMath decoratorMath =  new DecoratorMath();
        decoratorMath.go();
    }

    public void go() 
    {
        Solver solver = new Solver();
        decorate(solver);
        List<Double> results = solver.solveAll(02);
        for (Double d :results) 
        {
            System.out.println(d);
        }
    }

    public void decorate(Solver solver)
    {
        solver.addFunction(new MathFunction() 
        {
            @Override
            public double calculate(double x) 
            {
                return Math.sqrt(x);
            }
        });

        solver.addFunction(new MathFunction() 
        {
            @Override
            public double calculate(double x) 
            {
                return 1d/x;
            }
        });
    }

    class Solver
    {
        private List<MathFunction> mathFunctions = new ArrayList<MathFunction>();

        public void addFunction(MathFunction mathFunction)
        {
            mathFunctions.add(mathFunction);
        }

        public List<Double> solveAll(double x) 
        {
            List<Double> result = new ArrayList<Double>();
            for (MathFunction function : mathFunctions) 
            {
                result.add(new Double(function.calculate(x)));
            }
            return result;
        }
    }
}
于 2013-01-06T01:50:29.047 回答
0

在构造函数中做这一切只是不好的做法。无论如何,我的多合一解决方案。

import java.util.*;
import java.math.*;

//sqrt / inverse

public class Solver{

  private List<MathFunction> functionList;

  public interface MathFunction{
     double calculate(double x);
  }

  class X implements MathFunction {
    public double calculate(double x) {
      return Math.sqrt(x); 
  } 
  }

    class Y implements MathFunction {
    public double calculate(double y) {
      return 1/y; 
  } 
  }



  public Solver(){
  //here
    functionList = new ArrayList<MathFunction>();

    MathFunction f =  (MathFunction) new X();
    functionList.add(f);  

    MathFunction f2 =  (MathFunction) new Y();
    functionList.add(f2);

  }


  public List<Double> solveAll(double x){ 

  List<Double> result=new ArrayList<Double>();

    for (MathFunction function : this.functionList){

      result.add(new Double(function.calculate(x)));

    }

    return result;

  }

public static void main(String... args) {

    System.out.println("result="+new Solver().solveAll(123));

}

}
于 2015-01-09T23:48:24.320 回答