FizzBuzz是程序员中一个众所周知的练习,但我想添加一个叫做"openClosed“原则的方面(来自SOLID)。
FizzBuzz是一个非常简单的编程任务,用于软件开发人员的面试,以确定求职者是否能够实际编写代码。它是由Imran Ghory发明的,由杰夫·阿特伍德推广。下面是对这项任务的描述:
编写一个将数字从1打印到100的程序。但对于三种印刷品的倍数,“Fizz”而不是数字,以及五种打印“Buzz”的倍数。对于三倍和五倍的数字,请打印“FizzBuzz”。
用于运行示例的应用程序
public class App{
public static void main(String[] args) {
FizzBuzz fizzBuzz = new FizzBuzz();
fizzBuzz.addHandler(new FizzHandler());
fizzBuzz.addHandler(new BuzzHandler());
fizzBuzz.print(100);
}
}public interface Handler {
boolean matches(int number);
String getMessage();
}FizzHandler Handler实现
public class FizzHandler implements Handler {
@Override
public boolean matches(int number) {
return number % 3 == 0;
}
@Override
public String getMessage() {
return "Fizz";
}
}BuzzHandler Handler实现
public class BuzzHandler implements Handler {
@Override
public boolean matches(int number) {
return number % 5 == 0;
}
@Override
public String getMessage() {
return "Buzz";
}
}public class FizzBuzz {
private List<Handler> handlers = new ArrayList<>();
public void print(int countDestination) {
IntStream.range(0,countDestination).forEach(this::printFizzBuzz);
}
private void printFizzBuzz(int i) {
List<Handler> matchingHandler = handlers.stream().filter(h -> h.matches(i)).toList();
String output = matchingHandler.isEmpty()?
Integer.toString(i):
matchingHandler.stream().map(Handler::getMessage).collect(Collectors.joining());
System.out.println(output);
}
public void addHandler(Handler handler) {
handlers.add(handler);
}
}发布于 2022-08-11 09:54:31
处理程序将匹配和处理组合到同一个类中。一个模块中的两个责任违反了单一责任原则。在我看来,处理程序对于Predicate<Integer>和Supplier<String>来说是不必要的装饰。将它们结合在一起,在一个专门的接口后面,使重用和更改变得更加复杂。
FizzBuzz类结合了循环功能和处理程序匹配。这又是两项责任。它依赖于这样一个事实,即用户必须按照特定的顺序注册处理程序,这不能从API中的任何内容中推断出来。我更希望看到处理程序与优先级或其他方式相关联,在注册代码中明确了它们的执行顺序。我个人把处理程序注册和地图联系在一起。我不知道其他人是否同意这一点,但是将方法名更改为addLast(Handler)已经清楚地表明存在订单。API没有明确说明类也依赖于两个处理程序在它们匹配时都被执行。我没有现成的API更改来纠正这一点,所以至少应该在JavaDoc中记录它。
print(int countDestination)没有给出实际定义范围的参数的线索。应该将其重命名为printRange(int start, int end)。它还应该包括对start大于end的错误检查。我不确定打印一个范围是否应该是一个功能。FizzBuzz类可能只是一个Function<Integer, String>,因此它可以包含在其他地方的流操作中。毕竟,IntStream比通常强制用户进入“零到某物”范围要灵活得多。
处理程序总是输出到System.out,这将关闭要更改的主要方法。无法将输出写入例如网络套接字。FizzBuzz可能只需要生成数据并让其他组件来决定它的编写位置。
https://codereview.stackexchange.com/questions/278768
复制相似问题