一、定义
组合(Composite)模式是一种对象的行为模式。将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式分为:安全组合模式和透明组合模式。
安全组合模式是指:从客户使用组合模式上看是否更安全。如果是安全的,那么就不会有发生误操作的可能,能访问的方法都是被支持的功能。
透明组合模式是指:从客户使用组合模式上看是否需要区分到底是组合对象还是叶子对象。如果是透明的,那就不用再区分,对于客户而言,都是组件对象,具体的类型对于客户而言是透明的,是客户无须关心的。
二、优点及缺点
优点:
1、统一了组合对象和叶子对象。
2、简化了客户端调用,无须区分操作的是组合对象还是叶子对象。
3、更容易扩展,有了Component的约束,新定义的Composite或Leaf子类能够很容易地与已有的结构一起工作。
缺点:
1、很难限制组合中的组件类型。
三、代码实现:
安全组合模式:
抽象类:
package com.example.demo.sjms.anquanzuhemoshi; /** * @Author: caesar * @Date:2020年10月22日 14:10:23 * @Description: 抽象构建角色 */ public abstract class Component { protected String name; public Component(String name) { this.name = name; } /*** * @Author: caesar * @Date:2020年10月22日 14:10:43 * @Description: 打印树枝和叶子的抽象方法 * @Param: * @Return: */ public abstract void println(); }
树枝类:
package com.example.demo.sjms.anquanzuhemoshi; import java.util.ArrayList; import java.util.List; /** * @Author: caesar * @Date:2020年10月22日 14:10:36 * @Description: 树枝构件角色 */ public class Composite extends Component{ private List<Component> componentList = new ArrayList<Component>(); public Composite(String name) { super(name); } /*** * @Author: caesar * @Date:2020年10月22日 14:10:06 * @Description: 添加节点 * @Param: * @Return: */ public void addComponent(Component component){ componentList.add(component); } /*** * @Author: caesar * @Date:2020年10月22日 14:10:06 * @Description: 删除节点 * @Param: * @Return: */ public void removeComponent(int index){ componentList.remove(index); } @Override public void println() { System.out.println("树枝的名称为:"+super.name); if(!componentList.isEmpty()){ System.out.println("树叶节点名称如下:"); componentList.forEach(x -> x.println()); } } }
树叶类:
package com.example.demo.sjms.anquanzuhemoshi; /** * @Author: caesar * @Date:2020年10月22日 14:10:50 * @Description: 树叶角色 */ public class Leaf extends Component{ public Leaf(String name) { super(name); } @Override public void println() { System.out.println(super.name); } }
测试类:
package com.example.demo.sjms.anquanzuhemoshi; /** * @Author: caesar * @Date:2020年10月22日 14:10:30 * @Description: 测试类 */ public class Test { public static void main(String[] args) { Composite composite = new Composite("大树"); Composite composite1 = new Composite("树枝"); Leaf leaf1 = new Leaf("树叶一"); Leaf leaf2 = new Leaf("树叶二"); Leaf leaf3 = new Leaf("树叶三"); composite1.addComponent(leaf1); composite1.addComponent(leaf2); composite1.addComponent(leaf3); composite1.println(); // ---------------假如再来一层,将树枝放大树里面---------------- composite.addComponent(composite1); composite.println(); } }
透明组合模式:
抽象类:
package com.example.demo.sjms.anquanzuhemoshi; /** * @Author: caesar * @Date:2020年10月22日 14:10:30 * @Description: 测试类 */ public class Test { public static void main(String[] args) { Composite composite = new Composite("大树"); Composite composite1 = new Composite("树枝"); Leaf leaf1 = new Leaf("树叶一"); Leaf leaf2 = new Leaf("树叶二"); Leaf leaf3 = new Leaf("树叶三"); composite1.addComponent(leaf1); composite1.addComponent(leaf2); composite1.addComponent(leaf3); composite1.println(); // ---------------假如再来一层,将树枝放大树里面---------------- composite.addComponent(composite1); composite.println(); } }
树枝类:
package com.example.demo.sjms.toumingzuhemoshi; import java.util.ArrayList; import java.util.List; /** * @Author: caesar * @Date:2020年10月22日 14:10:36 * @Description: 树枝构件角色 */ public class Composite extends Component { public Composite(String name) { super(name); } /*** * @Author: caesar * @Date:2020年10月22日 14:10:06 * @Description: 添加节点 * @Param: * @Return: */ @Override public void addComponent(Component component){ super.componentList.add(component); } /*** * @Author: caesar * @Date:2020年10月22日 14:10:06 * @Description: 删除节点 * @Param: * @Return: */ @Override public void removeComponent(int index){ super.componentList.remove(index); } @Override public void println() { System.out.println("树枝的名称为:"+super.name); if(!super.componentList.isEmpty()){ System.out.println("树叶节点名称如下:"); super.componentList.forEach(x -> System.out.println(x.name)); } } }
树叶类:
package com.example.demo.sjms.toumingzuhemoshi; /** * @Author: caesar * @Date:2020年10月22日 14:10:50 * @Description: 树叶角色 */ public class Leaf extends Component { public Leaf(String name) { super(name); } @Override public void println() { System.out.println(super.name); } @Override public void addComponent(Component component) { System.out.println("无法使用!!!"); } @Override public void removeComponent(int index) { System.out.println("无法使用!!!"); } }
测试类:
package com.example.demo.sjms.toumingzuhemoshi; /** * @Author: caesar * @Date:2020年10月22日 14:10:30 * @Description: 测试类 */ public class Test { public static void main(String[] args) { Composite composite = new Composite("大树"); Composite composite1 = new Composite( "树枝"); Leaf leaf1 = new Leaf("树叶一"); Leaf leaf2 = new Leaf("树叶二"); Leaf leaf3 = new Leaf("树叶三"); composite1.addComponent(leaf1); composite1.addComponent(leaf2); composite1.addComponent(leaf3); composite1.println(); // ---------------假如再来一层,将树枝放大树里面---------------- composite.addComponent(composite1); composite.println(); // 这就很ok } }
四、源码级别
五、总结
我认为,组合模式的精髓,就在于,它可以不区分组合对象和叶子对象,客户可以不用关系内部结构,直接调用,说白了就是组合对象和叶子对象是一样的,只是实现方法不一样,如果使用安全组合模式的话,虽然保证了程序员不会在使用这个设计模式的时候出现失误,但是它实际已经将组合对象和叶子对象区分开了,甚至会出现,向下转型,方法丢失的情况,所以最好不要使用安全组合模式。