常用设计模式之组合(合成)模式

组合模式的中心思想就是整体和部分可以被一致对待。

合成模式就像树形结构的数据结构。例如文件夹的存储和排列,它们是典型的树形结构,而组合模式就是将对象组合成树形结构,使得程序对整体或者单一都具有一致性。

组合模式的目的或者说好处:
定义一个基本对象,这个基本对象可以被组合成组合对象,而这个组合对象又能组合成更加复杂的对象,不断的递归,任何用到基本对象的地方都可以使用组合对象。

使用场景:
当需要体现出部分和整体的结构层次的时候,并且希望忽略掉组合和个体的不同的时候,需要统一使用组合结构中的所有对象时,就应该考虑组合模式。
先看代码:

/**
 * 为组合模式中的对象声明接口
 */
public abstract class Component {
    private String name;

    public String getName() {
        return name;
    }

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

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

    public abstract void add(Component component);//添加

    public abstract void remove(Component component);//删除

    public abstract void display(int depth);//显示等级
}
/**
 * 表示子节点对象,用来存储子节点
 */
public class Composite extends Component {

    private List composites = new ArrayList<>();

    public Composite(String name) {
        super.Component(name);
    }

    @Override
    public void add(Component component) {
        composites.add(component);
    }

    @Override
    public void remove(Component component) {
        composites.remove(component);
    }

    @Override
    public void display(int depth) {
        //非叶节点不光需要显示信息还要向下级添加数据
        Log.i("test", "等级:" + depth + " 名称:" + getName());
        for (Component component : composites) {
            component.display(depth + 2);
        }
    }
}
/**
 * 表示叶节点对象
 */
public class Leaf extends Component {

    public Leaf(String name) {
        super.Component(name);
    }

    @Override
    public void display(int depth) {
        //叶节点中具体逻辑只用于显示信息
        Log.i("test", "等级:" + depth + " 名称:" + getName());

    }

    //因为叶节点为末尾节点,所以没有添加和删除方法
    @Override
    public void add(Component component) {

    }

    @Override
    public void remove(Component component) {

    }


}

子节点对象和叶子节点对象都继承了Component 抽象类,并实现了其中的抽象方法。

而一个属性结构中,除了叶子节点没有向下的数据以外,其他的节点的数据类型都是一样的。

那么组合模式就把这种具有树形结构的对象表示成了标准的树形数据结构,只不过不再是数据结构而是”对象“结构。

以上代码运行方式:

//我们来模拟android sd卡中存储文件的一个树形结构对象
private void test() {
        //生成根节点,上面有两个叶子节点
        Composite root = new Composite("data/data/android/");
        root.add(new Leaf("test.txt"));
        root.add(new Leaf("test.mp3"));

        //生成一个子节点,上面有两个叶子节点,并把这个子节点给根节点
        Composite composite = new Composite("image/");
        composite.add(new Leaf("20160511175230_img.jpg"));
        composite.add(new Leaf("20160511175231_img.jpg"));
        root.add(composite);

        //在子节点X上又附加子节点Y,并且Y也有两个叶子节点
        Composite composite2 = new Composite("cache/");
        composite2.add(new Leaf("20160511175230_img.jpg"));
        composite2.add(new Leaf("20160511175230_img.jpg"));
        composite.add(composite2);

        //在根节点上又加两个叶子节点,但是d这个叶子节点又被清除
        root.add(new Leaf("test.image"));
        Leaf leaf=new Leaf("test.docx");
        root.add(leaf);
        root.remove(leaf);

        root.display(1);
    }

打印出来的结果就是一个标准的树形结构。

这就是组合模式的用处。
组合模式又分为透明方式和安全方式。
以上代码呈现的就是组合模式的透明方式,声明Composite对象来管理所有子对象,对于程序来说,根节点,子节点,叶子节点拥有完全一致的行为接口,没有什么区别。
而叶子节点对象中显然是没有用到add()和remove()方法的。所以这是无用功,也是没有意义的。

安全方式恰恰相反。在Composite接口中声明所有用来管理子类对象的方法但是不包括add和remove方法。由于不够透明,子节点和叶子节点拥有不同的接口,程序调用要做相应的判断,带来了不便。

所以,程序中你该如何运用透明方式还是安全方式取决于需求。

你可能感兴趣的:(设计模式)