Java 如何在没有实现的情况下删除类之间的重复代码?

Java 如何在没有实现的情况下删除类之间的重复代码?,java,dry,code-reuse,Java,Dry,Code Reuse,我编写了许多函数的实现来计算给定位置的斐波那契数 斐波那契类:该类帮助我测试每个实现,而无需重写相同的测试代码。我不想在这里添加“fibonacci(n-2).add(fibonacci(n-1));”,因为有些实现不使用它(命令式迭代,函数式迭代) 递归斐波那契类 public class SimpleRecursiveFibonacci implements Fibonacci{ public BigInteger fibonacci(int n) { if(n < 2)

我编写了许多函数的实现来计算给定位置的斐波那契数

斐波那契类:该类帮助我测试每个实现,而无需重写相同的测试代码。我不想在这里添加“
fibonacci(n-2).add(fibonacci(n-1));
”,因为有些实现不使用它(命令式迭代,函数式迭代)

递归斐波那契类

public class SimpleRecursiveFibonacci implements Fibonacci{

  public BigInteger fibonacci(int n) {
    if(n < 2) {
      return BigInteger.ONE;             
    }

    return fibonacci(n - 2).add(fibonacci(n - 1));
  }
}
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);
  }
}

我怎样才能保持它干燥?删除重复的代码?

记忆的RecursiveFibonacci可以委托给
递归Fibonacci
实例:

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

那么抽象的普通父母呢? 大概是这样的:

public abstract class ParentFibonacci implements Fibonacci {
    protected BigInteger getFirstValues(int n) {
        if (n < 2) {
            return BigInteger.ONE;
        }
        return BigInteger.ZERO;
    }
}
公共抽象类ParentFibonacci实现了Fibonacci{
受保护的BigInteger GetFirstValue(int n){
if(n<2){
返回BigInteger.1;
}
返回biginger.ZERO;
}
}
这样,您的斐波那契实现需要实现Fibonacci.Fibonacci(intn),并且可以使用父方法

public class SimpleRecursiveFibonacci extends ParentFibonacci {

    public BigInteger fibonacci(int n) {
        if (n < 2) {
            return getFirstValues();
        }
        return fibonacci(n - 2).add(fibonacci(n - 1));
    }
}
公共类SimpleRecursiveFibonacci扩展了ParentFibonacci{
公共大整数斐波那契(整数n){
if(n<2){
返回getFirstValues();
}
返回fibonacci(n-2).add(fibonacci(n-1));
}
}

Make static factory method.+
Fibonacci
不是一个类,而是一个接口。你的答案是正确的,但它使记忆版本比递归版本慢。@minhquanggo为什么记忆版本会慢?正在使用缓存,因此不会再次计算已计算的值。@Mureinik SimpleRecursiveFibonacci不会利用缓存。如果
n
不在缓存中,即使
n-1
n-2
在缓存中,调用记忆化函数与调用简单函数是一样的。速度较慢的一个原因是在缓存未命中时搜索缓存的开销。此实现只有在缓存已预填充的情况下才能工作,例如使用
var memorized=new memorizedRecursiveFibonacci();备忘录(100)
(计算起来需要很长时间。从那时起,对n<100的
memoized.fibonacci(n)
调用都会很快。但这不是“memoized”的定义。正确的记忆化方法应使用以前计算的值;因此,不能通过将其委托给简单的递归版本来实现。此外,
Map.computeIfAbsent
也不能用于实现记忆化的斐波那契方法。
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);
  }
}
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));
}
public abstract class ParentFibonacci implements Fibonacci {
    protected BigInteger getFirstValues(int n) {
        if (n < 2) {
            return BigInteger.ONE;
        }
        return BigInteger.ZERO;
    }
}
public class SimpleRecursiveFibonacci extends ParentFibonacci {

    public BigInteger fibonacci(int n) {
        if (n < 2) {
            return getFirstValues();
        }
        return fibonacci(n - 2).add(fibonacci(n - 1));
    }
}