Java设计模式之组合模式

来源:互联网 发布:js获取标签内容 编辑:程序博客网 时间:2024/05/21 06:21

组合模式(Composite):将对象组合成树形结构以表示’部分-整体‘的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。


Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。

//Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。public abstract class Component {    protected String name;    public 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<Component> children = new ArrayList<Component>();    public Composite(String name) {        super(name);    }    @Override    public void add(Component component) {        children.add(component);    }    @Override    public void remove(Component component) {        children.remove(component);    }    @Override    public void display(int depth) {        // 显示其枝节点名称,并对其下级进行遍历        System.out.println(StringUtil.repeatableString("-", depth) + this.name);        for (Component component : children) {            component.display(depth + 2);        }    }}

这里用到一个工具类StringUtil:

/** * Util for String * */public class StringUtil {    private static final int DEFAULT_STRING_LENGTH = 10;    private static final String LETTERS = "abcdefghijkllmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";    private static Random random = new Random();    /**     * Don't let anyone instantiate this class.     */    private StringUtil() {    }    /**     * @param str     * @return {@code true} if the input {@code String} is null or ""     */    public static boolean empty(final String str) {        return str == null || str.trim().isEmpty();    }    /**     * generate random string     *     * @return a random string     */    public static String generateRandomString() {        return generateRandomString(DEFAULT_STRING_LENGTH);    }    /**     * generate random string using all letters and the given length     *     * @param stringLength     * @return a random string     */    public static String generateRandomString(int stringLength) {        if (stringLength <= 0) {            stringLength = DEFAULT_STRING_LENGTH;        }        StringBuilder stringBuilder = new StringBuilder();        for (int i = 0; i < stringLength; i++) {            stringBuilder                    .append(LETTERS.charAt(random.nextInt(LETTERS.length())));        }        return stringBuilder.toString();    }    /**     * repeat a {@code String} called repeatStr for repeatNum times     *     * @param repeatStr     * @param repeatNum     * @return {@code String} repeatedString     */    public static String repeatableString(String repeatStr, int repeatNum) {        StringBuilder stringBuilder = new StringBuilder();        while (repeatNum-- > 0) {            stringBuilder.append(repeatStr);        }        return stringBuilder.toString();    }}
Leaf在组合中表示叶节点对象,叶节点没有子节点:
public class Leaf extends Component {//Leaf在组合中表示叶节点对象,叶节点没有子节点    public Leaf(String name) {        super(name);    }    @Override    public void add(Component component) {        System.out.println("cannot add to a leaf");    }    @Override    public void remove(Component component) {        System.out.println("cannot remove from a leaf");    }    @Override    public void display(int depth) {        // 通过“-”的数目显示级别        System.out.println(StringUtil.repeatableString("-", depth) + this.name);    }}
客户端。通过Component接口操作组合部件的对象:

public class CompositeClient {//客户端。通过Component接口操作组合部件的对象    public static void main(String[] args) {        // 生成树根,根上长出两叶Leaf A和Leaf B        Composite root = new Composite("root");        root.add(new Leaf("Leaf A"));        root.add(new Leaf("Leaf B"));        // 根上长出分支Composite X,分支上也有两叶Leaf X-A和Leaf X-B        Composite compositeX = new Composite("Composite X");        compositeX.add(new Leaf("Leaf X-A"));        compositeX.add(new Leaf("Leaf X-B"));        root.add(compositeX);        // 在Composite X上再长出分支Composite X-Y,分支上也有两叶Leaf X-Y-A和Leaf X-Y-B        Composite compositeXY = new Composite("Composite X-Y");        compositeXY.add(new Leaf("Leaf X-Y-A"));        compositeXY.add(new Leaf("Leaf X-Y-B"));        compositeX.add(compositeXY);        // 显示大树的样子        root.display(1);    }}
运行结果:

-root---Leaf A---Leaf B---Composite X-----Leaf X-A-----Leaf X-B-----Composite X-Y-------Leaf X-Y-A-------Leaf X-Y-B
组合模式适用场合:

当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象,就应该考虑组合模式。

组合模式的好处:

组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构,基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象。用户是不用关系到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了,组合模式让客户户可以一致地使用组合结构和单个对象。

原创粉丝点击