I wrote many implementations of a function to compute the Fibonacci number at a given position.
Fibonacci Class : this class helps me to test each implementation without rewrite same test code. I don't want to add " fibonacci(n - 2).add(fibonacci(n - 1));
" here because some implementations do not use it (imperative iteration, functional iteration).
public interface Fibonacci {
BigInteger fibonacci(int n);
}
RecursiveFibonacci Class
public class SimpleRecursiveFibonacci implements Fibonacci{
public BigInteger fibonacci(int n) {
if(n < 2) {
return BigInteger.ONE;
}
return fibonacci(n - 2).add(fibonacci(n - 1));
}
}
and MemorizedRecursiveFibonacci Class
public class MemoizedRecursiveFibonacci implements Fibonacci{
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);
}
}
As I see, there are some duplicated code in MemorizedRecursiveFibonacci Class
if(n < 2) {
return BigInteger.ONE;
and
BigInteger currentFibonacci = fibonacci(n - 2).add(fibonacci(n - 1));
How can I keep it DRY? remove duplicated code?
The MemorizedRecursiveFibonacci
can delegate to a RecursiveFibonacci
instance:
public class MemoizedRecursiveFibonacci implements Fibonacci {
SimpleRecursiveFibonacci simple = new SimpleRecursiveFibonacci();
private Map<Integer, BigInteger> cache = new HashMap<>();
public BigInteger fibonacci(int n) {
if(!cache.containsKey(n)) {
BigInteger currentFibonacci = simple.fibonacci(n);
cache.put(n, currentFibonacci);
}
return cache.get(n);
}
}
Or, even more elegantly, using Java 8's Map#computeIfAbsent
:
public class MemoizedRecursiveFibonacci implements Fibonacci {
SimpleRecursiveFibonacci simple = new SimpleRecursiveFibonacci();
private Map<Integer, BigInteger> cache = new HashMap<>();
public BigInteger fibonacci(int n) {
return cache.computeIfAbsent(n, k -> simple.fibonacci(k));
}
What about an abstract common parent? Something like this:
public abstract class ParentFibonacci implements Fibonacci {
protected BigInteger getFirstValues(int n) {
if (n < 2) {
return BigInteger.ONE;
}
return BigInteger.ZERO;
}
}
This way your Fibonacci implementation need to implement Fibonacci.fibonacci(int n) and can use parent methods.
public class SimpleRecursiveFibonacci extends ParentFibonacci {
public BigInteger fibonacci(int n) {
if (n < 2) {
return getFirstValues();
}
return fibonacci(n - 2).add(fibonacci(n - 1));
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.