zoukankan      html  css  js  c++  java
  • C++ 设计模式--模板模式、策略模式、观察者模式

    现代软件设计特征:需求频繁变化

    设计模式的要点是“寻找变化点”,在变化点应用设计模式,从而更好的应对需求变化。

    1、 Template Method

    在软件构建结构中,往往他有整体的稳定结构,但是各个子步骤确有变化的需求,或者因为固有的原因(比如框架和应用之间)而无法和任务的整体结构同时实现。
    这个时候往往使用Template Method方法。

    定义一个操作中算法的骨架(稳定),而将一些步骤延迟(变化)到子类(父类定义虚函数,在子类中具体实现)。使得子类可以不改变(复用)一个算法的结构即

    可重定义override该算法的某些特定步骤。让框架调用应用程序而不是应用程序调用框架。“不要调用我让我来调用你”,晚绑定和早绑定的区别。

    UML类图:

    代码实例:

    
    class Library {//稳定的数据结构,不会发生改变
      public:
        void step1() {}
        int step2() { return contrl;}
        void virtual step3() {}
        void step4() {}
        void virtual step5() {}
        
        void run() {
          step1();
          if(step2()) {
            step3();
          }   
          else {
            step5();
          }   
    
          for(int i = 10; i < 100; ++i) {
            step4();
          }   
        }   
        
        virtual ~Library() {}; 
    
        std::string name = "myname";
    };
    
    class Application1 : public Library {//  承载着不断变化的需求
      public:
        void step3() override { std::cout << this->name << std::endl; }
        void step5() override { std::cout << this->Library::name << std::endl; }
        std:: string name = "Application";
    };
    
    class Application2 : public Library {//  承载者不断变化的需求
      public:
        void step3() override {}
        void step5() override {}
    }; 
    
     
    int main() {
     Library *a = new Application1;
     a->run();
     delete a;
      return 0;
    }
        
    

    2、 策略模式(Strategy)

    在软件构建的过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中去,将会使得对象变得异常复杂,而且有时候支持几乎不使用的算法也是一种性能负担。

    问题:如何在运行的时候根据需要透明的改变算法? 将算法与对象本身解耦合,从而避免上述问题?
    定义:定义一系列算法,将他们一个个封装起来,而且他们可以相互替换(变化)。该模式使得算法可以独立于使用他们的应用程序(稳定)而变化(扩张,子类化)

    UML类图:

    代码实例:

    class Strategy {
    public:
      virtual int doOperation(int num1, int num2) {} // 基类中需要改写的方法
      virtual ~Strategy(){}
    };
    
    class plus final : public Strategy {// 不同的策略
    public:
      int doOperation(int num1, int num2) {
        return num1 + num2;
      }
    };
    
    class multipl final : public Strategy {
    public:
      int doOperation(int num1, int num2) {
        return num1 * num2;
      }
    };
    
    class minus final : public Strategy {
    public:
      int doOperation(int num1, int num2) {
        return num1 - num2;
      }
    };
    
    class Context { //封装调用接口
    public:
      Context(Strategy *init) :stra(init) {}
      int run(int num1, int num2) {
        return this->stra->doOperation(num1, num2);
      }
    private:
      Strategy *stra;
    };
    
     
    int main() {
    Context demo(new multipl);
    std::cout << demo.run(10, 20) << std::endl; //使用调用接口中的基类指针多态的执行。
      return 0;
    }
    
    

    3、 观察者模式(Observer)

    一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
    一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
    一个对象必须通知其他对象,而并不知道这些对象是谁。

    定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    UML类图:

    代码示例:

    enum class msg {
      RETURN1,
      RETURN2,
      RETURN3
    };
    
    class Observer {
      public:
        void virtual update(msg ms) = 0;
    };
    
    class ob1 : public Observer {
      public:
        void update(msg ms) {
          switch(ms) {
            case msg::RETURN1 :
            case msg::RETURN2 :
            case msg::RETURN3 :
              std::cout << "RETURN1" << std::endl;
            default:
              std::cout << "right" << std::endl;
          }
        }
    };
    
    class ob2 : public Observer {
      public:
        void update(msg ms) {
          switch(ms) {
            case msg::RETURN1 :
            case msg::RETURN2 :
            case msg::RETURN3 : {
              std::cout << "RETURN2" << std::endl;
              break;
            }
            default:
              std::cout << "erro ms2" << std::endl;
          }
        }
    };
    
    class ob3 : public Observer {
      public:
        void update(msg ms) {
          switch(ms) {
            case msg::RETURN1 :
            case msg::RETURN2 :
            case msg::RETURN3 : {
                std::cout << "RETURN3" << std::endl;
                break;
              }
            default:
              std::cout << "erro ms3" << std::endl;
          }
        }
    };
    
    class subject {
      public:
        void addob(Observer *ob) { obs.insert(ob);}
        void removeob(Observer *ob) {
          auto rob = obs.find(ob);
          if(rob != obs.end()){
            obs.erase(ob);
          }
          else std::cout << "erro no matching observer" << std::endl;
        }
        void update() {
          for(auto& ob : obs) {
            ob->update(ms);
          }
        }
    
        msg ms;
        std::set<Observer*> obs;
    };
    
    int main() {
     Observer *ob_1 = new ob1;
     Observer *ob_2 = new ob2;
     Observer *ob_3 = new ob3;
     subject *sub = new subject;
     sub->ms = msg::RETURN1;
     sub->addob(ob_1);
     sub->addob(ob_2);
     sub->addob(ob_3);
     sub->update();
     return 0;
    }
    
    
    

    observer:变化尽量通过调用方的多态机制,传递给被调用方,决定如何调用。

  • 相关阅读:
    【知识强化】第六章 查找 6.4 散列(Hash)表
    【知识强化】第七章 排序 7.5 归并排序和基数排序
    【知识强化】第六章 查找 6.3 B树和B+树
    【知识强化】第五章 图 5.4 图的应用
    【知识强化】第五章 图 5.3 图的遍历
    linux的自启动服务脚本的(/etc/rc.d/init.d或者其链接/etc/init.d)
    shell文件包含
    shell输入输出重定向
    shell函数参数
    shell函数
  • 原文地址:https://www.cnblogs.com/Smarc/p/13970495.html
Copyright © 2011-2022 走看看