Java小案例

wen java案例 3

5个Java小案例,让你彻底搞懂面向对象编程的核心逻辑

📚 目录导读

  1. 简易计算器——从“过程”到“对象”的思维转变
  2. 学生信息管理系统——封装与私有化的实战演练
  3. 模拟银行取款——继承与多态的经典应用
  4. 停车场计费系统——接口与抽象类的选择难题
  5. 工厂模式生成日志——设计模式在Java中的真实落地
  6. 高频面试问答(FAQ)

引言:为什么刷了那么多理论,你还是写不好Java?

很多初学者背熟了“封装、继承、多态”的定义,但一遇到实际开发就手足无措,核心原因在于——你缺少“场景化”的训练,本文通过5个由浅入深的Java小案例,带你从“写代码”进阶到“设计代码”,每个案例均取自真实业务简化模型,既包含语法要点,又暗含设计思想。

Java小案例


简易计算器——从“过程”到“对象”的思维转变

场景:需要实现加、减、乘、除四种运算。

传统过程式写法(反面教材):

public static double calc(double a, double b, String op) {
    if ("+".equals(op)) return a + b;
    else if ("-".equals(op)) return a - b;
    // ... 每次新增运算都要改这里
}

这种写法导致代码臃肿且违反“开闭原则”。

面向对象改造

interface Operation { double execute(double a, double b); }
class Add implements Operation { public double execute(double a, double b) { return a + b; } }
class Div implements Operation { 
    public double execute(double a, double b) { 
        if (b == 0) throw new ArithmeticException("除数不能为0");
        return a / b; 
    } 
}

核心收获:用Map<String, Operation>注册策略,新增运算只需添加新类,无需修改调用方,这就是策略模式的雏形。


学生信息管理系统——封装与私有化的实战演练

场景:管理学生的姓名、成绩,要求成绩不能为负数,且只能通过方法修改。

错误示范:直接公开属性public double score;——外部可随意赋负值,破坏数据完整性。

正确封装

public class Student {
    private String name;
    private double score;
    public void setScore(double score) {
        if (score < 0 || score > 100) {
            throw new IllegalArgumentException("成绩必须在0-100之间");
        }
        this.score = score;
    }
    public double getScore() { return score; }
    // 姓名只提供只读构造器设置
}

核心收获:封装不是简单加private,而是通过方法控制数据的合法性校验,同时暴露行为(如getRank())而非直接暴露数据。


模拟银行取款——继承与多态的经典应用

场景:普通储蓄卡与信用卡,取款逻辑不同(储蓄卡余额不足报错,信用卡允许透支但收取手续费)。

冗余写法:两个独立类,各写各的方法——代码重复且难扩展。

继承+多态优雅解法

abstract class BankCard {
    protected double balance;
    public abstract boolean withdraw(double amount); // 抽象方法强制子类实现
}
class DebitCard extends BankCard {
    public boolean withdraw(double amount) {
        if (balance >= amount) { balance -= amount; return true; }
        return false;
    }
}
class CreditCard extends BankCard {
    private double creditLimit;
    public boolean withdraw(double amount) {
        double fee = amount * 0.02; // 手续费
        if (balance + creditLimit >= amount + fee) {
            balance -= (amount + fee); // 允许负余额
            return true;
        }
        return false;
    }
}

核心收获:父类定义统一契约(抽象方法),子类各自实现细节,调用方只管用父类引用,运行时自动定位正确实现——这就是多态的价值。


停车场计费系统——接口与抽象类的选择难题

场景:小车每小时5元,货车每小时8元,但所有车辆都要记录入场时间。

初学者常见误区:把所有逻辑写在一个Vehicle类里,用type字段switch判断——后续新车型会改爆这个类。

接口+组合优于继承

interface FeeStrategy { double calcFee(long hours); }
class CarFee implements FeeStrategy { public double calcFee(long h) { return h * 5; } }
class TruckFee implements FeeStrategy { public double calcFee(long h) { return h * 8; } }
class ParkingTicket {
    private long entryTime;
    private FeeStrategy strategy; // 组合而非继承
    public double getFee() {
        long hours = (System.currentTimeMillis() - entryTime) / 3600000;
        return strategy.calcFee(hours);
    }
}

核心收获当存在“是”的关系(卡车是汽车)用继承;当存在“有”的关系(票据有计费策略)用组合,此处用接口隔离变化,比抽象类更灵活(一个类可实现多个接口)。


工厂模式生成日志——设计模式在Java中的真实落地

场景:根据配置文件决定输出到控制台或文件。

无工厂的代码:在业务代码里new ConsoleLogger()new FileLogger()——一旦切换需改动业务代码。

简单工厂解法

interface Logger { void log(String msg); }
class ConsoleLogger implements Logger { public void log(String msg) { System.out.println(msg); } }
class FileLogger implements Logger { public void log(String msg) { /* 写文件 */ } }
class LoggerFactory {
    public static Logger create(String type) {
        if ("file".equals(type)) return new FileLogger();
        return new ConsoleLogger();
    }
}
// 业务代码只依赖 Logger 接口
Logger logger = LoggerFactory.create(config.getProperty("log.type"));

核心收获:消灭了new关键字出现在业务代码中的坏味道,工厂模式让对象的创建与使用分离,配合配置文件可实现不重新编译就切换行为。


❓ 高频面试问答(FAQ)

Q1:抽象类和接口,到底怎么选?

答:优先用接口,只有需要共享状态(字段)或模板方法时用抽象类,JDK8后接口也有默认方法,90%场景接口足够。

Q2:我写的代码每次增加功能都要改旧代码,怎么办?

答:参考案例四,把变化的东西抽成策略/接口,核心原则:面向扩展开放,面向修改关闭(开闭原则)。

Q3:private字段怎么被外部访问?

答:通过public的getter/setter,但注意setter里要加校验逻辑,不能直接赋值(案例二已演示)。

Q4:多态是怎么实现的?

答:虚拟机在运行时根据实际对象类型,在方法表中查找对应方法,这就是“晚期绑定”或“动态分派”。

Q5:小项目需要设计模式吗?

答:不需要硬套,但建议从“小案例”开始,培养识别“变化点”的眼光——当发现if-else缠成一团时,就是重构为策略模式的好时机。


从“会用”到“会设计”的三步跃迁

  1. 第一步:跑通案例代码,理解每个关键字的语法作用。
  2. 第二步:对照“反例”与“正解”,体会设计思想(封装边界、接口隔离、继承层级)。
  3. 第三步:关闭教程,只凭中文需求重写代码,卡住的地方就是你的知识盲区。

Java学习不在于背诵多少API,而在于构建清晰的领域模型,这5个小案例虽简单,却浓缩了面向对象设计的大部分精髓,建议你亲手键入代码,并用JUnit为每个案例编写单元测试——那将是质变的开始。

上一篇计算器案例

下一篇记事本案例

抱歉,评论功能暂时关闭!