Как я могу удалить дублированный код между классами?
У меня есть 2 класса: RecursiveFibonacci и MemorizedRecursiveFibonacci. Это то, что я до сих пор.
Рекурсивный класс Фибоначчи
public class SimpleRecursiveFibonacci {
public BigInteger fibonacci(int n) {
if(n < 2) {
return BigInteger.ONE;
}
return fibonacci(n - 2).add(fibonacci(n - 1));
}
}
и MemorizedRecursiveFibonacci Class
public class MemoizedRecursiveFibonacci {
private Map<Integer, BigInteger> cache = new HashMap<>();
public BigInteger fibonacci(int n) {
if(n < 2) {
return BigInteger.ONE;
}
if(!cache.containsKey(n)){
BigInteger currentFibonacci = fibonacci(n - 2).add(fibonacci(n - 1));
cache.put(n, currentFibonacci);
}
return cache.get(n);
}
}
Как я вижу, в MemorizedRecursiveFibonacci есть некоторый дублированный код
if(n < 2) {
return BigInteger.ONE;
а также
BigInteger currentFibonacci = fibonacci(n - 2).add(fibonacci(n - 1));
Как я могу держать это сухим? удалить дублированный код?
Ответы
Ответ 1
Как насчет чего-то вроде этого:
public class SimpleRecursiveFibonacci {
/** Gets the fibonacci value for n */
public final BigInteger fibonacci(int n) {
if (n == 0) {
return BigInteger.ZERO;
} else if (n == 1) {
return BigInteger.ONE;
}
return getFibonacci(n);
}
/** Recursively calculates the fibonacci by adding the two previous fibonacci. */
protected final BigInteger calculateFibbonacci(int n) {
return fibonacci(n - 2).add(fibonacci(n - 1));
}
/**
* Somehow get the fibonacci value for n.
* Could be by calculation, getting it from a cache, or anything.
* Defaults to calculation.
*/
protected BigInteger getFibonacci(int n) {
return calculateFibbonacci(n);
}
}
public class MemoizedRecursiveFibonacci extends SimpleRecursiveFibonacci {
// Cache using an array list as recommended by user @DodgyCodeException
private ArrayList<BigInteger> cache = new ArrayList<>();
@Override
protected BigInteger getFibonacci(int n) {
if (cache.size() < n) {
BigInteger fib = calculateFibbonacci(n);
cache.add(fib);
return fib;
} else {
return cache.get(n - 1);
}
}
}
Ответ 2
Может быть, это вариант... но не самый лучший, я думаю.
public class SimpleRecursiveFibonacci {
public BigInteger fibonacci(int n) {
if(n < 2) {
return BigInteger.ONE;
}
return calculate(n);
}
protected BigInteger calculate(int n){
return fibonacci(n - 2).add(fibonacci(n - 1)),
}
}
public class MemoizedRecursiveFibonacci extends SimpleRecursiveFibonacci{
private Map<Integer, BigInteger> cache = new HashMap<>();
@Override
protected BigInteger calculate(int n) {
if(!cache.containsKey(n)){
BigInteger currentFibonacci = super.calculate(n);
cache.put(n, currentFibonacci);
}
return cache.get(n)
}
}
Ответ 3
Другой пример использования функций Java 8 - интерфейс BiFunction
с лямбда-выражением:
BiFunction<Fibonacci, Integer, BigInteger> func = (fibonacci, n) -> {
if (n < 2) {
return BigInteger.ONE;
}
return fibonacci.calc(n - 2).add(fibonacci.calc(n - 1));
};
new CachedFibonacci(func).calc(100);
Реализация:
interface Fibonacci {
BigInteger calc(int n);
}
class SimpleFibonacci implements Fibonacci {
private BiFunction<Fibonacci, Integer, BigInteger> fibonacci;
SimpleFibonacci(BiFunction<Fibonacci, Integer, BigInteger> fibonacci) {
this.fibonacci = fibonacci;
}
public BigInteger calc(int n) {
return fibonacci.apply(this, n);
}
}
class CachedFibonacci implements Fibonacci {
private BiFunction<Fibonacci, Integer, BigInteger> fibonacci;
private Map<Integer, BigInteger> cache = new HashMap<>();
CachedFibonacci(BiFunction<Fibonacci, Integer, BigInteger> fibonacci) {
this.fibonacci = fibonacci;
}
public BigInteger calc(int n) {
if (!cache.containsKey(n)) {
cache.put(n, fibonacci.apply(this, n));
}
return cache.get(n);
}
}
Ответ 4
использовать статический метод:
public class SimpleRecursiveFibonacci {
public static BigInteger fibonacci(int n) {
if(n < 2) {
return BigInteger.ONE;
}
return fibonacci(n - 2).add(fibonacci(n - 1));
}
}
public class MemoizedRecursiveFibonacci {
private Map<Integer, BigInteger> cache = new HashMap<>();
public BigInteger fibonacci(int n) {
if(!cache.containsKey(n)){
BigInteger currentFibonacci = SimpleRecursiveFibonacci.fibonacci(n);
cache.put(n, currentFibonacci);
}
return cache.get(n);
}
}