• 设计模式之组合模式


    题外话:昨天看到了一句话, 面向过程编程和面向对象编程。

    switch(type)
    {
       case type1: 
            // do something 
    break; case type2: //do something
         break; case type3: //do something
         break;
      default:
        break;
    }

    当dosomething的方法类似时,使用面向对象的多态似乎更加方便些。如果需要增加新的类型,也更加方便。但是如果需要对dosomething修改时,面向对象需要修改所有的子类,而面向过程只需要修改一个函数。因此,在考虑具体使用哪种时,根据自己的实际情况进行。

    下面来说组合模式:

    组合模式作为一种结构型模式,是来描述类与类之间的关系。关于组合模式,在设计模式这本书中,是这样定义的:

            将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。


    1.将对象组合成树结构。

    关于树结构,在数据结构中有详细的介绍,大体来说,树有根节点,叶子节点以及子树的根节点组成。组合模式中,也分为这三种类,位域根节点的类一般为基类,叶子节点和子树的根节点继承该基类。形成类似树的结构。

    class Component
    {
      virtual void doSomething();
    }

    class Composite : public Component
    {
      vector<Component*> list;
      virtual void doSomething();
    }

    class Leaf : public Component
    {
      virtual void doSomething();
    }

     如上,Composite 和Leaf 均为Component的子类,而Composite 还可以继续派生Leaf子类,构成树状结构。

    2.用户对单个对象和组合对象的使用具有一致性。

    学习设计模式最困惑的其实是:这个设计模式用到哪些场景?

    在网上看到一个非常好的组合模式的实际例子:

    我们通常使用测试框架编写测试用例时,无论是gTest也好或者是cppTest框架也好,都有 TestSuit和TestCase的概念,TestSuit里面往往是一系列相关的TestCase, 而在执行测试用例时,我门见到最多的其实是Test.run(). 我们完全不用关心是TestSuit.Run 还是TestCase.run().这就是组合模式的好处。

    在框架中的实现一般是这样的

    Test类: 该类有两个主要的方法: run() 和 add(Test*),后者用于添加Testsuit和TestCase对象到容器中,在run方法中,我们遍历容器内的对象进行run。

    TestSuit: 该类和Test类功能大致一样,其add方法一般添加TestCase对象到其容器中,在其run方法中,遍历其容器内的TestCase()进行run。

    TestCase:其run方法实现了真正的run动作。

    框架运行时,将TestSuit下的TestCase添加到TestSuit的容器中,将Test下的TestCase和TestSuit添加至Test的容器中,也就是说,Test基类的容器中可以获取到所有的Testcase对象。、而我们在使用框架时,不用考虑到到底是单个对象还是组合对象。

    组合模式的结构图:

     

    组合模式实例:

    class Test
    {
        virtaul void add(Test* t);
        
        virtual void Remove(Test*t);
        virtual void run();
    };
    
    class TestSuit: public Test
    {
    public:
        virtual void add(Test* t);
        virtual void Remove(Test* t);
        virtaul void run()
        {
            for i in list:
                 i.run();
         }
    private:
        vector<Test*> list;
    };
    
    class TestCase: public Test
    {
        public:
         vittual void run()
    {
        cout << "test case run";
    }
    };
    
    int main()
    {
        Test* root =  new TestSuit();
        Test*  case1 = new TestCase();
        root.add(case1);
        
        Test* suit1 =  new TestSuit();
       root.add(suit);
       Test *case2 = new TestCase()
       suit1.add(case2);
    }

     

    ~~~~~
  • 相关阅读:
    学就要学好 就要学明白
    URL的基础
    各种waf识别
    Linux命令行上的上传和下载文件命令
    Linux服务器安全加固(三)
    Linux服务器安全加固(二)
    Linux服务器安全加固(一)
    Centos7配置SNMP服务
    Windows Server 系统通用安全基线配置详细
    Windows Server 2016 部署AD域控制器及添加AD域控制器
  • 原文地址:https://www.cnblogs.com/missmzt/p/4703385.html
Copyright © 2020-2023  润新知