目录
组合(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);
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)