Java模板方法案例

wen java案例 3

本文目录导读:

Java模板方法案例

  1. Java模板方法模式案例
  2. 案例1:游戏制作模板
  3. 案例2:数据导出系统
  4. 案例3:银行取款流程
  5. 模板方法模式的优势
  6. 适用场景

Java模板方法模式案例

模板方法模式是一种行为设计模式,它定义一个操作中的算法骨架,而将一些步骤延迟到子类中,下面通过几个实际案例来演示。

案例1:游戏制作模板

基础模板类

// 游戏模板
public abstract class Game {
    // 模板方法 - 定义游戏流程
    public final void play() {
        // 初始化游戏
        initGame();
        // 开始游戏
        startPlay();
        // 结束游戏
        endPlay();
        // 可选钩子方法
        if (isAddBonus()) {
            addBonus();
        }
    }
    // 抽象方法 - 子类必须实现
    protected abstract void initGame();
    protected abstract void startPlay();
    protected abstract void endPlay();
    // 钩子方法 - 子类可选覆盖
    protected boolean isAddBonus() {
        return false;
    }
    protected void addBonus() {
        System.out.println("添加额外奖励");
    }
}

具体子类实现

// 足球游戏
public class FootballGame extends Game {
    @Override
    protected void initGame() {
        System.out.println("足球游戏初始化:创建22名球员,准备足球场");
    }
    @Override
    protected void startPlay() {
        System.out.println("足球游戏开始:开球,比赛进行中");
    }
    @Override
    protected void endPlay() {
        System.out.println("足球游戏结束:裁判吹响终场哨");
    }
    // 覆盖钩子方法
    @Override
    protected boolean isAddBonus() {
        return true;
    }
    @Override
    protected void addBonus() {
        System.out.println("足球游戏特殊奖励:最佳球员额外获得10分");
    }
}
// 篮球游戏
public class BasketballGame extends Game {
    @Override
    protected void initGame() {
        System.out.println("篮球游戏初始化:创建10名球员,准备篮球场");
    }
    @Override
    protected void startPlay() {
        System.out.println("篮球游戏开始:跳球,比赛开始");
    }
    @Override
    protected void endPlay() {
        System.out.println("篮球游戏结束:计时器响铃");
    }
}

测试代码

public class TemplateMethodDemo {
    public static void main(String[] args) {
        System.out.println("=== 足球游戏 ===");
        Game football = new FootballGame();
        football.play();
        System.out.println("\n=== 篮球游戏 ===");
        Game basketball = new BasketballGame();
        basketball.play();
    }
}

输出结果

=== 足球游戏 ===
足球游戏初始化:创建22名球员,准备足球场
足球游戏开始:开球,比赛进行中
足球游戏结束:裁判吹响终场哨
足球游戏特殊奖励:最佳球员额外获得10分
=== 篮球游戏 ===
篮球游戏初始化:创建10名球员,准备篮球场
篮球游戏开始:跳球,比赛开始
篮球游戏结束:计时器响铃

案例2:数据导出系统

导出模板类

// 数据导出模板
public abstract class DataExporter {
    // 模板方法 - 定义导出流程
    public final void exportData(String data) {
        System.out.println("===== 开始导出数据 =====");
        // 1. 验证数据
        if (!validateData(data)) {
            System.out.println("数据验证失败,导出终止");
            return;
        }
        // 2. 处理数据
        String processedData = processData(data);
        // 3. 写入文件
        writeToFile(processedData);
        // 4. 发送通知
        sendNotification();
        System.out.println("===== 导出完成 =====");
    }
    // 抽象方法
    protected abstract boolean validateData(String data);
    protected abstract String processData(String data);
    protected abstract void writeToFile(String data);
    // 具体方法
    protected void sendNotification() {
        System.out.println("发送导出完成通知");
    }
    // 钩子方法
    protected boolean needValidation() {
        return true;
    }
}

具体导出类

// CSV导出器
public class CSVExporter extends DataExporter {
    @Override
    protected boolean validateData(String data) {
        System.out.println("CSV格式验证:检查逗号分隔格式");
        return data != null && data.contains(",");
    }
    @Override
    protected String processData(String data) {
        System.out.println("CSV数据处理:添加表头和数据行");
        return "ID,名称,价格\n" + data;
    }
    @Override
    protected void writeToFile(String data) {
        System.out.println("写入CSV文件:export.csv");
        System.out.println("文件内容:\n" + data);
    }
}
// PDF导出器
public class PDFExporter extends DataExporter {
    @Override
    protected boolean validateData(String data) {
        System.out.println("PDF格式验证:检查数据完整性");
        return data != null && !data.isEmpty();
    }
    @Override
    protected String processData(String data) {
        System.out.println("PDF数据处理:添加PDF标记和字体信息");
        return "%PDF-1.4\n" + data + "\n%%EOF";
    }
    @Override
    protected void writeToFile(String data) {
        System.out.println("写入PDF文件:export.pdf");
        System.out.println("文件内容:\n" + data);
    }
}

测试代码

public class ExportDemo {
    public static void main(String[] args) {
        // CSV导出
        System.out.println("=== CSV导出 ===");
        DataExporter csvExporter = new CSVExporter();
        csvExporter.exportData("1,苹果,5.5\n2,香蕉,3.2");
        System.out.println("\n=== PDF导出 ===");
        DataExporter pdfExporter = new PDFExporter();
        pdfExporter.exportData("商品列表\na. 苹果 - 5.5元\nb. 香蕉 - 3.2元");
    }
}

案例3:银行取款流程

银行模板类

// 银行取款模板
public abstract class BankTransaction {
    // 模板方法 - 定义取款流程
    public final void withdraw(String account, double amount) {
        System.out.println("===== 取款流程开始 =====");
        // 1. 验证账户
        if (!verifyAccount(account)) {
            System.out.println("账户验证失败");
            return;
        }
        // 2. 验证余额
        if (!verifyBalance(account, amount)) {
            System.out.println("余额不足");
            return;
        }
        // 3. 执行取款
        double fee = calculateFee(amount);
        double actualAmount = amount - fee;
        executeWithdrawal(account, actualAmount);
        // 4. 记录交易
        logTransaction(account, actualAmount, fee);
        // 5. 可选发送短信
        if (needSendSMS()) {
            sendSMS("取款成功:" + actualAmount + "元,手续费:" + fee + "元");
        }
        System.out.println("===== 取款流程结束 =====");
    }
    // 抽象方法
    protected abstract boolean verifyAccount(String account);
    protected abstract boolean verifyBalance(String account, double amount);
    protected abstract void executeWithdrawal(String account, double amount);
    protected abstract double calculateFee(double amount);
    // 通用方法
    protected void logTransaction(String account, double amount, double fee) {
        System.out.println("记录交易:" + account + " 取款" + amount + "元,手续费" + fee + "元");
    }
    // 钩子方法
    protected boolean needSendSMS() {
        return true;
    }
    protected void sendSMS(String message) {
        System.out.println("发送短信通知:" + message);
    }
}

具体银行类

// 普通银行取款
public class NormalBank extends BankTransaction {
    @Override
    protected boolean verifyAccount(String account) {
        System.out.println("普通银行验证账户:" + account);
        return account.startsWith("SAV");
    }
    @Override
    protected boolean verifyBalance(String account, double amount) {
        System.out.println("普通银行检查余额");
        // 假设余额充足
        return amount <= 10000;
    }
    @Override
    protected void executeWithdrawal(String account, double amount) {
        System.out.println("普通银行执行取款:" + amount + "元");
    }
    @Override
    protected double calculateFee(double amount) {
        // 普通银行手续费1%
        return amount * 0.01;
    }
    @Override
    protected boolean needSendSMS() {
        return true;
    }
}
// VIP银行取款
public class VIPBank extends BankTransaction {
    @Override
    protected boolean verifyAccount(String account) {
        System.out.println("VIP银行验证账户:" + account);
        return account.startsWith("VIP");
    }
    @Override
    protected boolean verifyBalance(String account, double amount) {
        System.out.println("VIP银行检查余额");
        // VIP客户可透支
        return amount <= 100000;
    }
    @Override
    protected void executeWithdrawal(String account, double amount) {
        System.out.println("VIP银行执行取款:" + amount + "元");
    }
    @Override
    protected double calculateFee(double amount) {
        // VIP客户免手续费
        return 0;
    }
    // 覆盖钩子方法
    @Override
    protected boolean needSendSMS() {
        return false; // VIP客户不需要短信通知
    }
}

测试代码

public class BankDemo {
    public static void main(String[] args) {
        System.out.println("=== 普通银行取款 ===");
        BankTransaction normalBank = new NormalBank();
        normalBank.withdraw("SAV001", 1000);
        System.out.println("\n=== VIP银行取款 ===");
        BankTransaction vipBank = new VIPBank();
        vipBank.withdraw("VIP001", 5000);
    }
}

模板方法模式的优势

  1. 代码复用:公共算法骨架在父类中实现一次,子类只实现差异部分
  2. 控制流程:算法流程由父类控制,子类无法改变流程顺序
  3. 扩展方便:通过钩子方法,子类可以灵活地插入自定义逻辑
  4. 符合开闭原则:新增功能时,只需创建新的子类,不需要修改父类

适用场景

  • 多个子类有共同的操作步骤和算法
  • 重要的、复杂的算法集中在父类中
  • 想让子类实现算法的可变部分,保持算法的整体结构不变
  • 需要通过钩子方法控制子类的扩展点

模板方法模式非常适合处理那些有固定流程,但具体步骤实现不同的业务场景,如业务流程、数据处理、框架设计等。

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