找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4387

积分

0

好友

601

主题
发表于 2026-2-4 08:59:59 | 查看: 87| 回复: 0

在软件开发中,随着需求迭代,代码逐渐变得臃肿、耦合,难以维护——这就是所谓的“代码腐化”。它不仅降低开发效率,更会积累沉重的技术债务。今天,我们就通过一个具体的 C++ 案例,一步步演示如何运用经典的设计模式,将一团乱麻的函数重构成清晰、可扩展的优雅代码。

原始代码展示

我们先来看一个典型的“上帝函数”,它试图在一个函数 processOrder 中完成所有订单处理逻辑:

#include <iostream>
#include <string>
#include <vector>
#include <fstream>

using namespace std;

void processOrder(const string& orderId, const vector<string>& items){
// 验证订单
if (orderId.empty()) {
cout << "订单ID不能为空" << endl;
return;
    }

// 计算总价
double totalPrice = 0.0;
for (const auto& item : items) {
if (item == "book") {
            totalPrice += 50.0;
        } else if (item == "pen") {
            totalPrice += 10.0;
        } else if (item == "notebook") {
            totalPrice += 20.0;
        }
    }

// 生成订单文件
ofstream orderFile("order_" + orderId + ".txt");
if (orderFile.is_open()) {
        orderFile << "订单ID: " << orderId << endl;
        orderFile << "商品列表: ";
for (const auto& item : items) {
            orderFile << item << " ";
        }
        orderFile << endl;
        orderFile << "总价: " << totalPrice << endl;
        orderFile.close();
cout << "订单文件生成成功" << endl;
    } else {
cout << "无法创建订单文件" << endl;
    }

// 发送通知
cout << "订单已处理,通知客户" << endl;
}

int main(){
vector<string> items = {"book", "pen", "notebook"};
    processOrder("20260203001", items);
return 0;
}

问题分析

这段代码虽然功能完整,但存在典型的“坏味道”:

  1. 单一职责原则违反processOrder 函数承担了验证订单、计算总价、生成文件和发送通知等多个职责,导致函数过于庞大复杂。
  2. 紧耦合:函数内部直接依赖于具体的商品定价逻辑和文件操作方式,难以进行单元测试和扩展。
  3. 可扩展性差:当新增商品类型时,需要修改 processOrder 函数中的条件判断,违反了开闭原则。
  4. 代码重复:如果系统中存在多个类似的订单处理逻辑,会导致大量重复代码。
  5. 错误处理不完善:函数中的错误处理比较简单,缺乏统一的错误处理机制。

重构方案设计

设计思路

针对上述问题,我们将采用分阶段的重构策略,逐步引入经典设计模式

  1. 单一职责原则:将订单处理的不同职责拆分到不同的类中。
  2. 策略模式:将商品定价逻辑封装到策略类中,实现运行时切换。
  3. 工厂模式:根据不同的订单类型创建不同的订单处理器。
  4. 观察者模式:实现订单处理完成后的通知机制。

重构阶段规划

  1. 第一阶段:职责拆分,将订单处理的不同功能拆分到不同的类中。
  2. 第二阶段:应用策略模式,将商品定价逻辑抽象为策略接口。
  3. 第三阶段:应用工厂模式,实现订单处理器的动态创建。
  4. 第四阶段:应用观察者模式,实现订单处理完成后的通知机制。
  5. 第五阶段:代码优化与测试,确保重构后的代码功能正确且性能良好。

重构实施

第一阶段:职责拆分

首先,我们将原来混杂在单一函数中的职责,拆分到独立的类中。每个类只做一件事。

// 订单验证器
class OrderValidator {
public:
bool validate(const string& orderId){
if (orderId.empty()) {
cout << "订单ID不能为空" << endl;
return false;
        }
return true;
    }
};

// 价格计算器
class PriceCalculator {
public:
double calculate(const vector<string>& items){
double totalPrice = 0.0;
for (const auto& item : items) {
if (item == "book") {
                totalPrice += 50.0;
            } else if (item == "pen") {
                totalPrice += 10.0;
            } else if (item == "notebook") {
                totalPrice += 20.0;
            }
        }
return totalPrice;
    }
};

// 订单文件生成器
class OrderFileGenerator {
public:
bool generate(const string& orderId, const vector<string>& items, double totalPrice){
        ofstream orderFile("order_" + orderId + ".txt");
if (orderFile.is_open()) {
            orderFile << "订单ID: " << orderId << endl;
            orderFile << "商品列表: ";
for (const auto& item : items) {
                orderFile << item << " ";
            }
            orderFile << endl;
            orderFile << "总价: " << totalPrice << endl;
            orderFile.close();
cout << "订单文件生成成功" << endl;
return true;
        } else {
cout << "无法创建订单文件" << endl;
return false;
        }
    }
};

// 通知发送器
class NotificationSender {
public:
void send(const string& orderId){
cout << "订单" << orderId << "已处理,通知客户" << endl;
    }
};

// 订单处理器
class OrderProcessor {
private:
    OrderValidator validator;
    PriceCalculator calculator;
    OrderFileGenerator fileGenerator;
    NotificationSender sender;

public:
void process(const string& orderId, const vector<string>& items){
if (!validator.validate(orderId)) {
return;
        }

double totalPrice = calculator.calculate(items);

if (!fileGenerator.generate(orderId, items, totalPrice)) {
return;
        }

        sender.send(orderId);
    }
};

int main(){
vector<string> items = {"book", "pen", "notebook"};
    OrderProcessor processor;
    processor.process("20260203001", items);
return 0;
}

重构效果:通过职责拆分,每个类都变得小巧且目标明确。OrderProcessor 现在只负责协调,符合单一职责原则,代码的可读性和可维护性显著提高。单元测试也变得容易,你可以单独测试 PriceCalculatorOrderValidator

第二阶段:应用策略模式

价格计算器中仍存在硬编码的条件判断。我们使用策略模式将其抽象。

// 定价策略接口
class PricingStrategy {
public:
virtual double calculatePrice(const string& item) = 0;
virtual ~PricingStrategy() = default;
};

// 图书定价策略
class BookPricingStrategy : public PricingStrategy {
public:
double calculatePrice(const string& item) override {
return 50.0;
    }
};

// 笔定价策略
class PenPricingStrategy : public PricingStrategy {
public:
double calculatePrice(const string& item) override {
return 10.0;
    }
};

// 笔记本定价策略
class NotebookPricingStrategy : public PricingStrategy {
public:
double calculatePrice(const string& item) override {
return 20.0;
    }
};

// 价格计算器
class PriceCalculator {
private:
    map<string, unique_ptr<PricingStrategy>> strategies;

public:
    PriceCalculator() {
        strategies["book"] = make_unique<BookPricingStrategy>();
        strategies["pen"] = make_unique<PenPricingStrategy>();
        strategies["notebook"] = make_unique<NotebookPricingStrategy>();
    }

double calculate(const vector<string>& items){
double totalPrice = 0.0;
for (const auto& item : items) {
if (strategies.find(item) != strategies.end()) {
                totalPrice += strategies[item]->calculatePrice(item);
            }
        }
return totalPrice;
    }
};

重构效果:定价逻辑被封装到独立的策略类中。现在,如果要新增一种商品(例如“eraser”),你只需要创建一个新的 EraserPricingStrategy 类并在 PriceCalculator 的构造器中注册它,无需修改 PriceCalculator::calculate 方法的任何现有代码。这完美遵循了开闭原则,系统扩展性大大增强。

第三阶段:应用工厂模式

系统可能需要支持不同类型的订单(如普通订单、加急订单)。我们可以用工厂模式来创建对应的处理器。

// 订单处理器接口
class OrderProcessor {
public:
virtual void process(const string& orderId, const vector<string>& items) = 0;
virtual ~OrderProcessor() = default;
};

// 普通订单处理器
class NormalOrderProcessor : public OrderProcessor {
private:
    OrderValidator validator;
    PriceCalculator calculator;
    OrderFileGenerator fileGenerator;
    NotificationSender sender;

public:
void process(const string& orderId, const vector<string>& items) override {
if (!validator.validate(orderId)) {
return;
        }

double totalPrice = calculator.calculate(items);

if (!fileGenerator.generate(orderId, items, totalPrice)) {
return;
        }

        sender.send(orderId);
    }
};

// 加急订单处理器
class ExpressOrderProcessor : public OrderProcessor {
private:
    OrderValidator validator;
    PriceCalculator calculator;
    OrderFileGenerator fileGenerator;
    NotificationSender sender;

public:
void process(const string& orderId, const vector<string>& items) override {
if (!validator.validate(orderId)) {
return;
        }

double totalPrice = calculator.calculate(items) * 1.2; // 加急订单加价20%

if (!fileGenerator.generate(orderId, items, totalPrice)) {
return;
        }

        sender.send(orderId + " (加急)");
    }
};

// 订单处理器工厂
class OrderProcessorFactory {
public:
static unique_ptr<OrderProcessor> createProcessor(const string& orderType){
if (orderType == "normal") {
return make_unique<NormalOrderProcessor>();
        } else if (orderType == "express") {
return make_unique<ExpressOrderProcessor>();
        }
return nullptr;
    }
};

int main(){
vector<string> items = {"book", "pen", "notebook"};

// 创建普通订单处理器
auto normalProcessor = OrderProcessorFactory::createProcessor("normal");
if (normalProcessor) {
        normalProcessor->process("20260203001", items);
    }

// 创建加急订单处理器
auto expressProcessor = OrderProcessorFactory::createProcessor("express");
if (expressProcessor) {
        expressProcessor->process("20260203002", items);
    }

return 0;
}

重构效果:客户端(main函数)不再需要知道 NormalOrderProcessorExpressOrderProcessor 的具体实现细节,它只依赖于抽象的 OrderProcessor 接口和 OrderProcessorFactory。这种松耦合的设计使得增加新的订单类型(如“团购订单”)变得非常容易,只需新增一个处理器类并扩展工厂方法,而不会影响现有客户端代码。

第四阶段:应用观察者模式

最后,我们改造通知机制。原来的 NotificationSender 是紧耦合的,我们使用观察者模式来实现灵活、可扩展的通知系统。

// 观察者接口
class OrderObserver {
public:
virtual void onOrderProcessed(const string& orderId) = 0;
virtual ~OrderObserver() = default;
};

// 邮件通知观察者
class EmailNotificationObserver : public OrderObserver {
public:
void onOrderProcessed(const string& orderId) override {
cout << "发送邮件通知:订单" << orderId << "已处理" << endl;
    }
};

// 短信通知观察者
class SMSNotificationObserver : public OrderObserver {
public:
void onOrderProcessed(const string& orderId) override {
cout << "发送短信通知:订单" << orderId << "已处理" << endl;
    }
};

// 订单处理器接口
class OrderProcessor {
public:
virtual void process(const string& orderId, const vector<string>& items) = 0;
virtual void addObserver(unique_ptr<OrderObserver> observer) = 0;
virtual ~OrderProcessor() = default;
};

// 普通订单处理器
class NormalOrderProcessor : public OrderProcessor {
private:
    OrderValidator validator;
    PriceCalculator calculator;
    OrderFileGenerator fileGenerator;
    vector<unique_ptr<OrderObserver>> observers;

public:
void process(const string& orderId, const vector<string>& items) override {
if (!validator.validate(orderId)) {
return;
        }

double totalPrice = calculator.calculate(items);

if (!fileGenerator.generate(orderId, items, totalPrice)) {
return;
        }

// 通知所有观察者
for (const auto& observer : observers) {
            observer->onOrderProcessed(orderId);
        }
    }

void addObserver(unique_ptr<OrderObserver> observer) override {
        observers.push_back(move(observer));
    }
};

int main(){
vector<string> items = {"book", "pen", "notebook"};

// 创建普通订单处理器 (假设工厂模式已集成)
auto normalProcessor = OrderProcessorFactory::createProcessor("normal");
if (normalProcessor) {
// 添加观察者
        normalProcessor->addObserver(make_unique<EmailNotificationObserver>());
        normalProcessor->addObserver(make_unique<SMSNotificationObserver>());

        normalProcessor->process("20260203001", items);
    }

return 0;
}

重构效果:通知系统与订单处理逻辑彻底解耦。OrderProcessor 不再关心谁接收通知、如何通知,它只负责在适当的时候发出事件。你可以动态地添加或移除观察者(例如新增一个“企业微信通知观察者”),而订单处理的核心代码纹丝不动。这再次体现了开闭原则的强大威力。

总结

回顾这次重构之旅,我们从一个职责混乱、高度耦合的“上帝函数”出发,通过分步应用单一职责原则策略模式工厂模式观察者模式,最终构建了一个职责清晰、松耦合、易扩展的C++系统。

重构的核心价值不在于让代码立刻多做多少事,而在于让代码在未来更容易应对变化。每一次拆分、每一个接口的引入,都是在为代码的可维护性和可扩展性投资。掌握这些设计原则与模式,并将其融入日常的编码与重构实践中,是每一位追求卓越的开发者必经之路。

希望这个详细的案例能为你提供清晰的代码重构思路。如果你对如何在复杂系统中进行更大规模的重构,或者对其他设计模式的应用有疑问,欢迎在云栈社区与更多开发者一起交流探讨。

C++项目技术模块与知识库管理界面截图




上一篇:手机直连卫星为何难?解析大规模用户并发的四大技术壁垒与巨头优势
下一篇:深度解析DCDC芯片:为何TPS54302等标称3A实际输出能力却不同?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-26 12:05 , Processed in 0.521546 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表