首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >又一个嗡嗡的嗡嗡声

又一个嗡嗡的嗡嗡声
EN

Code Review用户
提问于 2022-08-11 08:10:52
回答 1查看 130关注 0票数 4

FizzBuzz是程序员中一个众所周知的练习,但我想添加一个叫做"openClosed“原则的方面(来自SOLID)。

FizzBuzz是一个非常简单的编程任务,用于软件开发人员的面试,以确定求职者是否能够实际编写代码。它是由Imran Ghory发明的,由杰夫·阿特伍德推广。下面是对这项任务的描述:

编写一个将数字从1打印到100的程序。但对于三种印刷品的倍数,“Fizz”而不是数字,以及五种打印“Buzz”的倍数。对于三倍和五倍的数字,请打印“FizzBuzz”。

用于运行示例的应用程序

代码语言:javascript
复制
public class App{

    public static void main(String[] args) {
        FizzBuzz fizzBuzz = new FizzBuzz();
        fizzBuzz.addHandler(new FizzHandler());
        fizzBuzz.addHandler(new BuzzHandler());
        fizzBuzz.print(100);
    }
}

Handler

代码语言:javascript
复制
public interface Handler {

    boolean matches(int number);

    String getMessage();
}

FizzHandler Handler实现

代码语言:javascript
复制
public class FizzHandler implements Handler {

    @Override
    public boolean matches(int number) {
        return number % 3 == 0;
    }

    @Override
    public String getMessage() {
        return "Fizz";
    }
}

BuzzHandler Handler实现

代码语言:javascript
复制
public class BuzzHandler implements Handler {
    @Override
    public boolean matches(int number) {
        return number % 5 == 0;
    }

    @Override
    public String getMessage() {
        return "Buzz";
    }
}

FizzBuzz

代码语言:javascript
复制
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);
    }
}
EN

回答 1

Code Review用户

回答已采纳

发布于 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可能只需要生成数据并让其他组件来决定它的编写位置。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/278768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档