Тест программирования Java для интервью

Вот тест программирования, используемый в собеседовании. Я нахожу, что у него очень странная перспектива, отличная от OO, и удивляйтесь, почему кто-то подходит к конструктору с этой точки зрения. Будучи очень опытным программистом на Java, я сразу же сомневаюсь в способности человека, написавшего этот код и странную перспективу вопроса.

Я нахожу эти странные из контекстных вопросов на собеседование тревожными. Мне бы хотелось получить отзывы от других опытных программистов Java OO.

Завершите конструктор Solver, чтобы вызов solveAll возвращал список с двумя значениями включая квадратный корень и обратный целому числу, переданному как параметр.

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;
    }
} 

Ответ 1

Это тестирование ваших шаблонов проектирования, используя простейший возможный метод. Я думаю, что это может быть Стратегия (или некоторые другие поведенческие модели). Смотрите следующее:

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

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

Если вы собираетесь провести собеседование по Java, вы должны иметь возможность идентифицировать шаблон дизайна, на который они намекают, и это должно помешать вам быть слишком нерешенным!

Чтобы ответить на вопрос, создайте два класса, которые реализуют MathFunction по мере необходимости, затем создайте два экземпляра и сохраните их в functionList.

Дело здесь не в том, что "вы можете делать вычисления этим странным образом", это "вы можете определить шаблоны дизайна".

Ответ 2

Я согласен, что это запутывает и перерабатывает.

Но я действительно думаю, что код достаточно объектно-ориентированный. Это пример стратегии. Код, который генерирует список ответов, не волнует, как вычисляются ответы - две проблемы разделены, и может быть применена другая стратегия расчета без необходимости касаться кода, который генерирует список.

Чтобы сделать класс более полезным, эти функции должны передаваться извне (например, инъекции зависимостей), а не создаваться в конструкторе.

Вы знаете ответ, я полагаю, но для чего это стоит...

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);
        }
    });
}

Ответ 3

ИМХО, это действительно странный подход. Имя Solver является общим, оно не должно выполнять определенные операции по умолчанию. Однако, может быть, это было частью интервью? Часть первая: просто выполните запрос. Часть вторая: скажите, что это странно.

Я бы сказал, что гораздо лучше использовать метод addMathFunction(MathFunction mf). И если хотите, создать подклассы, расширяющие класс Solver и добавление MathFunctions в их конструктор.

Ответ 4

Хотя я согласен с тем, что это, вероятно, не самый лучший способ или самый способ OO для этого, я должен был предположить, что суть этого упражнения - понять, насколько хорошо вы понимаете Inheritance, Interfaces и, возможно, анонимные внутренние классы, Это единственное, что я могу понять.

Ответ 5

Я думаю, они хотели, чтобы вы добавили два элемента в список функций. Каждый из них будет реализовывать интерфейс MathFunction, один для квадратного корня и один для обратного. Прбоблем находится в деталях:

1- У вас есть функция, которая возвращает 2 значения, потому что она выполняет две разные вещи: плохую

2- Если вы хотите иметь этот класс "все-все", m было бы интересно получить Mathfunctions в качестве параметра, чтобы вы могли делать любые типы MathFunctions, MathFunctions были бы параметризуемыми

Ответ 6

Вот мое решение. Это простая иллюстрация factory class.

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);
}

Этот вопрос показывает две вещи:

  • Независимо от того, понимает ли программист математические термины, такие как обратные.
  • Знает ли программист, что экземпляры интерфейсов или классов могут быть сохранены в списке и повторены позже.

Ответ 7

Хорошо, я закодировал решение своего вопроса. Мой инстинкт, что ничто не должно быть в конструкторе, кажется правильным. ФункцияList не является статической, поэтому для ее инициализации нужен экземпляр. Он задает целое число, поэтому я округлю до целого. Обратная функция не является продвинутой математикой.

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);

    }

Ответ 8

Немного надуманный, кажется мне ближе к дизайну декоратора. Не уверен, что бы я сказал во время интервью, но вот как я его кодирую:

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;
        }
    }
}

Ответ 9

Выполнение всего этого в конструкторе - это просто плохая практика. Во всяком случае, мое решение "все-в-одном".

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));

}

}