23设计模式——组合模式

23设计模式——组合模式,第1张

目录

组合(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 children=new ArrayList();
	
	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,getChildren等)

透明方式

抽象类Component里面声明所有用来管理子类对象的方法,包括add,emove,Display,getChildren等。

优点:所有的构件类都有相同的接口。

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

缺点:不够安全。

因为树叶类对象和合成类对象在本质上是有区别的,树叶类对象没有下一个层次的对象,因此add,remove,Display等方法没有意义,通过判断是getChildren的返回值确认是叶子节点还是树枝节点,如果处理不当,在编译时期不会出错,而会在运行时出错。

安全方式

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 children=new ArrayList();
	
	
	@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);
	}

}

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/920940.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存