23设计模式——组合模式

目录

组合(Composite)模式

适用场景

UML图

安全模式和透明模式

透明方式

安全方式

真实的组合模式

优缺点

实例——公司人员


组合(Composite)模式

本质:统一叶子对象和组合对象

组合模式也叫部分-整体模式。组合模式将对象组织到结构中,可以用来描述整体与部分的关系,可以使客户端将单纯元素与复合元素同等看待。

适用场景

  • 树形结构。
  • 需求中是体现部分与整体的结构。

让客户端统一操作组合对象和叶子对象,不再区分二者。如树形菜单、文件和文件夹管理,读XML文件等。

UML图(透明方式)

抽象构件(Component)角色:
给参与组合的对象规定共有方法和属性
树叶构件(Leaf)角色:
树叶对象,没有下级子对象。
树枝构件(Composite)角色:
树枝对象,有下级子对象,并实现Component类中规定的方法。

public abstract class Component {
	protected String name;
	
	public Component(String name) {
		super();
		this.name = name;
	}
	public abstract void add(Component c);
	public abstract void remove(Component c);
	public abstract void display(int depth);
	
}
import java.util.ArrayList;

public class Composite extends Component{
	private ArrayList<Component> children=new ArrayList<Component>();
	
	public Composite(String name) {
		super(name);
	}

	@Override
	public void add(Component c) {
		children.add(c);
	}

	@Override
	public void remove(Component c) {
		children.remove(c);
	}

	@Override
	public void display(int depth) {
		System.out.println(depth+name);
		for(Component component :children){
			component.display(depth+1);
		}
	}
}
public class Leaf extends Component{

	public Leaf(String name) {
		super(name);
	}

	@Override
	public void add(Component c) {
		//空实现,抛出一个"不支持请求"异常
		throw new UnsupportedOperationException();
	}

	@Override
	public void remove(Component c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void display(int depth) {
		System.out.println(depth+name);
	}
	
}
public class Main {

	public static void main(String[] args) {
		//根节点
		Composite root=new Composite("root");
		//树枝
		Composite b1=new Composite("branch1");
		Leaf y1=new Leaf("leaf1");
		Leaf y2=new Leaf("leaf2");
		root.add(b1);
		b1.add(y1);
		b1.add(y2);
		root.display(0);
	}

}

安全模式和透明模式

组合模式的实现根据所实现接口的区别分为两种形式:安全模式和透明模式。

组合模式必须在合适的地方提供子对象的管理方法,如:add、remove、display等。

透明方式

抽象类Component声明所有用来管理子类对象的方法,包括add,emove,display等,通过getChildren的返回值确认是叶子节点还是树枝节点

优点:树叶和树枝类有相同的接口。

树叶对象与树枝对象的区别起码在接口层次上消失了,客户端可以同等的对待所有的对象。

缺点:不够安全。

但树枝对象和叶子对象本质上是有区别的,叶子没有子对象,因此add,remove,display等方法没有意义,如果叶子生成子对象在编译时期不会出错,而会在运行时出错。

安全方式

Composite类里面声明所有的用来管理子类对象的方法

优点:安全。把树枝节点和树叶节点彻底分开,叶子没有管理子类对象的方法。

缺点:不够透明,树叶类和树枝类将具有不同的接口。

真实的组合模式

在项目中使用关系型数据库来存储这些信息。要求从数据库中直接提取出哪些人要分配到树枝,哪些人要分配到树叶,树枝与树枝、树叶的关系等。

 这张表定义了一个树形结构,我们要做的就是从数据库中把它读取出来,然后展现到前台上,用for循环加上递归就可以完成这个读取。用了数据库后,数据和逻辑已经在表中定义好了,我们直接读取放到树上就可以了。

优缺点

优点:

  • 简化了客户端调用。一棵树形机构中的所有节点都是Component,统一了组合对象和叶子对象。
  • 容易扩展。如果想增加一个树枝节点、树叶节点,只要找到它的父节点就成。

缺点:

  • 需要检测组件类型的时候,不能依靠编译期完成,必须在运行期间检测
  • 直接使用了实现类,与依赖倒置原则冲突

实例——公司人员

public abstract class Company {
	protected String name;
	protected String pos;
	
	
	public Company(String name, String pos) {
		super();
		this.name = name;
		this.pos = pos;
	}	
	
	public abstract void add(Company c);
	public abstract void remove(Company c);
	public abstract void display(int depth);
}
package com.oa;

import java.util.ArrayList;
import java.util.List;

import com.test.Component;

public class ConcreteCompany extends Company{
	public ConcreteCompany(String name, String pos) {
		super(name, pos);
	}

	private List<Company> children=new ArrayList<Company>();
	
	
	@Override
	public void add(Company c) {
		children.add(c);
	}

	@Override
	public void remove(Company c) {
		children.remove(c);
	}

	@Override
	public void display(int depth) {
		System.out.println(depth+":"+name+","+pos);
		for(Company company :children) {
			company.display(depth+1);
		}
	}
	
}
package com.oa;

public class Leaf extends Company{

	public Leaf(String name, String pos) {
		super(name, pos);
	}

	@Override
	public void add(Company c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void remove(Company c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void display(int depth) {
		System.out.println(depth+":"+name+","+pos);
	}
	
}
package com.oa;

public class Main {

	public static void main(String[] args) {
		ConcreteCompany root=new ConcreteCompany("李华","CEO");
		ConcreteCompany b1=new ConcreteCompany("张三","经理");
		ConcreteCompany b2=new ConcreteCompany("小红","经理");
		Leaf y1=new Leaf("李四","员工");
		Leaf y2=new Leaf("王五","员工");
		Leaf y3=new Leaf("王明","员工");
		root.add(b1);
		b1.add(y1);
		b1.add(y2);
		root.add(b2);
		b2.add(y3);
		root.display(0);
	}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值