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

Java:在main方法外部调用println的实践疑问与最佳方案

嘿,这个问题问得特别到位——你的教授说得没错,直接在业务方法里写死System.out.println()确实是个不良实践,会让你的代码耦合度太高,以后想改输出方式(比如存到日志文件、甚至推送到通知系统)就会非常麻烦。下面给你几个实用的实现方案,从简单到灵活,你可以根据课程需求选:

方案1:依赖注入(最推荐,符合开闭原则)

核心思路是把输出逻辑从业务方法中剥离,通过接口定义输出行为,再把具体的输出实现传给飞机类。这样飞机类只负责处理起飞/降落的业务逻辑,不用关心消息怎么输出。

首先定义一个输出处理的接口:

public interface OutputHandler {
    void printMessage(String message);
}

然后实现控制台输出的版本:

public class ConsoleOutputHandler implements OutputHandler {
    @Override
    public void printMessage(String message) {
        System.out.println(message);
    }
}

接下来改造你的飞机类,通过构造器注入输出处理实例:

public class Plane {
    private final OutputHandler outputHandler;

    // 构造器注入,让飞机类依赖抽象而非具体实现
    public Plane(OutputHandler outputHandler) {
        this.outputHandler = outputHandler;
    }

    public void fly() {
        // 这里写起飞的业务逻辑
        outputHandler.printMessage("✈️ 飞机正在起飞,即将进入巡航状态!");
    }

    public void land() {
        // 这里写降落的业务逻辑
        outputHandler.printMessage("🛬 飞机正在降落,即将抵达跑道!");
    }
}

最后在主程序中使用:

public class AirportSimulator {
    public static void main(String[] args) {
        OutputHandler consoleOutput = new ConsoleOutputHandler();
        Plane myPlane = new Plane(consoleOutput);
        
        myPlane.fly();
        myPlane.land();
    }
}

这个方案的好处是:以后如果要把输出改成写入日志文件,只需要新增一个FileOutputHandler实现OutputHandler接口,完全不用修改Plane类的代码——完美符合开闭原则,还能让你的代码更易测试(比如写个Mock输出类来验证方法是否被调用)。

方案2:观察者模式(适合多场景监听状态)

如果你的模拟器需要多个地方监听飞机的状态(比如同时输出到控制台、记录到机场日志面板),观察者模式会很合适。飞机作为被观察者,起飞/降落时通知所有注册的观察者,由观察者负责输出消息。

先定义观察者接口:

public interface PlaneObserver {
    void onPlaneFly();
    void onPlaneLand();
}

实现控制台观察者:

public class ConsolePlaneObserver implements PlaneObserver {
    @Override
    public void onPlaneFly() {
        System.out.println("[控制台] 飞机已起飞!");
    }

    @Override
    public void onPlaneLand() {
        System.out.println("[控制台] 飞机已安全降落!");
    }
}

改造飞机类,维护观察者列表并触发通知:

import java.util.ArrayList;
import java.util.List;

public class Plane {
    private final List<PlaneObserver> observers = new ArrayList<>();

    // 添加观察者
    public void addObserver(PlaneObserver observer) {
        observers.add(observer);
    }

    public void fly() {
        // 起飞业务逻辑
        notifyObserversOfFly();
    }

    public void land() {
        // 降落业务逻辑
        notifyObserversOfLand();
    }

    private void notifyObserversOfFly() {
        for (PlaneObserver observer : observers) {
            observer.onPlaneFly();
        }
    }

    private void notifyObserversOfLand() {
        for (PlaneObserver observer : observers) {
            observer.onPlaneLand();
        }
    }
}

主程序使用示例:

public class AirportSimulator {
    public static void main(String[] args) {
        Plane myPlane = new Plane();
        myPlane.addObserver(new ConsolePlaneObserver());
        // 还可以加其他观察者,比如LogFileObserver
        
        myPlane.fly();
        myPlane.land();
    }
}
方案3:静态日志工具(简单快速,适合小型项目)

如果你的课程项目比较简单,不想搞太复杂的设计,可以用Java自带的日志框架(或者第三方的SLF4J/Logback,但学校课程可能更倾向于原生工具)。这样既避免了硬编码控制台输出,又能轻松切换输出目标。

示例代码:

import java.util.logging.Logger;

public class Plane {
    // 为Plane类创建一个日志实例
    private static final Logger logger = Logger.getLogger(Plane.class.getName());

    public void fly() {
        // 起飞业务逻辑
        logger.info("飞机执行起飞操作,当前状态:起飞中");
    }

    public void land() {
        // 降落业务逻辑
        logger.info("飞机执行降落操作,当前状态:降落中");
    }
}

默认情况下,日志会输出到控制台。如果以后要改输出到文件,只需要修改日志配置文件,不用改业务代码,比直接用System.out灵活得多。


内容的提问来源于stack exchange,提问作者chill-nate

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:56:25