S11 组合模式

2022-01-23  本文已影响0人  拂去尘世尘

组合模式

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。 -- 百度百科

组合模式能够体现各个对象之间的层次关系,将所有对象设计为同一种类型,从而忽略组合与个体的差异,统一管理起来。

意义

组合模式将所有的对象统一管理,并按照树形排列起来。用户能够按照结构顺序来查询指定位置的对象属性。

应用场景

  1. 公司的结构顺序。公司存在多个部门,部门内又存在多个小组,小组内存在多个成员。
  2. 特殊类型的文件操作。类似于Xml类型的文本类型,其内部需要实现指定节点的增、删、改、查功能。

场景

设计一套层次关系,实现指定位置插入、删除节点的操作。

类图

组合模式

效果

客户端接口

//                      root
//                  /    \     \
//                 /      \     \
//               branch1 branch2 leaf
//              /   \         \
//             /     \         \
//        branch1_1  leaf1_1  leaf2_1

int main(int argc, char *argv[])
{
    CTrunk theRoot("root");
    CTrunk theBranch1("branch1");
    CTrunk theBranch2("branch2");
    CTrunk theBranch1_1("branch1_1");
    CLeaf  theLeaf("leaf");
    CLeaf  theLeaf1_1("leaf1_1");
    CLeaf  theLeaf2_1("leaf2_1");

    theBranch1.Add(&theBranch1_1);
    theBranch1.Add(&theLeaf1_1);

    theBranch2.Add(&theLeaf2_1);

    theRoot.Add(&theBranch1);
    theRoot.Add(&theBranch2);
    theRoot.Add(&theLeaf);


    theRoot.ShowAllBranch(&theRoot);
    //theRoot.ShowBranch();
    return 0;
}

输出

branch1 branch1_1 leaf1_1 
branch2 leaf2_1 
leaf 

具体实现

基类接口
定义对外接口,包括增加、删除节点接口。

class CTree
{
public:
    CTree(): mParent(0), mFirstChild(0), mLastChild(0), mPrev(0), mNext(0)
    {}
    
    virtual ~CTree() 
    {}

    virtual CTree* Add(CTree *pNode);

    virtual int Remove(CTree *pNode);

    virtual string GetName();

    virtual bool IsTrunk() const;

    CTree *mParent;

    CTree *mFirstChild;
    CTree *mLastChild;

    CTree *mPrev;
    CTree *mNext;
};

叶子类
叶子类无需增加子节点。

class CLeaf 
{
public:
    explicit CLeaf(string Name);

    ~CLeaf();

    string GetName();

private:
    string mName;
};

枝干类
枝干类需要实现增加节点接口,通过链表将各个节点连接起来。

class CTrunk : public CTree
{
public:
    explicit CTrunk(string Name);

    ~CTrunk();
    
    CTree* Add(CTree *pNode);

    int Remove(CTree *pNode);

    string GetName();

    bool IsTrunk() const;

    void ShowBranch();

    void ShowAllBranch(CTree *p);

private:
    string mName;
};

枝干类增加节点。每个枝干类内部维护一套双向链表,用于维护当前类增加的节点。

CTree* CTrunk::Add(CTree *pNode)
{
    if (NULL == pNode) {
        return 0;
    }

    if (mLastChild) {
        pNode->mNext = 0;
        pNode->mPrev = mLastChild;
        mLastChild->mNext = pNode;
        mLastChild = pNode;
    }
    else {
        mFirstChild = mLastChild = pNode;
        pNode->mPrev = 0;
        pNode->mNext = 0;
    }

    pNode->mParent = this;
    return pNode;
}

总结

上一篇下一篇

猜你喜欢

热点阅读