Java程序员的代码重构之旅:从混乱到优雅
Java程序员的代码重构之旅:从混乱到优雅
作为一个Java程序员,你是否曾经面对过这样的场景?代码库如同一团乱麻,函数命名让人摸不着头脑,逻辑分散在各个角落,每次修改都像是在玩俄罗斯方块,生怕哪一行不小心就会导致整个系统崩溃。别担心,今天我们就来一场代码重构的冒险,把这段混乱不堪的代码变成优雅的典范。
重构前的代码:一团糟
让我们先看看这位程序员朋友最初写的代码吧:
public class PaymentService {
public void processPayment(String paymentType, double amount, boolean isTaxDeducted) {
if (paymentType.equals("credit")) {
System.out.println("Processing credit card payment...");
double finalAmount = amount;
if (isTaxDeducted) {
finalAmount = calculateTax(amount);
}
chargeCreditCard(finalAmount);
} else if (paymentType.equals("debit")) {
System.out.println("Processing debit card payment...");
double finalAmount = amount;
if (isTaxDeducted) {
finalAmount = calculateTax(amount);
}
chargeDebitCard(finalAmount);
} else {
System.out.println("Unsupported payment type");
}
}
private double calculateTax(double amount) {
return amount * 0.05;
}
private void chargeCreditCard(double amount) {
System.out.println("Charging credit card for " + amount);
}
private void chargeDebitCard(double amount) {
System.out.println("Charging debit card for " + amount);
}
}
这段代码虽然能正常工作,但存在几个问题:
- 重复代码:处理信用卡和借记卡支付的逻辑几乎完全一样,只是调用了不同的方法。
- 硬编码:"credit"和"debit"这些字符串被直接写在代码里,增加了维护成本。
- 可读性差:函数名不够直观,参数含义不明。
接下来,我们一步步将这段代码重构为更优雅的形式。
第一步:提取公共逻辑
首先,我们可以看到chargeCreditCard和chargeDebitCard这两个方法非常相似,都是根据金额进行扣款操作。我们可以将它们合并成一个通用的方法。
private void chargeCard(double amount, String cardType) {
System.out.println("Charging " + cardType + " card for " + amount);
}
然后修改processPayment方法,统一调用这个新的chargeCard方法:
public void processPayment(String paymentType, double amount, boolean isTaxDeducted) {
if ("credit".equals(paymentType)) {
System.out.println("Processing credit card payment...");
double finalAmount = amount;
if (isTaxDeducted) {
finalAmount = calculateTax(amount);
}
chargeCard(finalAmount, "credit");
} else if ("debit".equals(paymentType)) {
System.out.println("Processing debit card payment...");
double finalAmount = amount;
if (isTaxDeducted) {
finalAmount = calculateTax(amount);
}
chargeCard(finalAmount, "debit");
} else {
System.out.println("Unsupported payment type");
}
}
这样做的好处是减少了重复代码,同时让代码结构更加清晰。
第二步:使用策略模式
为了让代码更具扩展性和灵活性,我们可以引入策略模式。通过定义一个接口PaymentStrategy,为每种支付方式实现不同的策略。
interface PaymentStrategy {
void execute(double amount);
}
class CreditCardPayment implements PaymentStrategy {
@Override
public void execute(double amount) {
System.out.println("Charging credit card for " + amount);
}
}
class DebitCardPayment implements PaymentStrategy {
@Override
public void execute(double amount) {
System.out.println("Charging debit card for " + amount);
}
}
接着修改PaymentService类,让它接受PaymentStrategy对象作为参数:
public class PaymentService {
private PaymentStrategy strategy;
public PaymentService(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void processPayment(double amount, boolean isTaxDeducted) {
double finalAmount = amount;
if (isTaxDeducted) {
finalAmount = calculateTax(amount);
}
strategy.execute(finalAmount);
}
private double calculateTax(double amount) {
return amount * 0.05;
}
}
现在我们可以轻松添加新的支付方式,而无需修改现有代码。比如新增一个PayPal支付:
class PayPalPayment implements PaymentStrategy {
@Override
public void execute(double amount) {
System.out.println("Processing PayPal payment for " + amount);
}
}
第三步:增强代码的可读性
最后一步是优化代码的可读性。我们可以使用枚举类型来代替字符串常量,这样不仅能提高代码的安全性,还能减少拼写错误的可能性。
enum PaymentType {
CREDIT, DEBIT, PAYPAL
}
public void processPayment(PaymentType type, double amount, boolean isTaxDeducted) {
PaymentStrategy strategy;
switch (type) {
case CREDIT:
strategy = new CreditCardPayment();
break;
case DEBIT:
strategy = new DebitCardPayment();
break;
case PAYPAL:
strategy = new PayPalPayment();
break;
default:
throw new IllegalArgumentException("Invalid payment type");
}
double finalAmount = amount;
if (isTaxDeducted) {
finalAmount = calculateTax(amount);
}
strategy.execute(finalAmount);
}
通过这些改进,我们的代码不仅更加简洁、灵活,而且易于维护和扩展。更重要的是,它传达了一个重要的编程理念:不要害怕重构,因为好的代码就像一杯好酒,越陈越香。
总结
代码重构是一门艺术,也是一种责任。它不仅仅是为了让代码看起来美观,更是为了提升系统的可维护性和可扩展性。希望今天的重构之旅能给你带来一些启发,在未来的编程生涯中,勇敢地拿起重构工具,让每一行代码都闪耀着智慧的光芒。记住,优秀的程序员不仅要会写代码,还要会“修理”代码!