【软件设计师中级】设计模式之组合学习笔记(c++)

本文详细介绍了设计模式中的组合模式,包括其意图、结构和适用性。通过UML图解析,展示了如何用C++实现一个树形结构的组合模式,以及如何通过递归操作遍历并执行所有子节点的方法。在代码实现中,创建了一个总公司及其下属分公司和部门的层次结构,展示了如何添加、删除和操作这些节点。递归调用使得用户可以统一地处理单个对象和组合对象,实现部分-整体的层次操作。
摘要由CSDN通过智能技术生成

1、composite

(1)意图

      将对象组合成树状态以表示“部分-整体”的层次结构。composite使得用户对单个对象和组合对象的使用具有一执行。

(2)结构

component为组合对中申明的接口,在适当的情况实现所有类共有接口的默认行为,声明一个接口用于访问管理componet的子组件,可选在递归结构中定义一个接口访问父组件,用于访问一个父组件,并在合适的情况下实现他。

leaf在组合中表示叶结点对象,叶结点没有子结点;在组合中定义图对象的行为。

composite定义有子组件的那些组件行为;存储子组件;在component接口实现与子组件有关的操作

client通过component接口操作组合对象的对象。

(3)适用性

想表示对象的部分-整体层次结构。

希望用户忽略组合对象与单个对象的不同,用户将统一的使用组合结构中的所有对象。

2、根据UML图写代码

 

1、泛华关系

从结构上来看 componet是leaf和composite的父类

2、关联关系

composite为compnet的关联关系(特殊关联 ——聚合),既在composite定义一个指向componet的指针。

3、备注

根据备注的解释,operatiaon方法解释 是要执行所有子类的operation

4、UML图的理解

   通过client构建一个composite对象,通过Add增加一个“component*”类型的的结点并顺序的存在一个链表中构建一个树形结构,通过operation方法实现递归并执行子结点全部operation实现遍历并完成对应的功能。同时每一个composite都有一个专属的leaf

3、代码实现

由于时间问题为涉及析构部分,若有兴趣可自行完成。

include<iostream>
#include<list>
using namespace std;
class composite;
class componet{
    public:
        virtual void add(componet* p)=0;
        virtual void remove( componet* p)=0;
        virtual void getchild(int)=0;
        virtual void operation()=0;
        string name;
};
class composite:public componet{
    public:
        composite(string name){
            this->name=name;

        }
        void add(componet *p){
            mylist.push_back(p);       
        }
        void remove(componet *p){ 
            mylist.remove(p); 
        }
        void getchild(int p){

        }
        void operation(){
            list<componet*>::iterator it;
            cout<<this->name<<endl;
            for(it=mylist.begin();it!=mylist.end();it++){            
                (*it)->operation();//递归方式调用 
            }
        }
    private:
        list<componet*> mylist;//以list实现树形结构,并提供一个componet* 指针合计形成指向一个componet*的聚合特殊关联关系
};


class leaf:public componet{
    public:
        leaf (string name){
            this->name=name;
        }
        void add(componet *p){

        }
        void remove(componet *p){

        }
        void getchild(int p){

        }
        void operation(){
            cout<<this->name<<endl;
        }

};
int main(){
    componet *a=new composite("总公司");//生产a结点
    a->add(new leaf("总公司旗下个部门"));//将leaf放入list中
    componet *b=new composite("分公司A");
    a->add(b);//b放入list a的序列
    b->add(new leaf("分公司A旗下各部门"));在b下面放一个list列表并存有leaf表
    componet *c=new composite("分公司B");
    a->add(c);
    c->add(new leaf("分公司B旗下各部门"));
    a->operation();
    a->remove(b);
    cout<<"---------------------"<<endl;
    a->operation();
    return 0;
}

代码实现

 ./a.out
总公司
总公司旗下个部门
分公司A
分公司A旗下各部门
分公司B
分公司B旗下各部门
---------------------
总公司
总公司旗下个部门
分公司B
分公司B旗下各部门
 
4、递归实现的过程

如果我们把代码中的a看中根结点(root)在list 下面链接过程是这样的:

a->b->c

对应的代码如下:

a->add(b)

a->add(c)

但是在结点b和c下面都各自的list结点l对应代码为:

 b->add(new leaf("分公司A旗下各部门"))

 c->add(new leaf("分公司 B旗下各部门"))

那么在b和c属于自己的list表中结构如下:

b->leaf

c->leaf

如果我们单存是循环root而不递归的话

   for(it=mylist.begin();it!=mylist.end();it++){            
               cout<<(*it)->name<<endl
            }

输出的结果就只有:
总公司旗下个部门
分公司A
分公司B
我们会发现分公司下的各部门不在显示,因为我们这里并没有让b结点去调用属于他自己的list表,如果我们要实现b也执行他自己list表则必须使用递归函数对应代码为:

   for(it=mylist.begin();it!=mylist.end();it++){            
                (*it)->operation();//递归方式调用 
            }

具体过程

第一次 i  it=mylist.begin=a.leaf()  it=a.leaf()     a.leaf()->operation()实现效果  总公司分公司 i++后没有数据了 进入下一层循环

第二次 it++后  it=b    b-> operation()实现效果       分公司A 

第三次 it++后 注意这里进入b的链表  it=mylist.begin=b.leaf()   b.leaf()->operation()实现效果 分公司A  i++后面没有相关的数据了,b的list循环结束进入下一层既c

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值