首页 > 其他分享 >组合模式

组合模式

时间:2022-09-18 14:45:55浏览次数:69  
标签:组合 Company 模式 Add virtual new void

理论

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

 

 透明方式与安全方式

透明方式:在 Leaf 类当中也有 Add 和 Remove 方法。这种方式叫做透明方式,在 Compoment 中声明所有用来管理子对象的方法,其中包括 Add、Remove 等。这样实现 Component 接口的所有子类都具备了 Add 和 Remove。这样做的好处就是叶节点和枝结点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为 Leaf 类本身不具备 Add()、Remove() 方法的功能,所以实现它是没有意义的。

安全方式:在 Leaf 类当中不用 Add 和 Remove方法。在 Component 接口中不去声明 Add 和 Remove 方法,那么子类的 Leaf 就不需要去实现它,而是在 Composite 声明所有用来管理子类对象的方法,这样就不会出现透明方式中的问题。不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不变。

组合模式的应用场景

  1. 当需求中是体现部分与整体层次的结构时

  2. 希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中地所有对象时

组合模式的优点

组合模式定义包含了基本对象和组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象。

因此用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就不需要为定义组合而写一些选择判断语句。

组合模式让客户可以一致地使用组合结构和单个对象。

实例

模拟公司管理系统如下图

 特征:整体与部分可以被一致对待

UML类图

 代码实现

#include <iostream>
#include <list>
using namespace std;

//公司类 (抽象类) 
class Company {
public:
	Company(string _name) :name(_name) {}
	virtual void Add(Company* c) = 0; //增加
	virtual void Remove(Company* c) = 0; //移除
	virtual void Display(int depth) = 0; //显示
	virtual void LineOfDuty() = 0; //旅行职责

protected:
	string name;
};

//其他公司类 实现接口 树枝结点
class ConcreteCompany : public Company{
public:
	ConcreteCompany(string _name) :Company(_name) {}
	virtual void Add(Company* c){
		children.push_back(c);
	}
	void Remove(Company* c) {
		children.remove(c);
	}
	virtual void Display(int depth) {
		string  s(depth, '-');
		cout << s << name << endl;
		for (list<Company*>::iterator it = children.begin(); it != children.end(); it++) {
			(*it)->Display(depth + 2);
		}
	}
	virtual void LineOfDuty() {
		for (list<Company*>::iterator it = children.begin(); it != children.end(); it++) {
			(*it)->LineOfDuty();
		}
	}

private:
	list<Company*> children;
};

//人力资源部与财务部类 树叶结点
class HRDepartment : public Company {
public:
	HRDepartment(string _name) :Company(_name) {}
	virtual void Add(Company* c) {}
	virtual void Remove(Company* c) {}
	virtual void Display(int depth) {
		string  s(depth, '-');
		cout << s << name << endl;
	}
	virtual void LineOfDuty() {
		cout << name << "  员工招聘培训管理" << endl;
	}
};

//财务部
class FinanceDepartment : public Company {
public:
	FinanceDepartment(string _name) :Company(_name) {}
	virtual void Add(Company* c) {}
	virtual void Remove(Company* c) {}
	virtual void Display(int depth) {
		string  s(depth, '-');
		cout << s << name << endl;
	}
	virtual void LineOfDuty() {
		cout << name << "  公司财务收支管理" << endl;
	}
};

//客户端调用
int main()
{
	ConcreteCompany* root = new ConcreteCompany("北京总公司");
	root->Add(new HRDepartment("总公司人力资源部"));
	root->Add(new FinanceDepartment("总公司财务部"));
	
	ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
	comp->Add(new HRDepartment("华东分公司人力资源部"));
	comp->Add(new FinanceDepartment("华东分公司财务部"));
	root->Add(comp);

	ConcreteCompany* comp1 = new ConcreteCompany("南京办事处");
	comp1->Add(new HRDepartment("南京办事处人力资源部"));
	comp1->Add(new FinanceDepartment("南京办事处财务部"));
	comp->Add(comp1);

	ConcreteCompany* comp2 = new ConcreteCompany("杭州办事处");
	comp2->Add(new HRDepartment("杭州办事处人力资源部"));
	comp2->Add(new FinanceDepartment("杭州办事处财务部"));
	comp->Add(comp2);

	cout << "结构图:" << endl;
	root->Display(1);
	cout << endl;

	cout << "职责:" << endl;
	root->LineOfDuty();

	delete root;
	delete comp;
	delete comp1;
	delete comp2;

	system("pause");
	return 0;
}

 

标签:组合,Company,模式,Add,virtual,new,void
From: https://www.cnblogs.com/kyzh-lhl/p/16704525.html

相关文章

  • 商业模式定义
    商业模式是指企业为了实现其客户价值的最大化,把能使企业运行的内部资源和外部相关要素进行有效的整合,形成一个完整,高效率的,具有独特核心竞争力的企业运行系统,并通过最有的......
  • 单例模式
    单例模式就是只有一个对象饿汉式1、将构造器私有化2、在类中直接创建一个私有对象(static)3、向外暴露一个静态公共方法,返回对象  懒汉式1.将构造器私有化2、......
  • JAVA设计模式-工厂模式
    JAVA设计模式-工厂模式简单工厂模式介绍简单工厂模式就是定义一个工厂类,工厂类提供获取实例的方法,方法会根据传入的参数不同来返回不同的实例。不同的实例基本都有共同......
  • 适配器模式
    Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。该角色把其他类转换为我们期望的接口Adapter(适配器类):将被适配者和目标接口组合......
  • MVC,大家都知道的模式……不太好
    MVC,大家都知道的模式……不太好“MVC是引用最多(也是最错误引用)的模式之一”——MartinFowlerCréditphoto:史蒂夫·约翰逊与许多关于这个主题的文章和评论相反,......
  • Jmeter远程服务模式运行时引用csv文件的路径配置
    问题在使用jmeter过程中,本机的内存等配置不足,启动较多的线程时,可以采用分布式运行。在分布式运行的时候,jmeter会自动将脚本从master主机发送到remote主机上,所以不需要考......
  • 设计模式
    1.单例模式-饿汉实现步骤:1.构造器私有化。2.类的内部创建对象。3.向外暴漏一个静态的公共方法。getInstance使用场景:publicclassFindGirlFriend{//......
  • js工厂模式和构造函数
    <!DOCTYPEhtml><html><head> <title>工厂模式和构造函数</title> <metacharset="utf-8"></head><body> <scripttype="text/javascript">//工厂模式跟构造函数//在js中......
  • 第 30 题:两个数组合并成一个数组
    请把两个数组['A1','A2','B1','B2','C1','C2','D1','D2']和['A','B','C','D'],合并为['A1','A2','A',......
  • 简单工厂模式
    简单工厂模式工厂接口packagesimpleFactorytypedrinkinterface{show()}咖啡对象packagesimpleFactorytypecoffeestruct{}func(c*coffee)show()......