代碼重構的15個小技巧
前言
相信很多小伙伴在日常工作中都會遇到這樣的情況:接手了一個歷史項目,代碼像一團亂麻。
或者自己寫的代碼隨著業務的不斷迭代,變得越來越臃腫難以維護。
這時候,代碼重構就顯得尤為重要了。
那么,如何進行高效的代碼重構呢?
這篇文章我跟大家大家一起聊聊15個實用的代碼重構技巧,希望對你會有所幫助。
1. 提取方法
有些小伙伴在工作中可能會寫出這樣的代碼:一個方法幾百行,里面包含了各種業務邏輯。
這樣的代碼不僅難以閱讀,也難以維護和測試。
重構前:
public void processOrder(Order order) {
// 驗證訂單
if (order == null) {
throw new IllegalArgumentException("訂單不能為空");
}
if (order.getItems() == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("訂單項不能為空");
}
if (order.getCustomer() == null) {
throw new IllegalArgumentException("客戶信息不能為空");
}
// 計算訂單總價
double total = 0;
for (OrderItem item : order.getItems()) {
double price = item.getPrice();
int quantity = item.getQuantity();
total += price * quantity;
}
// 應用折扣
if (order.getCustomer().isVip()) {
total = total * 0.9;
}
// 保存訂單
order.setTotal(total);
orderRepository.save(order);
// 發送通知
String message = "訂單" + order.getId() + "已處理,總價:" +
total;
emailService.sendEmail(order.getCustomer().getEmail(), "訂單處理
通知", message);
smsService.sendSms(order.getCustomer().getPhone(), message);
}重構后:
public void processOrder(Order order) {
validateOrder(order);
double total = calculateOrderTotal(order);
total = applyDiscount(order, total);
saveOrder(order, total);
sendNotifications(order, total);
}
private void validateOrder(Order order) {
if (order == null) {
thrownew IllegalArgumentException("訂單不能為空");
}
if (order.getItems() == null || order.getItems().isEmpty()) {
thrownew IllegalArgumentException("訂單項不能為空");
}
if (order.getCustomer() == null) {
thrownew IllegalArgumentException("客戶信息不能為空");
}
}
private double calculateOrderTotal(Order order) {
double total = 0;
for (OrderItem item : order.getItems()) {
double price = item.getPrice();
int quantity = item.getQuantity();
total += price * quantity;
}
return total;
}
private double applyDiscount(Order order, double total) {
if (order.getCustomer().isVip()) {
return total * 0.9;
}
return total;
}
private void saveOrder(Order order, double total) {
order.setTotal(total);
orderRepository.save(order);
}
private void sendNotifications(Order order, double total) {
String message = "訂單" + order.getId() + "已處理,總價:" +
total;
emailService.sendEmail(order.getCustomer().getEmail(), "訂單處理
通知", message);
smsService.sendSms(order.getCustomer().getPhone(), message);
}通過提取方法,我們將一個大方法拆分成了多個小方法,每個方法只負責一個功能。
這樣不僅提高了代碼的可讀性,也使得每個方法更容易測試和維護。
2. 引入解釋性變量
有時候,一個復雜的表達式可能難以理解。
這時,我們可以引入一個解釋性變量來提高代碼的可讀性。
重構前:
public boolean isEligibleForDiscount(Customer customer, Order
order) {
return (customer.getAge() >= 60 || (customer.getMembershipYears
() > 5 && order.getTotal() > 1000)) && !customer.
hasOutstandingPayments();
}重構后:
public boolean isEligibleForDiscount(Customer customer, Order
order) {
boolean isSenior = customer.getAge() >= 60;
boolean isLoyalCustomerWithLargeOrder = customer.
getMembershipYears() > 5 && order.getTotal() > 1000;
boolean hasNoOutstandingPayments = !customer.
hasOutstandingPayments();
return (isSenior || isLoyalCustomerWithLargeOrder) &&
hasNoOutstandingPayments;
}通過引入解釋性變量,我們使得復雜的條件表達式更加清晰易懂。每個變量都有一個描述性的名稱,使得代碼的意圖更加明確。
3. 替換條件表達式
有些小伙伴在處理不同類型的對象時,可能會使用大量的條件語句(if-else或switch)。
這樣的代碼不僅冗長,而且每次添加新類型都需要修改這些條件語句,違反了開閉原則。
重構前:
public class PaymentProcessor {
public void processPayment(Payment payment) {
if (payment.getType().equals("CREDIT_CARD")) {
// 處理信用卡支付
validateCreditCard(payment);
chargeCreditCard(payment);
} else if (payment.getType().equals("PAYPAL")) {
// 處理PayPal支付
validatePayPalAccount(payment);
chargePayPalAccount(payment);
} else if (payment.getType().equals("BANK_TRANSFER")) {
// 處理銀行轉賬
validateBankAccount(payment);
initiateTransfer(payment);
} else {
throw new IllegalArgumentException("不支持的支付類型:" +
payment.getType());
}
}
// 其他方法...
}重構后:
public interface PaymentProcessor {
void processPayment(Payment payment);
}
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
validateCreditCard(payment);
chargeCreditCard(payment);
}
// 其他方法...
}
public class PayPalProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
validatePayPalAccount(payment);
chargePayPalAccount(payment);
}
// 其他方法...
}
public class BankTransferProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
validateBankAccount(payment);
initiateTransfer(payment);
}
// 其他方法...
}
public class PaymentFactory {
public static PaymentProcessor getProcessor(String paymentType)
{
if (paymentType.equals("CREDIT_CARD")) {
return new CreditCardProcessor();
} elseif (paymentType.equals("PAYPAL")) {
return new PayPalProcessor();
} elseif (paymentType.equals("BANK_TRANSFER")) {
return new BankTransferProcessor();
} else {
throw new IllegalArgumentException("不支持的支付類型:" +
paymentType);
}
}
}
// 使用
PaymentProcessor processor = PaymentFactory.getProcessor(payment.
getType());
processor.processPayment(payment);通過使用多態,我們將不同類型的支付處理邏輯分散到各自的類中,使得代碼更加模塊化,也更容易擴展。
當需要添加新的支付類型時,只需創建一個新的處理器類,而不需要修改現有的代碼。
4. 移除重復代碼
代碼重復是軟件開發中的一大問題。
重復的代碼不僅增加了代碼量,也增加了維護的難度。當需要修改一個功能時,可能需要在多個地方進行相同的修改,這增加了出錯的可能性。
重構前:
public class UserService {
public User findUserById(Long id) {
// 記錄日志
Logger logger = LoggerFactory.getLogger(UserService.class);
logger.info("查詢用戶,ID:" + id);
// 查詢用戶
User user = userRepository.findById(id);
if (user == null) {
logger.error("用戶不存在,ID:" + id);
thrownew UserNotFoundException("用戶不存在,ID:" + id);
}
return user;
}
public User findUserByEmail(String email) {
// 記錄日志
Logger logger = LoggerFactory.getLogger(UserService.class);
logger.info("查詢用戶,Email:" + email);
// 查詢用戶
User user = userRepository.findByEmail(email);
if (user == null) {
logger.error("用戶不存在,Email:" + email);
thrownew UserNotFoundException("用戶不存在,Email:" +
email);
}
return user;
}
}重構后:
public class UserService {
private static final Logger logger = LoggerFactory.getLogger
(UserService.class);
public User findUserById(Long id) {
logger.info("查詢用戶,ID:" + id);
return findUserOrThrow(() -> userRepository.findById(id), "
用戶不存在,ID:" + id);
}
public User findUserByEmail(String email) {
logger.info("查詢用戶,Email:" + email);
return findUserOrThrow(() -> userRepository.findByEmail
(email), "用戶不存在,Email:" + email);
}
private User findUserOrThrow(Supplier<User> finder, String
errorMessage) {
User user = finder.get();
if (user == null) {
logger.error(errorMessage);
throw new UserNotFoundException(errorMessage);
}
return user;
}
}通過提取公共方法,我們消除了重復代碼,使得代碼更加簡潔。
當需要修改查詢用戶的邏輯時,只需要修改一個地方,而不是多個地方。
5. 引入參數對象
當一個方法有多個參數時,特別是當這些參數經常一起出現時,可以考慮將它們封裝成一個對象。
重構前:
public class ReportGenerator {
public Report generateReport(String startDate, String endDate,
String department, String format, boolean includeCharts) {
// 生成報告的邏輯
// ...
}
public void emailReport(String startDate, String endDate,
String department, String format, boolean includeCharts, String
email) {
Report report = generateReport(startDate, endDate,
department, format, includeCharts);
// 發送報告的邏輯
// ...
}
public void saveReport(String startDate, String endDate, String
department, String format, boolean includeCharts, String
filePath) {
Report report = generateReport(startDate, endDate,
department, format, includeCharts);
// 保存報告的邏輯
// ...
}
}重構后:
public class ReportCriteria {
private String startDate;
private String endDate;
private String department;
private String format;
private boolean includeCharts;
// 構造函數、getter和setter
// ...
}
public class ReportGenerator {
public Report generateReport(ReportCriteria criteria) {
// 生成報告的邏輯
// ...
}
public void emailReport(ReportCriteria criteria, String email) {
Report report = generateReport(criteria);
// 發送報告的邏輯
// ...
}
public void saveReport(ReportCriteria criteria, String
filePath) {
Report report = generateReport(criteria);
// 保存報告的邏輯
// ...
}
}通過引入參數對象,我們減少了方法的參數數量,使得方法調用更加簡潔。同時,參數對象也可以包含與這些參數相關的行為,進一步提高代碼的內聚性。
6. 使用策略模式
有些小伙伴在處理不同的算法或策略時,可能會使用大量的條件語句。
這樣的代碼不僅難以維護,也難以擴展。
重構前:
public class ShippingCalculator {
public double calculateShippingCost(Order order, String
shippingMethod) {
if (shippingMethod.equals("STANDARD")) {
// 標準運費計算邏輯
return order.getWeight() * 0.5;
} else if (shippingMethod.equals("EXPRESS")) {
// 快遞運費計算邏輯
return order.getWeight() * 1.0 + 10;
} else if (shippingMethod.equals("OVERNIGHT")) {
// 隔夜運費計算邏輯
return order.getWeight() * 1.5 + 20;
} else {
throw new IllegalArgumentException("不支持的運輸方式:" +
shippingMethod);
}
}
}重構后:
public interface ShippingStrategy {
double calculateShippingCost(Order order);
}
public class StandardShipping implements ShippingStrategy {
@Override
public double calculateShippingCost(Order order) {
return order.getWeight() * 0.5;
}
}
public class ExpressShipping implements ShippingStrategy {
@Override
public double calculateShippingCost(Order order) {
return order.getWeight() * 1.0 + 10;
}
}
public class OvernightShipping implements ShippingStrategy {
@Override
public double calculateShippingCost(Order order) {
return order.getWeight() * 1.5 + 20;
}
}
public class ShippingCalculator {
private Map<String, ShippingStrategy> strategies = new HashMap<>
();
public ShippingCalculator() {
strategies.put("STANDARD", new StandardShipping());
strategies.put("EXPRESS", new ExpressShipping());
strategies.put("OVERNIGHT", new OvernightShipping());
}
public double calculateShippingCost(Order order, String
shippingMethod) {
ShippingStrategy strategy = strategies.get(shippingMethod);
if (strategy == null) {
thrownew IllegalArgumentException("不支持的運輸方式:" +
shippingMethod);
}
return strategy.calculateShippingCost(order);
}
}通過使用策略模式,我們將不同的運費計算邏輯分散到各自的類中,使得代碼更加模塊化,也更容易擴展。
當需要添加新的運輸方式時,只需創建一個新的策略類,并將其添加到策略映射中,而不需要修改現有的代碼。
7. 使用構建者模式
當一個類有多個構造參數時,特別是當有些參數是可選的時,可以考慮使用構建者模式。
重構前:
public class User {
private String username;
private String email;
private String firstName;
private String lastName;
private String phone;
private String address;
private String city;
private String country;
private String postalCode;
// 構造函數
public User(String username, String email) {
this.username = username;
this.email = email;
}
public User(String username, String email, String firstName,
String lastName) {
this.username = username;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
}
public User(String username, String email, String firstName,
String lastName, String phone) {
this.username = username;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
this.phone = phone;
}
// 更多構造函數...
// getter和setter
// ...
}重構后:
public class User {
private String username;
private String email;
private String firstName;
private String lastName;
private String phone;
private String address;
private String city;
private String country;
private String postalCode;
private User(Builder builder) {
this.username = builder.username;
this.email = builder.email;
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.phone = builder.phone;
this.address = builder.address;
this.city = builder.city;
this.country = builder.country;
this.postalCode = builder.postalCode;
}
// getter(沒有setter,使對象不可變)
// ...
public static class Builder {
// 必需參數
private final String username;
private final String email;
// 可選參數
private String firstName;
private String lastName;
private String phone;
private String address;
private String city;
private String country;
private String postalCode;
public Builder(String username, String email) {
this.username = username;
this.email = email;
}
public Builder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder lastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder phone(String phone) {
this.phone = phone;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder city(String city) {
this.city = city;
returnthis;
}
public Builder country(String country) {
this.c ountry = country;
return this;
}
public Builder postalCode(String postalCode) {
this.postalCode = postalCode;
return this;
}
public User build() {
return new User(this);
}
}
}
// 使用
User user = new User.Builder("johndoe", "john.doe@example.com")
.firstName("John")
.lastName("Doe")
.phone("1234567890")
.build();通過使用構建者模式,我們解決了構造函數參數過多的問題,使得對象創建更加靈活和可讀。
同時,構建者模式也可以確保對象在創建后是不可變的,提高了代碼的安全性。
8. 使用工廠方法
當對象的創建邏輯比較復雜時,可以考慮使用工廠方法。
重構前:
public class ProductService {
public Product createProduct(String type, String name, double
price) {
Product product;
if (type.equals("PHYSICAL")) {
product = new PhysicalProduct(name, price);
// 設置物理產品的屬性
// ...
} else if (type.equals("DIGITAL")) {
product = new DigitalProduct(name, price);
// 設置數字產品的屬性
// ...
} else if (type.equals("SUBSCRIPTION")) {
product = new SubscriptionProduct(name, price);
// 設置訂閱產品的屬性
// ...
} else {
throw new IllegalArgumentException("不支持的產品類型:" +
type);
}
return product;
}
}重構后:
public abstract class ProductFactory {
public static Product createProduct(String type, String name,
double price) {
if (type.equals("PHYSICAL")) {
return createPhysicalProduct(name, price);
} else if (type.equals("DIGITAL")) {
return createDigitalProduct(name, price);
} else if (type.equals("SUBSCRIPTION")) {
return createSubscriptionProduct(name, price);
} else {
thrownew IllegalArgumentException("不支持的產品類型:" +
type);
}
}
private static Product createPhysicalProduct(String name,
double price) {
PhysicalProduct product = new PhysicalProduct(name, price);
// 設置物理產品的屬性
// ...
return product;
}
private static Product createDigitalProduct(String name, double
price) {
DigitalProduct product = new DigitalProduct(name, price);
// 設置數字產品的屬性
// ...
return product;
}
private static Product createSubscriptionProduct(String name,
double price) {
SubscriptionProduct product = new SubscriptionProduct(name,
price);
// 設置訂閱產品的屬性
// ...
return product;
}
}
// 使用
Product product = ProductFactory.createProduct("PHYSICAL", "書籍",
29.99);通過使用工廠方法,我們將對象的創建邏輯從客戶端代碼中分離出來,使得代碼更加模塊化,也更容易維護。
當需要添加新的產品類型時,只需在工廠類中添加相應的創建方法,而不需要修改客戶端代碼。
9. 使用Optional避免空指針異常
空指針異常(NullPointerException)是Java中最常見的異常之一。
為了避免這種異常,我們可以使用Java 8引入的Optional類。
重構前:
public class UserService {
public User findUserById(Long id) {
// 查詢用戶
return userRepository.findById(id);
}
public String getUserEmail(Long id) {
User user = findUserById(id);
if (user != null) {
String email = user.getEmail();
if (email != null) {
return email;
}
}
return"未知";
}
}重構后:
public class UserService {
public Optional<User> findUserById(Long id) {
// 查詢用戶
User user = userRepository.findById(id);
return Optional.ofNullable(user);
}
public String getUserEmail(Long id) {
return findUserById(id)
.map(User::getEmail)
.orElse("未知");
}
}通過使用Optional,我們明確表示方法可能返回空值,使得代碼更加清晰。
同時,Optional提供了豐富的API,如map、filter、orElse等,使得處理可能為空的值更加方便。
10. 使用Stream API簡化集合操作
Java 8引入的Stream API提供了一種函數式編程的方式來處理集合,使得代碼更加簡潔和可讀。
重構前:
public class OrderService {
public List<Order> findLargeOrders(List<Order> orders) {
List<Order> largeOrders = new ArrayList<>();
for (Order order : orders) {
if (order.getTotal() > 1000) {
largeOrders.add(order);
}
}
return largeOrders;
}
public double calculateTotalRevenue(List<Order> orders) {
double total = 0;
for (Order order : orders) {
total += order.getTotal();
}
return total;
}
public List<String> getCustomerNames(List<Order> orders) {
List<String> names = new ArrayList<>();
for (Order order : orders) {
String name = order.getCustomer().getName();
if (!names.contains(name)) {
names.add(name);
}
}
return names;
}
}重構后:
public class OrderService {
public List<Order> findLargeOrders(List<Order> orders) {
return orders.stream()
.filter(order -> order.getTotal() > 1000)
.collect(Collectors.toList());
}
public double calculateTotalRevenue(List<Order> orders) {
return orders.stream()
.mapToDouble(Order::getTotal)
.sum();
}
public List<String> getCustomerNames(List<Order> orders) {
return orders.stream()
.map(order -> order.getCustomer().getName())
.distinct()
.collect(Collectors.toList());
}
}通過使用Stream API,我們將命令式的代碼轉換為聲明式的代碼,使得代碼更加簡潔和可讀。
Stream API提供了豐富的操作,如filter、map、reduce等,使得處理集合更加方便。
11. 使用Lambda表達式簡化匿名內部類
Java 8引入的Lambda表達式提供了一種更簡潔的方式來創建匿名函數,特別適合用于替代匿名內部類。
重構前:
public class ButtonHandler {
public void setupButton(Button button) {
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// 處理點擊事件
System.out.println("按鈕被點擊");
}
});
}
public void sortUsers(List<User> users) {
Collections.sort(users, new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
return u1.getName().compareTo(u2.getName());
}
});
}
}重構后:
public class ButtonHandler {
public void setupButton(Button button) {
button.setOnClickListener(view -> {
// 處理點擊事件
System.out.println("按鈕被點擊");
});
}
public void sortUsers(List<User> users) {
Collections.sort(users, (u1, u2) -> u1.getName().compareTo
(u2.getName()));
// 或者更簡潔地
users.sort(Comparator.comparing(User::getName));
}
}通過使用Lambda表達式,我們將冗長的匿名內部類替換為簡潔的函數式表達式,使得代碼更加簡潔和可讀。
12. 使用方法引用簡化Lambda表達式
Java 8引入的方法引用提供了一種更簡潔的方式來引用已有的方法,特別適合用于替代簡單的Lambda表達式。
重構前:
public class UserProcessor {
public List<String> getUserNames(List<User> users) {
return users.stream()
.map(user -> user.getName())
.collect(Collectors.toList());
}
public void printUsers(List<User> users) {
users.forEach(user -> System.out.println(user));
}
public List<User> createUsers(List<String> names) {
return names.stream()
.map(name -> new User(name))
.collect(Collectors.toList());
}
}重構后:
public class UserProcessor {
public List<String> getUserNames(List<User> users) {
return users.stream()
.map(User::getName)
.collect(Collectors.toList());
}
public void printUsers(List<User> users) {
users.forEach(System.out::println);
}
public List<User> createUsers(List<String> names) {
return names.stream()
.map(User::new)
.collect(Collectors.toList());
}
}通過使用方法引用,我們將簡單的Lambda表達式替換為更簡潔的方法引用,使得代碼更加簡潔和可讀。
13. 使用CompletableFuture簡化異步編程
Java 8引入的CompletableFuture提供了一種更簡潔的方式來處理異步操作,特別適合用于替代傳統的回調方式。
重構前:
public class UserService {
public void processUser(Long userId, Callback<User> callback) {
// 異步查詢用戶
userRepository.findByIdAsync(userId, new Callback<User>() {
@Override
public void onSuccess(User user) {
// 異步查詢用戶的訂單
orderRepository.findByUserIdAsync(userId, new
Callback<List<Order>>() {
@Override
public void onSuccess(List<Order> orders) {
// 處理用戶和訂單
user.setOrders(orders);
callback.onSuccess(user);
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
@Override
public void onError(Exception e) {
callback.onError(e);
}
});
}
}重構后:
public class UserService {
public CompletableFuture<User> processUser(Long userId) {
return userRepository.findByIdAsync(userId)
.thenCompose(user -> orderRepository.findByUserIdAsync
(userId)
.thenApply(orders -> {
user.setOrders(orders);
return user;
}));
}
}
// 使用
userService.processUser(123L)
.thenAccept(user -> {
// 處理用戶
System.out.println("用戶:" + user.getName());
System.out.println("訂單數:" + user.getOrders().size());
})
.exceptionally(e -> {
// 處理異常
System.err.println("處理用戶時出錯:" + e.getMessage());
returnnull;
});通過使用CompletableFuture,我們將嵌套的回調轉換為鏈式的調用,使得代碼更加簡潔和可讀。
CompletableFuture提供了豐富的API,如thenApply、thenCompose、thenAccept等,使得處理異步操作更加方便。
14. 使用接口默認方法簡化接口實現
Java 8引入的接口默認方法允許在接口中提供方法的默認實現,使得接口的演化更加靈活。
重構前:
public interface PaymentProcessor {
void processPayment(Payment payment);
void refundPayment(Payment payment);
void cancelPayment(Payment payment);
}
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
// 處理信用卡支付
}
@Override
public void refundPayment(Payment payment) {
// 處理信用卡退款
}
@Override
public void cancelPayment(Payment payment) {
// 取消支付并退款
refundPayment(payment);
}
}
public class PayPalProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
// 處理PayPal支付
}
@Override
public void refundPayment(Payment payment) {
// 處理PayPal退款
}
@Override
public void cancelPayment(Payment payment) {
// 取消支付并退款
refundPayment(payment);
}
}重構后:
public interface PaymentProcessor {
void processPayment(Payment payment);
void refundPayment(Payment payment);
default void cancelPayment(Payment payment) {
// 默認實現:取消支付并退款
refundPayment(payment);
}
}
public class CreditCardProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
// 處理信用卡支付
}
@Override
public void refundPayment(Payment payment) {
// 處理信用卡退款
}
}
public class PayPalProcessor implements PaymentProcessor {
@Override
public void processPayment(Payment payment) {
// 處理PayPal支付
}
@Override
public void refundPayment(Payment payment) {
// 處理PayPal退款
}
}通過使用接口默認方法,我們將公共的實現從具體的類中提取到接口中,減少了重復代碼。
當需要修改公共實現時,只需修改接口中的默認方法,而不需要修改所有實現類。
15. 使用枚舉替代常量
使用枚舉可以提供類型安全的常量,避免使用魔法數字或字符串常量。
重構前:
public class OrderStatus {
public static final String PENDING = "PENDING";
public static final String PROCESSING = "PROCESSING";
public static final String SHIPPED = "SHIPPED";
public static final String DELIVERED = "DELIVERED";
public static final String CANCELLED = "CANCELLED";
}
public class Order {
private String status;
public void setStatus(String status) {
this.status = status;
}
public String getStatus() {
return status;
}
public boolean isCancellable() {
return status.equals(OrderStatus.PENDING) || status.equals
(OrderStatus.PROCESSING);
}
}
// 使用
Order order = new Order();
order.setStatus(OrderStatus.PENDING);
// 可能的錯誤:使用了未定義的常量
order.setStatus("REFUNDED");重構后:
public enum OrderStatus {
PENDING,
PROCESSING,
SHIPPED,
DELIVERED,
CANCELLED;
public boolean isCancellable() {
return this == PENDING || this == PROCESSING;
}
}
public class Order {
private OrderStatus status;
public void setStatus(OrderStatus status) {
this.status = status;
}
public OrderStatus getStatus() {
return status;
}
public boolean isCancellable() {
return status.isCancellable();
}
}
// 使用
Order order = new Order();
order.setStatus(OrderStatus.PENDING);
// 編譯錯誤:無法使用未定義的枚舉常量
// order.setStatus("REFUNDED");通過使用枚舉,我們提供了類型安全的常量,避免了使用魔法數字或字符串常量可能導致的錯誤。
同時,枚舉也可以包含方法,使得與常量相關的行為更加內聚。
總結
在這篇文章中,我們探討了15個代碼重構的小技巧,從簡單的提取方法到高級的設計模式應用。
這些技巧可以幫助我們寫出更加簡潔、可讀、可維護的代碼。
代碼重構是一個持續的過程,我們應該在日常開發中不斷地應用這些技巧,逐步改進我們的代碼質量。
記住,好的代碼不僅僅是能夠正確運行,還應該易于理解、易于修改和易于擴展。
希望這些技巧對你有所幫助,讓我們一起寫出更好的代碼!

































