Java 如何删除类之间的重复代码?

Java 如何删除类之间的重复代码?,java,dry,Java,Dry,我有两门课:递归斐波那契和记忆递归斐波那契。这就是我目前所拥有的 递归斐波那契类 public class SimpleRecursiveFibonacci { public BigInteger fibonacci(int n) { if(n < 2) { return BigInteger.ONE; } return fibonacci(n - 2).add(fibonacci(n - 1)); } } pub

我有两门课:递归斐波那契和记忆递归斐波那契。这就是我目前所拥有的

递归斐波那契类

public class SimpleRecursiveFibonacci {

  public 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(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);
  }
}
我怎样才能保持它干燥?删除重复的代码?

使用静态方法:

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);
  }
}
公共类SimpleRecursiveFibonacci{
公共静态双整数fibonacci(int n){
if(n<2){
返回BigInteger.1;
}
返回fibonacci(n-2).add(fibonacci(n-1));
}
}
公共类MemorizedRecursiveFibonacci{
私有映射缓存=新的HashMap();
公共大整数斐波那契(整数n){
如果(!cache.containsKey(n)){
BigInteger currentFibonacci=SimpleRecursiveFibonacci.fibonacci(n);
cache.put(n,currentFibonacci);
}
返回cache.get(n);
}
}

也许这是一个选项。。。但不是我认为最好的

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)),
}
公共类SimpleRecursiveFibonacci{
公共大整数斐波那契(整数n){
if(n<2){
返回BigInteger.1;
}
返回计算(n);
}
受保护的BigInteger计算(int n){
返回fibonacci(n-2).add(fibonacci(n-1)),
}
}

公共类memorizedRecursiveFibonacci扩展了SimpleRecursiveFibonacci{
私有映射缓存=新的HashMap();
@凌驾
受保护的BigInteger计算(int n){
如果(!cache.containsKey(n)){
BigInteger currentFibonacci=super.calculate(n);
cache.put(n,currentFibonacci);
}
返回cache.get(n)
}

}像这样的东西怎么样:

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);
        }
    }
}
公共类SimpleRecursiveFibonacci{
/**获取n的斐波那契值*/
公共最终大整数斐波那契(整数n){
如果(n==0){
返回biginger.ZERO;
}else如果(n==1){
返回BigInteger.1;
}
返回fibonacci(n);
}
/**通过将前面的两个fibonacci相加,递归计算fibonacci*/
受保护的最终大整数calculateFibbonacci(int n){
返回fibonacci(n-2).add(fibonacci(n-1));
}
/** 
*以某种方式得到n的斐波那契值。
*可以通过计算,从缓存中获取,或者其他任何方式。
*默认为“计算”。
*/
受保护的BigInteger getFibonacci(int n){
返回值计算为bbonacci(n);
}
}
公共类memorizedRecursiveFibonacci扩展了SimpleRecursiveFibonacci{
//使用用户@DodgyCodeException建议的数组列表进行缓存
私有ArrayList缓存=新建ArrayList();
@凌驾
受保护的BigInteger getFibonacci(int n){
if(cache.size()
另一个使用Java 8功能的示例-与lambda表达式的接口:

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);
BiFunction func=(斐波那契,n)->{
if(n<2){
返回BigInteger.1;
}
返回fibonacci.calc(n-2).add(fibonacci.calc(n-1));
};
新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);
    }
}
接口斐波那契{
大整数计算(整数n);
}
类SimpleFibonacci实现Fibonacci{
私有双函数斐波那契;
SimpleFibonacci(双函数fibonacci){
fibonacci=fibonacci;
}
公共大整数计算(整数n){
返回fibonacci.apply(这个,n);
}
}
类cachedfibancci实现斐波那契{
私有双函数斐波那契;
私有映射缓存=新的HashMap();
cachedfbonacci(双函数fibonacci){
fibonacci=fibonacci;
}
公共大整数计算(整数n){
如果(!cache.containsKey(n)){
put(n,fibonacci.apply(this,n));
}
返回cache.get(n);
}
}

这将只记忆最终值,而不是中间值。使用MemoizedRecursiveFibonacci并实现类似public BigInteger fibonacci(int n,bool useCache)的方法,让调用方使用或不使用缓存怎么样?或者使用属性@Cacheable来修饰方法以获得缓存?一个不相关的观察结果:记忆版本总是用连续的整数键填充HashMap。因此,使用ArrayList并使用索引而不是键会更有效。事实上这并不坏。经典模板法:)我唯一的改进是提前返回
currentFibonacci
,而不是再次查找。类似于我的想法。我使用第三种方法来“获取”斐波那契值,可以从缓存中获取,也可以通过重新计算来获取。这是可行的,它完成了它应该做的事情,但我发现有点难以遵循。它似乎以减少可读性来换取消除重复。
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);
        }
    }
}
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);
    }
}