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);
}
}
结果:
--总公司
----财务部
----子公司
----技术部
---------------------------------------
总结:
这种改进版肯定是代码量少了,简洁了。这种写法还是启用继承,继承总公司,使所有部门知道自己来源于总公司,并且自己部门扩展了新功能。这种就是安全组合模式。