java 调用多个类的更好替代方案

mctunoxg  于 2023-05-21  发布在  Java
关注(0)|答案(2)|浏览(99)

更好的选择

switch (num) {
      case NAKED_SINGLE:
        return NakedSingle.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case NAKED_PAIR:
        return NakedPair.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case NAKED_TRIPLE:
        return NakedTriple.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case NAKED_QUAD:
        return NakedQuad.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case HIDDEN_SINGLE:
        return HiddenSingle.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case HIDDEN_PAIR:
        return HiddenPair.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case HIDDEN_TRIPLE:
        return HiddenTriple.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);
      case HIDDEN_QUAD:
        return HiddenQuad.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);

// more cases
}

这里num是一个int,所有这些类(根据数独提示名称)都有一个getHint方法(相同的签名),该方法返回一个String值。这段代码的问题是,当我添加更多的提示情况时,它会变得更大。有没有一个更好的替代方案,没有开关的情况下,使特定的类getHint方法得到调用根据num值与更少的代码行。

yyhrrdl8

yyhrrdl81#

这里通常的解决方案是利用 * 多态性 * 和编程到接口,而不是实现。你有许多类都实现了相同的接口。每个实现都做一些不同的事情,但是方法签名是相同的。这允许您交换实现,而不会影响调用方。

interface HintProvider {
  Hint getHint(
      Map<…, …> numberMap,
      Board penBoard,
      Board pencilBoard,
      Board solvedBoard,
      Collection<Hint> hints)
}

class NakedSingle implements HintProvider {
  @Override
  public Hint getHint(
      final Map<…, …> numberMap,
      final Board penBoard,
      final Board pencilBoard,
      final Board solvedBoard,
      final Collection<Hint> hints) {
    // impl …
  }
}

在你的代码中:

final HintProvider hintProvider = getHintProvider(num);
return hintProvider.getHint(numberMap, penBoard, pencilBoard, solvedBoard, hints);

getHintProvider可以用开关/ shell 或Map来实现,例如:

private static final Map<Integer, HintProvider> HINT_PROVIDERS = Map.ofEntries(
  Map.entry(NAKED_SINGLE, new NakedSingle()),
  Map.entry(…, …),
  …);

private HintProvider getHintProvider(final int num) {
  return Objects.requireNonNull(HINT_PROVIDERS.get(num));
  // or:
  // return HINT_PROVIDERS.getOrDefault(num, NO_HINT_PROVIDER);
}
dgjrabp2

dgjrabp22#

如果你以前上过关于继承和多态性的课,你的教授可能会给你这个练习。面向对象编程的这些概念用于解决这类问题。
你没有告诉我们任何关于NakedQuadHiddenSingle的事情,但是从你使用它们的方式来看,它们似乎是类。但是从您使用的大写字母来判断(如果我们假设您使用符合标准的大写字母),您对它们调用的getHint(...)方法是static方法。
也许在学习基础知识时这种做事方式是有意义的,但现在有了继承,你必须提高你的游戏水平。
你要做的第一件事就是把这些方法变成示例方法而不是静态方法。这是通过删除static关键字完成的。然后,为了调用这些方法,您将需要示例。所以,你不能再调用NakedSingle.getHint(...)了,你必须先调用NakedSingle nakedSingle = new NakedSingle();,然后再调用nakedSingle.getHint(...)
一旦你做到了这一点,一切都应该工作。
现在,要减少代码量,您有两个选择:
1.引入一个interface Thingie声明一个getHint( ... )方法,并让所有这些东西实现该接口(class NakedSingle implements Thingie),每个东西都提供自己的该方法的实现。
1.引入一个公共基class Thingie,声明一个getHint( ... )抽象方法,并使每个对象扩展该抽象类(class NakedSingle extends Thingie),每个对象提供该方法的自己的实现。
然后,您的代码变为如下所示:

Thingie thingie;
switch (num) 
{
    case NAKED_SINGLE:
        thingie = nakedSingle;
        break;
    case NAKED_PAIR:
        thingie = nakedPair;
        break;
    case NAKED_TRIPLE: 
        thingie = nakedTriple;
        break;
    ...
    default:
        throw new RuntimeException( "eh?" );
}
thingie.getHint( ... );

(Note我称之为“东西”因为你还没告诉我们它们是什么。希望你会使用一个有意义的名字。)

相关问题