乐趣区

关于java:设计模式11-搞定组合模式

开局还是那种图,各位客官往下看 …

组合模式是什么?

组合模式,将对象组合成树形构造以示意“局部 - 整体”的层次结构。(百度百科)

其实,组合模式,又称为局部整体模式,用于把一组类似的对象当作一个繁多的对象。组合模式根据树形构造来组合对象,用来示意局部以及整体档次。这种类型的设计模式属于结构型模式,它创立了对象组的树形构造。

关键字:一致性 , 整体 局部

比方公司的组织架构,就是树形的构造:

公司上面有部门与人,人是属于部门,部门能够领有子部门,如果咱们将下面的节点,不论是组织,还是人,对立形象成为一个node,那么,咱们并不需要关怀以后节点到底是人,还是部门,统计人数的时候或者遍历的时候,厚此薄彼。

还有就是 Java Swing 编程中,个别也会容器的说法:Container, 咱们在 Container 外面能够放子的容器,也能够放具体的组件,比方 Button 或者Checkbox,其实这也是一种局部 - 整体的思维。

除此之外,最经典的是文件夹与文件的示意,一个文件夹(容器对象)既能够寄存文件夹(容器对象),也能够寄存文件(叶子对象)。如果把树的每个节点摊平,那就是List。而树结构,则是更能直观的体现每个节点与整体的关系。

为什么须要这个模式呢?它的目标是什么?

次要是想要对外提供一致性的应用形式,即便容器对象与叶子对象之间属性差异可能十分大,咱们心愿形象出雷同的中央,统一的解决。

组合模式的角色

组合模式中个别有以下三种角色:

  • 形象构件(Component):个别是接口或者抽象类,是叶子构件和容器构件对象申明接口,形象出拜访以及治理子构件的办法。
  • 叶子节点(Leaf):在组合中示意叶子节点对象,叶子节点没有子节点,也就没有子构件。
  • 容器构件(Composite):容器节点能够蕴含子节点,子节点能够是叶子节点,也能够是容器节点。

留神:关键点就是形象构件,所有节点都对立,不再须要调用者关怀叶子节点与非叶子节点的差别。

组合模式的两种实现

组合模式有两种不同的实现,别离是 通明模式 平安模式

两者的区别在于通明模式将组合应用的办法放到抽象类中,而平安模式则是放到具体实现类中

通明模式

通明模式是把组合的办法形象到抽象类中,不论是叶子节点,还是组合节点,都有一样的办法,这样对外解决的时候是统一的,不过实际上有些办法对叶子节点而言,是没有用的,有些累赘。

上面是代码实现:

抽象类,要求实现三个办法,减少,删除,展现:

package designpattern.composite;

public abstract class Component {
    String name;

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

    public abstract void add(Component component);

    public abstract void remove(Component component);

    public abstract void show(int depth);
}

组合类:

import java.util.ArrayList;
import java.util.List;

public class Composite extends Component {List<Component> childs = new ArrayList<>();

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

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

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

    @Override
    public void show(int depth) {for (int i = 0; i < depth; i++) {System.out.print(" ");
        }
        System.out.println(name + ":");
        for (Component component : childs) {component.show(depth + 1);
        }
    }
}

叶子类:


public class Leaf extends Component {public Leaf(String name) {super(name);
    }

    @Override
    public void add(Component component) { }

    @Override
    public void remove(Component component) { }

    @Override
    public void show(int depth) {for (int i = 0; i < depth; i++) {System.out.print(" ");
        }
        System.out.println(name);
    }
}

测试类:

public class Test {public static void main(String[] args) {Composite folderRoot = new Composite("备忘录文件夹");
        folderRoot.add(new Leaf("word 文件"));
        folderRoot.add(new Leaf("ppt 文件"));

        Composite folderLevel1 = new Composite("周报文件夹");
        folderLevel1.add(new Leaf("20210101 周报"));
        folderRoot.add(folderLevel1);


        Composite folderLevel2 = new Composite("笔记文件夹");
        folderLevel2.add(new Leaf("jvm.ppt"));
        folderLevel2.add(new Leaf("redis.txt"));
        folderLevel1.add(folderLevel2);


        folderRoot.add(new Leaf("需要.txt"));


        Leaf leaf = new Leaf("bug 单.txt");
        folderRoot.add(leaf);
        folderRoot.remove(leaf);

        folderRoot.show(0);
    }
}

运行后果如下:

备忘录文件夹: 
    word 文件
    ppt 文件
    周报文件夹: 
        20210101 周报
        笔记文件夹: 
            jvm.ppt
            redis.txt
    需要.txt

能够看到以上是一棵树的后果,不论是叶子节点,还是组合节点,都是一样的操作。

平安模式

平安模式,就是叶子节点和组合节点的个性离开,只有组合节点才有减少和删除操作,而两者都会领有展现操作。然而如果同时对外裸露叶子节点和组合节点的话,应用起来还须要做非凡的判断。

形象组件:

public abstract class Component {
    String name;

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

    public abstract void show(int depth);
}

组件构件:

public class Composite extends Component {List<Component> childs = new ArrayList<>();

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

    public void add(Component component) {this.childs.add(component);
    }

    public void remove(Component component) {this.childs.remove(component);
    }

    @Override
    public void show(int depth) {for (int i = 0; i < depth; i++) {System.out.print(" ");
        }
        System.out.println(name + ":");
        for (Component component : childs) {component.show(depth + 1);
        }
    }
}

叶子节点:

public class Leaf extends Component {public Leaf(String name) {super(name);
    }

    @Override
    public void show(int depth) {for (int i = 0; i < depth; i++) {System.out.print(" ");
        }
        System.out.println(name);
    }
}

测试类不变,测试后果也一样:

备忘录文件夹: 
    word 文件
    ppt 文件
    周报文件夹: 
        20210101 周报
        笔记文件夹: 
            jvm.ppt
            redis.txt
    需要.txt

平安模式中,叶子节点没有多余的办法,没有空的办法,里面调用的时候,不会调用到空办法。然而须要对节点进行判断,能力晓得哪一个办法能调,哪一个办法不能调。

小结一下

组合模式的长处:

  • 能够分档次定义简单对象,示意部分和全副,客户端能够疏忽不同的节点的差别。
  • 从高层次调用,能够很顺畅的调用到每一个部分,一致性比拟强。
  • 节点自在搭配,灵便度比拟高。

毛病:

  • 在应用组合模式时,其叶子和组合节点的申明都是实现类,而不是接口,违反了依赖倒置准则。

应用场景:

  • 心愿疏忽每个局部的差别,客户端统一应用
  • 须要体现为树形构造,以示意“整体 - 局部”的构造档次。

以一句网友的话结尾:

“张无忌学太极拳,遗记了所有招式,打倒了 ” 玄冥二老 ”,所谓 ” 心中无招 ”。设计模式堪称招数,如果先学通了各种模式,又忘掉了所有模式而得心应手,堪称 OO 之最高境界。”

【作者简介】
秦怀,公众号【秦怀杂货店】作者,集体网站:http://aphysia.cn,技术之路不在一时,山高水长,纵使迟缓,驰而不息。

剑指 Offer 全副题解 PDF

开源编程笔记

设计模式系列:

  • 设计模式【1】– 单例模式到底几种写法?
  • 设计模式【1.1】– 你想如何毁坏单例模式?
  • 设计模式【1.2】– 枚举式单例有那么好用么?
  • 设计模式【1.3】– 为什么饿汉式单例是线程平安的?
  • 设计模式【2】– 简略工厂模式理解一下?
  • 设计模式【2.1】– 简略工厂模式怎么演变成工厂办法模式?
  • 设计模式【2.2】– 工厂模式怎么演变成形象工厂模式?
  • 设计模式【3.1】– 浅谈代理模式之动态、动静、cglib 代理
  • 设计模式【3.2】– JDK 动静代理源码剖析有多香?
  • 设计模式【3.3】– CGLIB 动静代理源码解读
  • 设计模式【4】– 建造者模式详解
  • 设计模式【5】– 原型模式
  • 设计模式【6.1】– 初探适配器模式
  • 设计模式【6.2】– 再聊聊适配器模式
  • 设计模式【7】– 摸索一下桥接模式
  • 设计模式【8】– 手工耿教我写装璜器模式
  • 设计模式【9】– 外观模式?没那么高大上
  • 设计模式【10】– 顺便看看享元模式
退出移动版