题外话:昨天看到了一句话, 面向过程编程和面向对象编程。
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); }