原文地址:https://blog.csdn.net/qq_40709468/article/details/81990084
组合模式的概念
组合模式:组合多个对象形成树形结构以表示有整体-部分关系层次结构,组合模式可以让客户端统一对待单个对象和组合对象
由于在使用的时候,比如某个文件夹的方法被调用,那么这个会遍历整个树形结构,寻找也包含这个方法的具体实现(文件)。并且调用执行,其中会使用到递归调用的机制对整个机构进行处理。由于,容器和叶子的功能上的区别,在使用这些对象代码中必须去别的对待容器和叶子,这样会让程序非常复杂。
所以,组合模式就出现了!通过一些设计。让容器(文件夹)和叶子(文件)作为相同的对象来处理!
组合模式的UML图
component (抽象构件:容器):它可以是接口或者抽象类,为叶子构建和子容器构建对象声明接口,在该角色中可以包含所有子类共有的行为的实现和声明。在抽象构建中定义了访问及管理它的子构件的方法,如增加子构件,删除子构件,获取子构件等。
leaf(叶子构建):叶子构建可以说就是各种类型的文件!叶子构建没有子构件。它实现了抽象构建中的定义的行为。对于那些访问子容器,删除子容器,增加子容器的就报错。
compsite(子容器构建):它在组合模式中表示容器节点对象,容器结点是子节点,可以是子容器,也可以是叶子构建,它提供一个集合来存储子节点。
最简单的一个实现
public abstract class Component{
//这个是容器类的抽象类,定义好行为,定义创建移除子容器的方法抽象的。
public abstract void addComposite(Component c); //添加成员
public abstract void removeComposite(Component c);//移除成员
public abstract Component getComposite(int i);//获取子容器
public abstract void operation();//业务方法
}
public class Leaf extends Component{
//首先重写component的方法
//叶子节点关键点在于业务
public void Operation(){
System.out.print("业务方法");
}
public void addComponent(Component c){
//提示报错呗 。
System.out.print("不是子容器");
}
public void removeComponent(Component c){
//提示报错呗 。
System.out.print("不是子容器");
}
public Component addComponent(int c){
//提示报错呗 。
System.out.print("不是子容器");
return null;
}
}
public class Composite extends Component{
//首先来一个存储的集合
private ArrayList<Component> list = new ArrayList<Component> ;
public void addComponent(Component c){
list.add(c);
}
public void removeComponent(Component c){
list.remove(c);
}
public Component getComponent(int c){
Component c1 =list.get(c);
return c1;
}
public void operation(){
for(Object obj:list){
((Component)obj).operation();
}
}
}
杀毒软件为例
杀毒软件,该软件能够对某个文件夹杀毒,也可以指定对某些文件杀毒。
AbstractFile: 抽象文件类,充当抽象构建。
package compositePattern;
/**
*
* <p>Title: AbstractFiles</p>
* <p>Description:in this class we are use to test composite pattern </p>
* @author HAND_WEILI
* @date 2018年8月26日
*/
public abstract class AbstractFiles {
public abstract void add(AbstractFiles af);
public abstract void remove(AbstractFiles af);
public abstract AbstractFiles get(int i);
public abstract void killVirus();
}
叶子节点:文件类型,就写了一种。
package compositePattern;
public class ImageFile extends AbstractFiles {
private String name;
public ImageFile(String name) {
this.name=name;
}
@Override
public void add(AbstractFiles af) {
// TODO Auto-generated method stub
System.out.println("不支持该方法");
}
@Override
public void remove(AbstractFiles af) {
// TODO Auto-generated method stub
System.out.println("不支持该方法");
}
@Override
public AbstractFiles get(int i) {
// TODO Auto-generated method stub
System.out.println("不支持该方法");
return null;
}
@Override
public void killVirus() {
// TODO Auto-generated method stub
System.out.println("开始进行--"+name+"--文件杀毒");
}
}
文件类型:
package compositePattern;
import java.util.ArrayList;
public class Folder extends AbstractFiles {
//文件夹类,所有的都可以用
private ArrayList<AbstractFiles> list = new ArrayList<AbstractFiles>();
private String name;
public Folder(String name) {
this.name=name;
}
@Override
public void add(AbstractFiles af) {
list.add(af);
System.out.println("添加成狗");
}
@Override
public void remove(AbstractFiles af) {
// TODO Auto-generated method stub
if(list.remove(af)) {
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}
@Override
public AbstractFiles get(int i) {
// TODO Auto-generated method stub
return list.get(i);
}
@Override
public void killVirus() {
// TODO Auto-generated method stub
System.out.println("对文件夹"+name+"进行杀毒");
//递归调用
for(Object o:list) {
((AbstractFiles)o).killVirus();
}
}
}
测试:
package compositePattern;
public class Client {
public static void main(String[] args) {
//创建一个文件类型
AbstractFiles f1 = new Folder("主文件夹");
//创建文件
AbstractFiles file1= new ImageFile("孙悟空。png");
AbstractFiles file2= new ImageFile("龙珠.jpg");
AbstractFiles file3= new ImageFile("帅哥威.gif");
f1.add(file1);
f1.add(file2);
f1.add(file3);
f1.killVirus();
file1.killVirus();
}
}
组合模式的优缺点
优点:
可以清楚地定义分层次的复杂类型,表示对象的全部层次或者部分层次 ,它让客户端忽略了层次的差异,方便对整个层次经行控制。
客户端可以一致的使用一个组合模式或对单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端的代码。
在组合模式种增加新的容器构件和叶子构件都很方便,无需对现有类库进行任何修改,符合开闭原则。
为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合可以形成复杂的树形机构,但对树形结构的控制却很简单。
缺点:
在增加新的构件时就比较难咯。而且难以限定,有时候希望在一个容器种能有某些特定的对象,例如在某个文件夹只能有image或者gif等。这个就比较难以实现。
组合模式适用场景
1、在具有整体和部分的层次结构种希望通过一种忽略整体与个体之间差异的,客户端一致对待的情况。
2、在一个使用面向对象语言开发的系统中需要处理一个树形结构的。
3、在一个系统中能分离出叶子和容器的,而且他们的类型还固定不变,需要增加一些新的类型
总结
1、 组合模式用于组合多个对象所构成的树形结构层次。2、组合模式包含抽象构建,叶子构建,和容器构建三种角色。
3、组合模式的优点是解决客户端不好统一对待两种类型的类,缺点是面对一些特殊要求时不好办!