设计模式——组合模式

什么是组合模式

将对象组合成属性结构以表示“部分-整体”的层次结构。组合使得用户和单个对象和组合对象的使用具有一致性。 

 

组合对象的角色

1. Component:是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component. 
2. Leaf:在组合中表示叶子节点对象,叶子节点没有子节点。 
3. Composite:定义树枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加和删除等。

组合模式的结构有点类似于树状结构:

 

模式定义中的组合是指连接节点(node),单个对象是指叶子节点,一致性是指具有相同的函数方法,这个一致性有点问题,我们通过一个例子来说明

 

实例:文件系统

IFile:

public interface IFile {
    //添加文件夹或是文件,只对Folder有效
    void add(IFile file);
    //删除文件夹下的所有文件,只对文件夹有效
    void remove();
    //输出文件(夹)的名字
    void display();
    //删除文件(夹)
    void deletefile(IFile file);
}

 

Folder:

import java.util.ArrayList;
public class Folder implements IFile{

    private String name;
    private IFile parent=null;
    private ArrayList<IFile> childs=new ArrayList<IFile>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public IFile getParent() {
        return parent;
    }

    public void setParent(IFile parent) {
        this.parent = parent;
    }

    public ArrayList<IFile> getChilds() {
        return childs;
    }

    public void setChilds(ArrayList<IFile> childs) {
        this.childs = childs;
    }
    
    
    public Folder(String name){
        this(name,null);
    }
    
    public Folder(String name,IFile Parent){
        this.name=name;
        this.parent=Parent;
    }
    
    @Override
    public void add(IFile file) {
        childs.add(file);
    }

    @Override
    public void remove() {
        IFile child;
        while(!childs.isEmpty()){
            child=childs.get(0);
            if((child instanceof Folder))
                 child.remove();
            else
                 child.deletefile(child);         
        }
        
        if(parent!=null){
            System.out.println("删除文件夹"+name);
            deletefile(this);
        }
    }

    @Override
    public void display() {
        System.out.println("文件夹"+name);
        for(IFile child:childs)
            child.display();
    }

    @Override
    public void deletefile(IFile file) {
        ((Folder)parent).getChilds().remove(file);
    }
    
}

 

file:

public class File implements IFile{

    private String name;
    private IFile parent;

    
    public File(String name, IFile parent) {
        this.name = name;
        this.parent = parent;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public IFile getParent() {
        return parent;
    }

    public void setParent(IFile parent) {
        this.parent = parent;
    }
    
    @Override
    public void add(IFile file) {
        throw new UnsupportedOperationException("不支持对应操作");
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("不支持对应操作");
    }

    @Override
    public void display() {
        System.out.println("文件名:"+name);
    }

    @Override
    public void deletefile(IFile file) {
        System.out.println("删除文件"+name);
        ((Folder)parent).getChilds().remove(file);
    }
    
}

 

public class main {
    public static void main(String[] args){
        IFile deal=new Folder("C:\\");
        
        IFile movie=new Folder("电影",deal);
        IFile study=new Folder("学习资料",deal);
        
        deal.add(movie);
        deal.add(study);
        
        movie.add(new File("进击的巨人",movie));
        study.add(new File("设计模式",study));
        study.add(new File("python爬虫",study));
        
        deal.display();
        System.out.println("----------------------------");
        study.remove();
        System.out.println("----------------------------");
        deal.display();
        
    }
}

 

输出结果:

 

这里有一点矛盾,组合模式要求单个对象和组合对象的使用具有一致性,上述例子中,File类是不允许使用remove()、add()方法的,在File类中定义这两个方法是为了维护透明性(即对于用户来说,这两个对象的操作方式是一样的,用户不需要了解现在自己操作的是文件夹还是文件),但是牺牲了安全性(可能会抛出异常),我们也可以将remove()、add()方法抽象为另一个接口,但这也意味着用户需要时刻了解自己使用的是什么对象,对用户的使用造成不便,组合模式的结构决定了组合对象(可以添加子节点)与叶子对象(不能添加子节点)操作的不一致,因此,透明性与安全性是一个矛盾体,根据实际情况选择

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值