结构型模式之组合模式(java版)

1.引入:

组合模式就是把整体与部分进行组合,组合出来的结构为树形结构。使得用户操作部分中单个对象犹如操作整体对象一样。

2.举例:

在我们工作的周围会发现稍微大点的有规模上市的公司,都会有分公司,而且还会有相应的财务部和技术部等部门。然而对于这种大部门里有小部门,小部门里有小小部门的结构,一般会一层有一个负责人,分别向上级汇报工作的。会发现不是CEO直接管理我这个小码农,而是一层层管理的。所以采用这种树形结构的设计。但是如果我们采用平行结构的设计,那么就得搞ID号标识自己的身份,要不总公司的CEO哪知道你是分公司哪个研发部的哪个小码农。所以这种平行结构的设计用在此处是不合理的。就得采用树形结构设计。然后你会发现总公司和子公司的公司结构都差不多,都由技术部和财务部,销售部等等。综合来看,就是总公司这个整体和所有的子公司组成了整体和部分的关系了。总公司的公司结构也可以用于子公司。子复用父的功能肯定就想到了继承了。

3.实现:

--3.1.总公司类:

//总公司类
public abstract class Company {
	
	protected String name;
	public Company(String name){
		this.name=name;
	}
	//添加部门
	public abstract void add(Company c);
	//删除部门
	public abstract void remove(Company c);
	//显示部门
	public abstract void display(int depth);
}
--3.2.总公司下的部门类(分公司在此树形结构 中也属于总公司的部门)

public class Department extends Company{

	private List<Company> list=new ArrayList<Company>();
	public Department(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void add(Company c) {
		// TODO Auto-generated method stub
		list.add(c);
	}

	@Override
	public void remove(Company c) {
		// TODO Auto-generated method stub
		list.remove(c);
	}

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		String tempDepartment="";
		for(int i=0;i<depth;i++){
			tempDepartment+="-";
		}
		System.out.println(tempDepartment+name);
		for(Company c:list){
			c.display(depth+2);
		}
	}

}

--3.3财务部

public class FinanceDepartment extends Company{

	public FinanceDepartment(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void add(Company c) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void remove(Company c) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		String tempDepartment="";
		for(int i=0;i<depth;i++){
			tempDepartment+="-";
		}
		System.out.println(tempDepartment+name);
	}

}

解释:由于财务部属于总公司下的子部门,属于树中的儿子节点,所以要继承总公司类,但是虽然创建了子节点,但是发现了财务部下面是不会添加子公司的,所以财务部的添加add方法和删除remove方法是多余的代码。

--3.4技术部

public class TechnologyDepartment extends Company{

	public TechnologyDepartment(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void add(Company c) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void remove(Company c) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		String tempDepartment="";
		for(int i=0;i<depth;i++){
			tempDepartment+="-";
		}
		System.out.println(tempDepartment+name);
	}


}
--3.5.子公司

public class SonCompany extends Company{

	public SonCompany(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void add(Company c) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void remove(Company c) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		String tempDepartment="";
		for(int i=0;i<depth;i++){
			tempDepartment+="-";
		}
		System.out.println(tempDepartment+name);
	}

}
解释:会发现财务部,技术部和分公司的代码相同,因为它们都属于部分,相对于总公司这个整体。然而一个公司所有的产业都是由这些部分组成的,所以当CEO要对公司发布命令时,所有的部分都会收到。所以对这种组合对象的操作,实际也相当于对每个包含的子对象(组合里面单个对象)操作是一样的。

--3.6测试类:

public static void main(String[] args) {
		Department department=new Department("总公司");
		department.add(new FinanceDepartment("财务部"));
		department.add(new SonCompany("子公司"));
		department.add(new TechnologyDepartment("技术部"));
		
		department.display(2);
}
结果

--总公司
----财务部
----子公司
----技术部

---------------------------------------------------------------------------------------------

4总结:

4.1.

组合模式应用场景:首先需求中得有部分与整体这种层次结构,忽略了组合对象和部分单个对象的不同,可以统一的使用组合结构中的对象。

4.2.

我们发现了财务部、技术部和子公司都写了add方法,实际上这些就相当于叶子节点了,就是不可能叶子生出来叶子了,财务部不可能里面还有子公司了,这种方式叫做透明组合模式,缺点自然就是写了很多没用的代码。

改进版:

就是在总公司这个整体类中不去定义抽象方法,将定义方法的权利移交到部分类中,看部分类中谁需要谁自己去定义。

4.2.1总公司类

//总公司类
public abstract class Company {
	
	protected String name;
	public Company(String name){
		this.name=name;
	}
	
}

4.2.2总公司下的部门类

public class Department extends Company{

	private List<Company> list=new ArrayList<Company>();
	public Department(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}


	public void add(Company c) {
		
		list.add(c);
	}

	
	public void remove(Company c) {
		
		list.remove(c);
	}


	public void display(int depth) {
		//打印总公司
		String tempDepartment="";
		for(int i=0;i<depth;i++){
			tempDepartment+="-";
		}
		System.out.println(tempDepartment+name);
		//打印子公司
		for(Company c:list){
			System.out.println("----"+c.name);
		}
	}

}

4.2.3财务部类

public class FinanceDepartment extends Company{

	public FinanceDepartment(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

}

4.2.4技术部类

public class TechnologyDepartment extends Company{

	public TechnologyDepartment(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

}

4.2.5子公司类

public class SonCompany extends Company{

	public SonCompany(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

}

4.2.6测试:

public class Test {

	public static void main(String[] args) {
		Department department=new Department("总公司");
		department.add(new FinanceDepartment("财务部"));
		department.add(new SonCompany("子公司"));
		department.add(new TechnologyDepartment("技术部"));
		
		department.display(2);
	}
}

结果:

--总公司
----财务部
----子公司
----技术部

---------------------------------------

总结:

这种改进版肯定是代码量少了,简洁了。这种写法还是启用继承,继承总公司,使所有部门知道自己来源于总公司,并且自己部门扩展了新功能。这种就是安全组合模式。






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值