文章目录
- 1、组合模式
- 2、案例
- 3、总结
1、组合模式
下面的文件系统,树形结构,有文件夹节点和文件节点(有无儿子节点的区别),使用这两种节点也要做区分。
组合模式(部分整体模式),就是把一组相似的对象当作一个单一的对象。依照树形结构组合对象,表示部分以及整体层次。包含的角色有:
- 抽象根节点:定义系统各层次共有的方法和属性
- 树枝节点:存储子节点
- 叶子节点:其下再无分支,是遍历的最小单位
关键点:
- 意图:将对象组合成树形结构,以表示部分-整体这个层次
- 亮点:模糊简单元素和复杂元素的区别(文件和文件夹),以便可以统一使用结构中的所有对象
- 实现方式:树枝和叶子实现抽象根节点,树枝内部聚合抽象根节点对象
List<抽象根节点类>
2、案例
需求:对一个菜单,打印其及下面的儿子节点
类图:
菜单组件类,定义一些共有的属性和方法,属于抽象根节点。注意这个抽象类,添加、移除菜单等方法对于叶子节点来说是不支持的,因为它们没有,所以在 抽象类中直接throw new UnsupportedOperationException()
做为默认的实现,以后留给子类去实现,或者子类不需要这个方法,那就可以直接不管,这一点在很多源码中都有用到。
//菜单组件 不管是菜单还是菜单项,都应该继承该类
public abstract class MenuComponent {
protected String name; //菜单组件的名称
protected int level; //菜单组件的层级
//添加菜单
public void add(MenuComponent menuComponent){
throw new UnsupportedOperationException();
}
//移除菜单
public void remove(MenuComponent menuComponent){
throw new UnsupportedOperationException(); //不支持的异常
}
//获取指定的子菜单
public MenuComponent getChild(int index){
throw new UnsupportedOperationException();
}
//获取菜单名称
public String getName(){
return name;
}
//打印菜单名称
//也可直接定义成抽象
//public abstract void print();
public void print(){
throw new UnsupportedOperationException();
}
}
定义菜单类,属于树枝节点,继承 + 聚合抽象根节点
public class Menu extends MenuComponent {
//菜单可以有多个子菜单或者子菜单项(叶子)
private List<MenuComponent> menuComponentList;
public Menu(String name,int level){
this.level = level;
this.name = name;
menuComponentList = new ArrayList<MenuComponent>(); //构造方法中初始化
}
@Override
public void add(MenuComponent menuComponent) {
menuComponentList.add(menuComponent); //List中加一个
}
@Override
public void remove(MenuComponent menuComponent) {
menuComponentList.remove(menuComponent); //List中删一个
}
@Override
public MenuComponent getChild(int index) {
return menuComponentList.get(index);
}
@Override
public void print() {
//不同的层级,前面打印不同长度的横线,以作控制台打印缩进区分
for (int i = 1; i < level; i++) {
System.out.print("--");
}
//打印菜单名称
System.out.println(name);
//打印子菜单或子菜单项名称
for (MenuComponent menuComponent : menuComponentList) {
menuComponent.print();
}
}
}
定义菜单项类(没有儿子的叶子节点),add、remove等方法不再重写,采用父类的默认实现抛出一个UnsupportedOperationException即可
public class MenuItem extends MenuComponent {
public MenuItem(String name,int level) {
this.name = name;
this.level = level;
}
@Override
public void print() {
//不同的层级,前面打印不同长度的横线,以作控制台打印缩进区分
for (int i = 1; i < level; i++) {
System.out.print("--");
}
System.out.println(name);
}
}
测试:
public class Client {
public static void main(String[] args) {
//创建菜单树
MenuComponent menu1 = new Menu("菜单管理", 2);
//添加二级菜单的子菜单项
menu1.add(new MenuItem("页面访问", 3));
menu1.add(new MenuItem("展开菜单", 3));
menu1.add(new MenuItem("编辑菜单", 3));
menu1.add(new MenuItem("删除菜单", 3));
menu1.add(new MenuItem("新增菜单", 3));
MenuComponent menu2 = new Menu("权限管理", 2);
menu2.add(new MenuItem("页面访问", 3));
menu2.add(new MenuItem("提交保存", 3));
MenuComponent menu3 = new Menu("角色管理", 2);
menu3.add(new MenuItem("页面访问", 3));
menu3.add(new MenuItem("新增角色", 3));
menu3.add(new MenuItem("修改角色", 3));
//创建一级菜单
MenuComponent component = new Menu("系统管理", 1);
//将二级菜单添加到一级菜单下
component.add(menu1);
component.add(menu2);
component.add(menu3);
//打印菜单名称(及其子菜单)
component.print();
}
}
运行:
3、总结
组合模式为树形结构而生,可以方便的增加树枝节点和叶子节点,而无须对现有代码做任何修改