You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过方法链式调用重构FizzBuzz代码?

Implementing a Fluent Interface for Clean FizzBuzz Code

我正在尝试重构我的代码,但不知道如何实现预期效果,也不清楚这种写法的名称,因此无法通过Google检索到相关资料。

我的原始代码如下:

public void print(int from, int to) { 
    // TODO Auto-generated method stub 
    for(;from<=to;from++) { 
        if(from % 3 == 0) { 
            if(from % 5 == 0) { 
                System.out.println("Fizz Buzz"); 
            } else { 
                System.out.println("Fizz"); 
            } 
        } else { 
            if(from % 5 == 0) { 
                System.out.println("Buzz"); 
            } else { 
                System.out.println(from); 
            } 
        } 
    } 
}

我希望将代码重构为如下形式:

print("Fizz").If(from).IsMultipleOf(3); 
print("Buzz").If(from).IsMultipleOf(5); 
print("Fizz Buzz").If(from).IsMultipleOf(3).And.IsMultipleOf(5);

或者:

if(If(from).IsMultipleOf(3) && If(from).IsMultipleOf(5)) { 
    print("Fizz Buzz"); 
}

其中If(from).IsMultipleOf(3)需要返回布尔值,当返回true时执行print()方法。但我不知道如何实现这种用点(".")连接方法的写法,能否有人告诉我对应的检索术语,或者提供一个实现示例?提前感谢!


Hey there! The pattern you're aiming for is called a Fluent Interface — it's a design style that chains method calls together to create readable, natural-language-like code. Let's break down how to build this for your FizzBuzz scenario step by step.

Step 1: Build a Fluent Condition Class

First, we'll create a class to handle number checks and support method chaining. This will power the If(from).IsMultipleOf(x) logic:

public class FluentCondition {
    private final int number;
    private boolean conditionResult;

    // Private constructor to force use of the static "If" entry point
    private FluentCondition(int number) {
        this.number = number;
        this.conditionResult = true; // Start with a true base for chaining
    }

    // Static entry method to kick off the fluent chain
    public static FluentCondition If(int number) {
        return new FluentCondition(number);
    }

    // Check if the number is a multiple of the given divisor, then return the instance to keep chaining
    public FluentCondition IsMultipleOf(int divisor) {
        conditionResult = conditionResult && (number % divisor == 0);
        return this;
    }

    // Add an "And" property for readability (just returns the current instance)
    public FluentCondition getAnd() {
        return this;
    }

    // Convert the chained condition to a boolean for standard if statements
    public boolean toBoolean() {
        return conditionResult;
    }
}

Step 2: Create a Fluent Printer Class

Next, we'll build the print() side of things, which ties the condition check to printing your message:

public class FluentPrinter {
    private final String message;

    private FluentPrinter(String message) {
        this.message = message;
    }

    // Static entry method to start the print chain
    public static FluentPrinter print(String message) {
        return new FluentPrinter(message);
    }

    // Link to the FluentCondition class to add conditional logic
    public ConditionChecker If(int number) {
        return new ConditionChecker(message, number);
    }

    // Inner class to handle the condition-to-print flow
    public static class ConditionChecker {
        private final String message;
        private final FluentCondition condition;

        public ConditionChecker(String message, int number) {
            this.message = message;
            this.condition = FluentCondition.If(number);
        }

        public ConditionChecker IsMultipleOf(int divisor) {
            condition.IsMultipleOf(divisor);
            return this;
        }

        public ConditionChecker getAnd() {
            condition.getAnd();
            return this;
        }

        // Terminal method to trigger printing if the condition is true
        public void execute() {
            if (condition.toBoolean()) {
                System.out.println(message);
            }
        }
    }
}

Step 3: Use the Fluent Interface in Your FizzBuzz Logic

Now you can rewrite your code using the clean chained syntax. Here's how both of your desired approaches work:

Option 1: Direct Chained Print Calls

public void printFizzBuzz(int from, int to) {
    for (; from <= to; from++) {
        // Print "Fizz Buzz" if divisible by both 3 and 5
        FluentPrinter.print("Fizz Buzz").If(from).IsMultipleOf(3).getAnd().IsMultipleOf(5).execute();
        
        // Print "Fizz" only if not already part of "Fizz Buzz"
        if (!FluentCondition.If(from).IsMultipleOf(3).getAnd().IsMultipleOf(5).toBoolean()) {
            FluentPrinter.print("Fizz").If(from).IsMultipleOf(3).execute();
        }
        
        // Print "Buzz" only if not already part of "Fizz Buzz"
        if (!FluentCondition.If(from).IsMultipleOf(3).getAnd().IsMultipleOf(5).toBoolean()) {
            FluentPrinter.print("Buzz").If(from).IsMultipleOf(5).execute();
        }
        
        // Print the number if it's not Fizz/Buzz
        if (!FluentCondition.If(from).IsMultipleOf(3).toBoolean() && !FluentCondition.If(from).IsMultipleOf(5).toBoolean()) {
            System.out.println(from);
        }
    }
}

Option 2: Fluent Conditions in Standard If Statements

public void printFizzBuzz(int from, int to) {
    for (; from <= to; from++) {
        boolean isFizz = FluentCondition.If(from).IsMultipleOf(3).toBoolean();
        boolean isBuzz = FluentCondition.If(from).IsMultipleOf(5).toBoolean();

        if (isFizz && isBuzz) {
            System.out.println("Fizz Buzz");
        } else if (isFizz) {
            System.out.println("Fizz");
        } else if (isBuzz) {
            System.out.println("Buzz");
        } else {
            System.out.println(from);
        }
    }
}

Quick Notes

  • The core of a fluent interface is that each method returns an instance of the class (or a related class) to keep the chain going.
  • The getAnd() method lets you write .And in Java (since Java uses camelCase for getters) to make the chain read more like natural language.
  • We added an execute() terminal method because Java can't automatically trigger the print after the condition check — this is a necessary step to run the action when the condition passes.

内容的提问来源于stack exchange,提问作者Luké

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:37:50