组合模式
UML结构图
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/59ae29447a13fcbab21ad6f83307f651.jpeg)
范例
/**
* 为组合的对象声明接口,在适当的情况下,实现所有类共有接口的默认行.
* 声明一个接口用于访问和管理Component的子部件.
*/
public abstract class Component {
public String name;
public Component(String name) {
this.name = name;
}
public abstract void add(Component component);
public abstract void remove(Component component);
public abstract void desplay(int depth);
@Override
public String toString() {
return "Component{" +
"name='" + name + '\'' +
'}';
}
protected String getDepthString(int depth){
StringBuilder sb = new StringBuilder();
for (int i = 0; i <depth ; i++) {
sb.append("-");
}
return sb.toString();
}
}
/**
* 定义直节点行为,用来存储子部件
* 实现Component接口定义的子部件有关的行为,如add remove
*/
public class Composite extends Component{
private List<Component> mComponents=new ArrayList<>();
public Composite(String name) {
super(name);
}
@Override
public void add(Component component) {
mComponents.add(component);
}
@Override
public void remove(Component component) {
mComponents.remove(component);
}
@Override
public void desplay(int depth) {
Log.d("meee", getDepthString(depth)+name);
for(Component component:mComponents){
component.desplay(depth+2);
}
}
}
/**
* 在组合中表示叶节点,没有子节点
*/
public class Leaf extends Component{
public Leaf(String name) {
super(name);
}
@Override
public void add(Component component) {
Log.d("meee", "cannot add to a leaf");
}
@Override
public void remove(Component component) {
Log.d("meee", "cannot remove from a leaf");
}
@Override
public void desplay(int depth) {
Log.d("meee", ""+getDepthString(depth)+name);
}
}
//客户端调用
Component root=new Composite("root");
root.add(new Leaf("根叶子1"));
root.add(new Leaf("根叶子2"));
Component component1=new Composite("分支1");
component1.add(new Leaf("分支1叶子1"));
component1.add(new Leaf("分支1叶子2"));
root.add(component1);
Component component2=new Composite("分支2");
component2.add(new Leaf("分支2叶子1"));
component2.add(new Leaf("分支2叶子2"));
Composite 分支2的分支 = new Composite("分支2的分支");
分支2的分支.add(new Leaf("分支2的分支的叶子1"));
分支2的分支.add(new Leaf("分支2的分支的叶子2"));
分支2的分支.add(new Leaf("分支2的分支的叶子3"));
component2.add(分支2的分支);
root.add(component2);
Leaf removeLeaf = new Leaf("被风吹走的叶子");
root.add(removeLeaf);
root.remove(removeLeaf);
root.desplay(1);
04-10 14:51:08.446 28647-28647/? D/meee: -root
04-10 14:51:08.446 28647-28647/? D/meee: ---根叶子1
04-10 14:51:08.446 28647-28647/? D/meee: ---根叶子2
04-10 14:51:08.446 28647-28647/? D/meee: ---分支1
04-10 14:51:08.446 28647-28647/? D/meee: -----分支1叶子1
04-10 14:51:08.446 28647-28647/? D/meee: -----分支1叶子2
04-10 14:51:08.446 28647-28647/? D/meee: ---分支2
04-10 14:51:08.447 28647-28647/? D/meee: -----分支2叶子1
04-10 14:51:08.447 28647-28647/? D/meee: -----分支2叶子2
04-10 14:51:08.447 28647-28647/? D/meee: -----分支2的分支
04-10 14:51:08.447 28647-28647/? D/meee: -------分支2的分支的叶子1
04-10 14:51:08.447 28647-28647/? D/meee: -------分支2的分支的叶子2
04-10 14:51:08.447 28647-28647/? D/meee: -------分支2的分支的叶子3
组合模式的两种实现方式
/**
* 组合模式的两种实现方式:
* 1.透明方式
* 实现Component接口的所有子类都具备了add() remove().
* 好处是叶子节点和枝节点对于外部而言没有区别,他们具备完全相同的接口
* 坏处是叶子节点的add() remove()实际是没有意义的
* 2.安全方式
* 在Component接口中不声明add() remove()方法
* 好处是安全
* 坏处是客户端需要负担对不同的类型进行判断
*/
公司管理系统范例
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/75587315f674c784a4a47f7a58907b8b.jpeg)
public abstract class Company {
protected String name;
public Company(String name) {
this.name = name;
}
public abstract void remove(Company company);
public abstract void add(Company company);
public abstract void display(int depth);
public abstract void lineDuty();
protected String getDepthString(int depth){
StringBuilder sb = new StringBuilder();
for (int i = 0; i <depth ; i++) {
sb.append("-");
}
return sb.toString();
}
}
public class ConcreteCompany extends Company {
private List<Company> mCompanies=new ArrayList<>();
public ConcreteCompany(String name) {
super(name);
}
@Override
public void remove(Company company) {
mCompanies.add(company);
}
@Override
public void add(Company company) {
mCompanies.add(company);
}
@Override
public void display(int depth) {
Log.d("meee", getDepthString(depth)+"|"+name);
for (Company company:mCompanies){
company.display(depth+2);
}
}
@Override
public void lineDuty() {
Log.d("meee", name+"号召好好工作");
for (Company company:mCompanies){
company.lineDuty();
}
}
}
public class FinanceDepatrment extends Company{
public FinanceDepatrment(String name) {
super(name);
}
@Override
public void remove(Company company) {
}
@Override
public void add(Company company) {
}
@Override
public void display(int depth) {
Log.d("meee", getDepthString(depth)+"|"+name);
}
@Override
public void lineDuty() {
Log.d("meee", name+"开始计算公司的收人和支出");
}
}
public class HrDepartment extends Company {
public HrDepartment(String name) {
super(name);
}
@Override
public void remove(Company company) {
}
@Override
public void add(Company company) {
}
@Override
public void display(int depth) {
Log.d("meee", getDepthString(depth)+"|"+name);
}
@Override
public void lineDuty() {
Log.d("meee", name+"的HR开始招人");
}
}
Company mainCompany=new ConcreteCompany("母公司");
mainCompany.add(new FinanceDepatrment("总公司财务部"));
mainCompany.add(new HrDepartment("总公司人力资源部"));
Company GdCompany=new ConcreteCompany("广东分公司");
GdCompany.add(new HrDepartment("广东分公司人力资源部"));
GdCompany.add(new FinanceDepatrment("广东分公司财务部"));
mainCompany.add(GdCompany);
Company ShCompany=new ConcreteCompany("上海分公司");
ShCompany.add(new HrDepartment("上海分公司人力资源部"));
ShCompany.add(new FinanceDepatrment("上海分公司财务部"));
mainCompany.add(ShCompany);
Company BgCompany=new ConcreteCompany("北京分公司");
BgCompany.add(new HrDepartment("北京分公司人力资源部"));
BgCompany.add(new FinanceDepatrment("北京分公司财务部"));
mainCompany.add(BgCompany);
mainCompany.display(1);
mainCompany.lineDuty();
04-10 15:31:33.281 30620-30620/? D/meee: -|母公司
04-10 15:31:33.281 30620-30620/? D/meee: ---|总公司财务部
04-10 15:31:33.281 30620-30620/? D/meee: ---|总公司人力资源部
04-10 15:31:33.281 30620-30620/? D/meee: ---|广东分公司
04-10 15:31:33.281 30620-30620/? D/meee: -----|广东分公司人力资源部
04-10 15:31:33.281 30620-30620/? D/meee: -----|广东分公司财务部
04-10 15:31:33.281 30620-30620/? D/meee: ---|上海分公司
04-10 15:31:33.282 30620-30620/? D/meee: -----|上海分公司人力资源部
04-10 15:31:33.282 30620-30620/? D/meee: -----|上海分公司财务部
04-10 15:31:33.282 30620-30620/? D/meee: ---|北京分公司
04-10 15:31:33.282 30620-30620/? D/meee: -----|北京分公司人力资源部
04-10 15:31:33.282 30620-30620/? D/meee: -----|北京分公司财务部
04-10 15:31:33.282 30620-30620/? D/meee: 母公司号召好好工作
04-10 15:31:33.282 30620-30620/? D/meee: 总公司财务部开始计算公司的收人和支出
04-10 15:31:33.282 30620-30620/? D/meee: 总公司人力资源部的HR开始招人
04-10 15:31:33.282 30620-30620/? D/meee: 广东分公司号召好好工作
04-10 15:31:33.282 30620-30620/? D/meee: 广东分公司人力资源部的HR开始招人
04-10 15:31:33.282 30620-30620/? D/meee: 广东分公司财务部开始计算公司的收人和支出
04-10 15:31:33.282 30620-30620/? D/meee: 上海分公司号召好好工作
04-10 15:31:33.282 30620-30620/? D/meee: 上海分公司人力资源部的HR开始招人
04-10 15:31:33.282 30620-30620/? D/meee: 上海分公司财务部开始计算公司的收人和支出
04-10 15:31:33.282 30620-30620/? D/meee: 北京分公司号召好好工作
04-10 15:31:33.282 30620-30620/? D/meee: 北京分公司人力资源部的HR开始招人
04-10 15:31:33.282 30620-30620/? D/meee: 北京分公司财务部开始计算公司的收人和支出