• 第十九章-组合模式


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

    图片

    基本代码

    #include<iostream>
    #include<string>
    #include<vector>
    
    using namespace std;
    
    class Component
    {
    protected:
    	string name;
    public:
    	Component(string name_t)
    	{
    		name = name_t;
    	}
    
    	virtual void Add(Component* c) = 0;
    	virtual void Remove(Component* c) = 0;
    	virtual void Display(int depth) = 0;
    };
    
    class Leaf :public Component
    {
    public:
    	Leaf(string name_t)
    		:Component(name_t)
    	{ }
    
    	void Add(Component* c)
    	{
    		cout << "Cannot add to a lead" << endl;
    	}
    
    	void Remove(Component* c)
    	{
    		cout << "Cannot remove from a lead" << endl;
    	}
    
    	void Display(int depth)
    	{
    		cout << string(depth, '-') << " " << name << endl;
    	}
    };
    
    class Composite :public Component
    {
    private:
    	vector<Component*> children;
    public:
    	Composite(string name_t)
    		:Component(name_t)
    	{ }
    
    	void Add(Component* c)
    	{
    		children.push_back(c);
    	}
    
    	void Remove(Component* c)
    	{
    		for (auto _i = children.begin(); _i != children.end(); _i++)
    		{
    			if (*_i == c)
    			{
    				children.erase(_i);
    				break;
    			}
    		}
    	}
    
    	void Display(int depth)
    	{
    		cout << string(depth, '-') << " " << name << endl;
    		for (auto _i : children)
    		{
    			_i->Display(depth + 2);
    		}
    	}
    };
    
    
    
    int main()
    {
    	Composite* root = new Composite("root");
    	root->Add(new Leaf("Leaf A"));
    	root->Add(new Leaf("Leaf B"));
    
    	Composite* comp = new Composite("Composite X");
    	comp->Add(new Leaf("Leaf XA"));
    	comp->Add(new Leaf("Leaf XB"));
    
    	root->Add(comp);
    
    	Composite* comp2 = new Composite("Composite XY");
    	comp2->Add(new Leaf("Leaf XYA"));
    	comp2->Add(new Leaf("Leaf XYB"));
    
    	comp->Add(comp2);
    
    	root->Add(new Leaf("Leaf C"));
    
    	Leaf* leaf = new Leaf("Leaf D");
    	root->Add(leaf);
    	root->Remove(leaf);
    
    	root->Display(1);
    
    
    
    	system("pause");
    	return 0;
    }
    

    透明方式与安全方式

    • 透明方式,也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等,这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它们是没有意义的。
    • 安全方式,也就是在Component接口中不去声明Add和Remove方法,那么子类的Lead也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样就不会出现上面的问题,不过由于不够透明,所以树叶和树枝类将不具备相同的接口,客户端的调用需要做相应的判断,带来了不便。

    公司管理系统

    图片

    #include<iostream>
    #include<string>
    #include<vector>
    
    using namespace std;
    
    class Company
    {
    protected:
    	string name;
    public:
    	Company(string name_t)
    	{
    		name = name_t;
    	}
    
    	virtual void Add(Company* c) = 0;
    	virtual void Remove(Company* c) = 0;
    	virtual void Display(int depth) = 0;
    	virtual void LineOfDuty() = 0;
    };
    
    class ConcreteCompany :public Company
    {
    private:
    	vector<Company*> children;
    public:
    	ConcreteCompany(string name_t)
    		:Company(name_t)
    	{ }
    
    	void Add(Company* c)
    	{
    		children.push_back(c);
    	}
    
    	void Remove(Company* c)
    	{
    		for (auto _i = children.begin(); _i != children.end(); _i++)
    		{
    			if (*_i == c)
    			{
    				children.erase(_i);
    				break;
    			}
    		}
    	}
    
    	void Display(int depth)
    	{
    		cout << string(depth, '-') << " " << name << endl;
    		for (auto _i : children)
    		{
    			_i->Display(depth + 2);
    		}
    	}
    
    	void LineOfDuty()
    	{
    		for (auto _i : children)
    		{
    			_i->LineOfDuty();
    		}
    	}
    };
    
    class HRDepartment : public Company
    {
    public:
    	HRDepartment(string name_t): Company(name_t)
    	{ }
    
    	void Add(Company* c)
    	{ }
    
    	void Remove(Company* c)
    	{ }
    
    	void Display(int depth)
    	{
    		cout << string(depth, '-') << " " << name << endl;
    	}
    
    	void LineOfDuty()
    	{
    		cout << name << " 员工招聘培训管理" << endl;
    	}
    };
    
    class FinanceDepartment : public Company
    {
    public:
    	FinanceDepartment(string name_t) : Company(name_t)
    	{ }
    
    	void Add(Company* c)
    	{ }
    
    	void Remove(Company* c)
    	{ }
    
    	void Display(int depth)
    	{
    		cout << string(depth, '-') << " " << name << endl;
    	}
    
    	void LineOfDuty()
    	{
    		cout << name << " 公司财务收支管理" << endl;
    	}
    };
    
    int main()
    {
    	ConcreteCompany* root = new ConcreteCompany("北京总公司");
    	root->Add(new HRDepartment("总公司人力资源部"));
    	root->Add(new HRDepartment("总公司财务部"));
    
    	ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
    	comp->Add(new HRDepartment("华东分公司人力资源部"));
    	comp->Add(new HRDepartment("华东分公司财务部"));
    	root->Add(comp);
    
    	ConcreteCompany* comp1 = new ConcreteCompany("南京办事处");
    	comp1->Add(new HRDepartment("南京办事处人力资源部"));
    	comp1->Add(new HRDepartment("南京办事处财务部"));
    	comp->Add(comp1);
    
    	ConcreteCompany* comp2 = new ConcreteCompany("杭州办事处");
    	comp2->Add(new HRDepartment("杭州办事处人力资源部"));
    	comp2->Add(new HRDepartment("杭州办事处财务部"));
    	comp->Add(comp2);
    
    	cout << "
    结构图:" << endl;
    	root->Display(1);
    
    	cout << "
    职责:" << endl;
    	root->LineOfDuty();
    
    	system("pause");
    	return 0;
    }
    

    组合模式可以使基本对象可以被组合成更复杂的组合对象,而这个对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
    并且用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。
    简单点说,就是组合模式让客户可以一致的使用组合结构和的单个对象。

  • 相关阅读:
    记一次线上网络问题排查
    记服务器上session设置引起的OutofMemory
    由DateFormat引起的线程安全问题
    十二周总结
    团队开发冲刺第十天
    团队开发冲刺第九天
    团队开发冲刺第八天
    团队开发冲刺第七天
    十二周总结
    团队开发冲刺第六天
  • 原文地址:https://www.cnblogs.com/wfcg165/p/12035947.html
Copyright © 2020-2023  润新知