设计模式之组合模式C++()

1. 作用

组合模式也叫合成模式,或者部分——整体模式。它作用很明显可以是你将整体和部分同等对待。
意图:将对象组合成树形结构以表示“部分——整体”的层次结构,使得用户对单个对象的使用具有一致性。

2. UML类图

组合模式有两种形式,安全模式和透明模式。


这里写图片描述
透明模式
安全模式
安全模式

  • 参与者:
  • Componet:
    为组合对象声明接口。实现所有类共有的接口行为。声明接口用于访问子部件(透明模式)。
  • Leaf:叶节点对象,无子节点。
  • Composite:定义有子部件的那些部件行为。存储子部件,实现子部件有的行为。
  • Client:客户,通过使用component操作部件对象。

透明模式和安全模式的区别:透明模式将Composite部件的增减部件的接口在Componet进行了声明。所以Leaf必须实现它,只不过是空操作或者错误提示。而安全模式将增减部件的接口放在了Composite处,这样带来的坏处是使用时客户必须直接使用Composite具体类,不是针对接口编程了。个人一般使用透明模式。

3. 实现

举例:假设你要开一家公司,要招募大量员工,当然有经理,主管,普通员工,相信再小的公司都会有这样的组织架构。经理管主管,主管又管普通员工,普通员工自己管自己。代码试下如下:
代码:


#include <iostream>
#include <string>
#include <vector>
using namespace std;


//员工:抽象对象Component
class Employee
{
public:
    Employee(string name, string job) :m_Name(name), m_Job(job){}
    virtual void add(Employee*subordinate) = 0;
    virtual void remove(Employee*subordinate) = 0;
    virtual void showMe() = 0;
protected:
    string m_Name;
    string m_Job;
};

//设计员:叶节点实现
class Designer :public Employee
{
public:
    Designer(string name, string job) :Employee(name, job){}

    virtual void add(Employee*subordinate)
    {
        cout << "我是小员工,管理不了人!" << endl;
    }

    virtual void remove(Employee*subordinate)
    {
        cout << "我是小员工,没人归我管理!" << endl;
    }

    virtual void showMe()
    {
        cout << "姓名:" << m_Name << "--" << "职位:" << m_Job << endl;;
    }
};

//主管或经理:枝节点实现
class Manger :public Employee
{
public:
    Manger(string name, string job) :Employee(name, job){}

    //添加子节点
    void add(Employee *subordinate)
    {
        m_Subordinates.push_back(subordinate);
    }

    //删除子节点
    void remove(Employee *subordinate)
    {
        vector<Employee*>::iterator it = m_Subordinates.begin();
        while (it != m_Subordinates.end()) 
        {
            if (*it == subordinate)
            {
                m_Subordinates.erase(it);
                delete subordinate;
                subordinate = NULL;
                break;
            }
            ++it;
        }
    }

    //显示自己及手下
    virtual void showMe()
    {
        cout << "姓名:" << m_Name << "--" << "职位:" << m_Job << endl;
        cout << m_Name << "手下有:";
        //显示子节点
        vector<Employee*>::iterator it = m_Subordinates.begin();
        while (it != m_Subordinates.end())
        {
            (*it)->showMe();
            ++it;
        }
    }  
private:
    vector<Employee*>m_Subordinates;
};



//场景
int main()
{
    //招收员工,从上到下
    Employee *manager = new Manger("小强", "经理");
    Employee *supervisor = new Manger("小明", "主管");
    Employee *supervisor1 = new Manger("小英", "主管");
    Employee *staff1 = new Designer("小李", "设计员");
    Employee *staff2 = new Designer("小王", "设计员");


    //组织公司架构
    manager->add(supervisor);
    manager->add(supervisor1);
    supervisor->add(staff1);
    supervisor1->add(staff2);

    manager->showMe();

    staff2->add(manager);

    return 0;
}
结果:
姓名:小强--职位:经理
小强手下有:姓名:小明--职位:主管
小明手下有:姓名:小李--职位:设计员
姓名:小英--职位:主管
小英手下有:姓名:小王--职位:设计员
我是小员工,管理不了人!
请按任意键继续. . .


4. 优缺点

优点:高层模块调用简单,对于调用者来说,整体和局部无区别。
扩展容易,节点增减非常自由
缺点:如果你使用安全模式,那么客户不得不面对具体实现类,限制了接口的影响范围。

5. 使用场景

存在部分——整体关系的场景,或树形关系的系统。例如文件、菜单系统等。

6. 总结

存在树形结构,且层次较多,请使用组合模式。

猜你喜欢

转载自blog.csdn.net/a369189453/article/details/81193415
今日推荐