计划模式(二)

打印 上一主题 下一主题

主题 914|帖子 914|积分 2742

计划模式(二)

敏捷开发模式:Refactoring to Patterns
重构特点:
  1. 1. 静态 --------> 动态
  2. 1. 早绑定 -----------> 晚绑定
  3. 1. 继承 ----------> 组合
  4. 1. 编译时依赖 --------> 运行时依赖
  5. 1. 紧耦合 -------> 松耦合
复制代码
组件协作模式

通过晚期绑定,实现框架和应用间的松耦合

  • Template Method
  • Strategy
  • Observer / Event
  1. tips:
  2.         基类的析构函数需要写为 虚析构函数
  3. why:
  4.         1.析构函数的作用是清理对象占用的资源;当对象生命周期结束时,析构函数会被自动调用
  5.         2.为了确保当通过基类指针删除派生类对象时,能够正确地调用派生类的析构函数,从而避免资源泄漏
  6.         3.多态:基类指针可以指向派生类的对象;
  7.                 使用基类指针删除指向的派生类对象时,如果基类的析构函数不是虚的
  8.                 那么只会调用基类的析构函数,而不会调用派生类的析构函数
  9.                 派生类可能有自己的资源需要释放,比如动态分配的内存或者打开的文件,
  10.                 没有正确释放,就会造成资源的泄露
  11.         4.C++中对象的析构顺序是先调用派生类的析构函数,然后调用基类的析构函数
  12.                 如果基类的析构函数是虚的,那么当删除一个派生类对象时,
  13.                 首先会调用派生类的析构函数,然后是基类的析构函数
复制代码
Template Method

界说一个操纵中的算法的骨架(稳定), 而将一些步骤耽误(变化)到子类中
Template Method计划子类可以不改变(复用)一个算法的结构
即可重界说(override)该算法的某些步骤
  1. // 抽象类
  2. class Shape {
  3. public:
  4.     // 模板方法,定义了绘制图形的算法骨架
  5.     void draw() {
  6.         drawShape();
  7.         fillShape();
  8.     }
  9.     // 抽象操作,由子类实现
  10.     virtual void drawShape() = 0;
  11.     virtual void fillShape() = 0;
  12. };
  13. // 具体子类
  14. class Rectangle : public Shape {
  15. public:
  16.     // 实现抽象操作
  17.     void drawShape() override {
  18.         // 绘制矩形的轮廓
  19.     }
  20.     void fillShape() override {
  21.         // 填充矩形
  22.     }
  23. };
  24. class Circle : public Shape {
  25. public:
  26.     // 实现抽象操作
  27.     void drawShape() override {
  28.         // 绘制圆的轮廓
  29.     }
  30.     void fillShape() override {
  31.         // 填充圆
  32.     }
  33. };
复制代码
上述draw()是稳定的,不消虚函数
drawShape(), fillShape() 绘制图像,有圆的,有方的等
这是变化的,界说为虚函数;
这样就实现,算法的骨架(draw()) (稳定),变化(drawShape, fillShape)变化耽误到子类中
  1. 假设类中所有的都是稳定的,就不需要设计模式
  2. 假设类中所有都不是稳定的,也不需要设计模式了
复制代码
计划模式 就是在变化和稳定中间,寻找隔离点,将变化和稳定隔脱离
  1. tips:
  2.         查看代码时,找到类中哪些是变化的
  3.                                         哪些是稳定的
复制代码
  1. 这种晚绑定,c++通常用多态实现;
  2. 其实多态底层也是用函数指针实现
复制代码
Strategy

motivation
软件构建中,某些对象使用的算法大概多种多样;经常改变
假设这些算法都编码到对象中,将使对象变得异常复杂;
how to 运行时根据需要透明地更改对象的算法? 实现算法和对象本身解耦合
需要用动态的思维去思索题目,计划办理方案,思量将来;
如果使用静态的思维,只思量当前题目,无法计划出好的方案应对将来的变化
用扩展的方式来改变;而不是修改来改变源代码
eg:使用罗列(enum)来界说不同的税率计谋,然后使用if-else语句来选择相应的税率盘算方法
  1. enum TaxCountry {
  2.     CHINA,
  3.     USA,
  4.     GERMANY
  5. };
  6. double calculateTax(double income, TaxCountry country) {
  7.     switch (country) {
  8.         case CHINA:
  9.             return income * 0.2;
  10.         case USA:
  11.             return income * 0.3;
  12.         case GERMANY:
  13.             return income * 0.25;
  14.         default:
  15.             return 0;
  16.     }
  17. }
复制代码
计谋模式:创建一个TaxStrategy接口,将上面的每个case实例,界说为该接口的子类
  1. class TaxStrategy {
  2. public:
  3.     virtual ~TaxStrategy() {}
  4.     virtual double calculateTax(double income) = 0;
  5. };
  6. // 具体策略:中国税率
  7. class ChinaTaxStrategy : public TaxStrategy {
  8. public:
  9.     double calculateTax(double income) override {
  10.         return income * 0.2;
  11.     }
  12. };
  13. // 具体策略:美国税率
  14. class USATaxStrategy : public TaxStrategy {
  15. public:
  16.     double calculateTax(double income) override {
  17.         return income * 0.3;
  18.     }
  19. };
  20. // 具体策略:德国税率
  21. class GermanyTaxStrategy : public TaxStrategy {
  22. public:
  23.     double calculateTax(double income) override {
  24.         return income * 0.25;
  25.     }
  26. };
  27. // 上下文
  28. class IncomeCalculator {
  29. private:
  30.     std::unique_ptr<TaxStrategy> taxStrategy;
  31. public:
  32.     void setTaxStrategy(std::unique_ptr<TaxStrategy> taxStrategy) {
  33.         this->taxStrategy = std::move(taxStrategy);
  34.     }
  35.     double calculateIncomeTax(double income) {
  36.         return taxStrategy->calculateTax(income);
  37.     }
  38. };
  39. int main() {
  40.     double income = 10000;
  41.     IncomeCalculator calculator;
  42.     // 假设我们选择中国税率和美国税率
  43.     calculator.setTaxStrategy(std::make_unique<ChinaTaxStrategy>());
  44.     std::cout << "Income tax for China: " << calculator.calculateIncomeTax(income) << std::endl;
  45.     calculator.setTaxStrategy(std::make_unique<USATaxStrategy>());
  46.     std::cout << "Income tax for USA: " << calculator.calculateIncomeTax(income) << std::endl;
  47.     return 0;
  48. }
复制代码
界说一系列算法,把它们一个个封装起来,并且使它们可相互替换(变化);
该模式使得算法可独立于使用它的客户步伐(稳定) 而变化 (扩展,子类化)
if - else if 或 switch case; 通常都用计谋模式来做接口; 只有那些固定下来的条件,不会再变了可以使用
而且用switch case ,if else在运行时内存装载也会出现题目,造成内存痴肥
observe

motivation
软件构建过程中,需要为某些对象建立一种 通知依赖关系
即:一个对象(观察者)的状态发生改变,所有的依赖对象(观察者对象)都会得到通知
如果这样,依赖关系过于紧密,将使软件不能很好地抵抗变化
使用面向对象,将这种依赖关系弱化,形成一种稳定的依赖关系,从而实现软件体系结构的松耦合
新闻订阅服务为例,
  1. class NewsService {
  2. public:
  3.     void addNews(std::string news) {
  4.         // 添加新闻
  5.         for (auto user : users) {
  6.             user->notify(news); // 直接调用每个用户的notify方法
  7.         }
  8.     }
  9.    
  10. private:
  11.     std::vector<User*> users; // 紧密耦合的用户列表
  12. };
  13. class User {
  14. public:
  15.     void notify(std::string news) {
  16.         // 用户接收到新闻更新
  17.     }
  18. };
复制代码
  1. NewsService类与User类紧密耦合,如果需要添加新的用户类型或者改变通知方式,需要修改NewsService类的代码
  2. 扩展性差,如果未来有新的通知方式,例如邮件通知、短信通知等,需要在NewsService类中添加更多的代码
复制代码
通过一个抽象的接口进行交互
  1. class Subject {
  2. public:
  3.     virtual void registerObserver(Observer* observer) = 0;
  4.     virtual void removeObserver(Observer* observer) = 0;
  5.     virtual void notifyObservers(std::string news) = 0;
  6. };
  7. class Observer {
  8. public:
  9.     virtual void update(std::string news) = 0;
  10. };
  11. class NewsService : public Subject {
  12. private:
  13.     std::vector<Observer*> observers;
  14.    
  15. public:
  16.     void registerObserver(Observer* observer) override {
  17.         observers.push_back(observer);
  18.     }
  19.    
  20.     void removeObserver(Observer* observer) override {
  21.         // 移除观察者
  22.     }
  23.    
  24.     void notifyObservers(std::string news) override {
  25.         for (auto observer : observers) {
  26.             observer->update(news);
  27.         }
  28.     }
  29.    
  30.     void addNews(std::string news) {
  31.         notifyObservers(news); // 通知所有观察者
  32.     }
  33. };
  34. class User : public Observer {
  35. public:
  36.     void update(std::string news) override {
  37.         // 用户接收到新闻更新
  38.     }
  39. };
复制代码
  1. 可扩展性:可以轻松地添加新的观察者类型,例如添加一个新的User子类来处理不同类型的用户
  2. 可维护性:由于解耦,修改NewsService或User类时,对其他类的依赖更少,因此更容易维护
  3. 灵活性:可以动态地添加或移除观察者,而不需要修改NewsService类的内部实现
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

愛在花開的季節

金牌会员
这个人很懒什么都没写!

标签云

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