设计模式(15)组合模式

编程入门 行业动态 更新时间:2024-10-14 10:44:26

设计<a href=https://www.elefans.com/category/jswz/34/1771241.html style=模式(15)组合模式"/>

设计模式(15)组合模式

一、介绍:

1、定义:组合多个对象形成树形结构以表示“整体-部分”的关系的层次结构。组合模式对叶子节点和容器节点的处理具有一致性,又称为整体-部分模式。

2、优缺点:

优点:

(1)高层模块调用简单:组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码。

(2)节点自由增加:更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码。

缺点:

(1)在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

(2)设计较复杂,客户端需要花更多时间理清类之间的层次关系。

(3)不容易限制容器中的构件。

3、组成:

(1)抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)。

(2)树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

(3)树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。

// 定义抽象构件
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();
}// 定义叶子构件
public class Leaf extends Component {public Leaf(String name) {super(name);}@Overridepublic void add(Component component) {System.out.println("Cannot add to a leaf");}@Overridepublic void remove(Component component) {System.out.println("Cannot remove from a leaf");}@Overridepublic void display() {System.out.println("Leaf: " + name);}
}// 定义容器构件
public class Composite extends Component {private List<Component> children = new ArrayList<>();public Composite(String name) {super(name);}@Overridepublic void add(Component component) {children.add(component);}@Overridepublic void remove(Component component) {children.remove(component);}@Overridepublic void display() {System.out.println("Composite: " + name);for (Component component : children) {component.display();}}
}// 客户端代码
public class Client {public static void main(String[] args) {Component root = new Composite("root");Component leaf1 = new Leaf("leaf1");Component leaf2 = new Leaf("leaf2");Component composite1 = new Composite("composite1");Component leaf3 = new Leaf("leaf3");Component composite2 = new Composite("composite2");root.add(leaf1);root.add(leaf2);root.add(composite1);composite1.add(leaf3);composite1.add(composite2);root.display();}
}

4、应用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。

二、demo:

1、菜单:

(1)数据库model

public class MenuDTO {private String menuName;private String menuCode;private String parentMenuCode;public MenuDTO(String menuName,String menuCode,String parentMenuCode){this.menuCode = menuCode;this.menuName = menuName;this.parentMenuCode = parentMenuCode;}/**省略所有set、get芳芳*/
}

 抽象构件Component

public abstract class MenuComponent extends MenuDTO {MenuComponent(String menuName, String menuCode,String parentMenuCode) {super(menuName, menuCode,parentMenuCode);}void addMenu(MenuComponent component){}void removeMenu(MenuComponent component){}
}

(2)树枝构件(Composite): 

public class MenuVO extends MenuComponent {private List<MenuComponent> children = new ArrayList<>();MenuVO(String menuName, String menuCode,String parentMenuCode) {super(menuName, menuCode,parentMenuCode);}@Overridevoid addMenu(MenuComponent component) {children.add(component);}@Overridevoid removeMenu(MenuComponent component) {}
}

(3)树叶

public class MenuLeaf extends MenuComponent {MenuLeaf(String menuName, String menuCode,String parentMenuCode) {super(menuName, menuCode,parentMenuCode);}@Overridevoid addMenu(MenuComponent component) {super.addMenu(component);}@Overridevoid removeMenu(MenuComponent component) {super.removeMenu(component);}
}

 客户端:

public class Test {public static void main(String args[]) {MenuComponent menuVOS = listMenus();System.out.println(menuVOS);}public static MenuComponent listMenus(){//模拟数据库查询,查询所有一级菜单(menu_type = 1)、二级菜单(menu_type = 2)List<MenuDTO> firstMenus = new ArrayList<>();MenuDTO menuDTO = new MenuDTO("菜单1","cd1","root");firstMenus.add(menuDTO);menuDTO = new MenuDTO("菜单2","cd2","root");firstMenus.add(menuDTO);menuDTO = new MenuDTO("菜单3","cd3","root");firstMenus.add(menuDTO);List<MenuDTO> secondMenus = new ArrayList<>();menuDTO = new MenuDTO("菜单1-1","cd1-1","cd1");secondMenus.add(menuDTO);menuDTO = new MenuDTO("菜单1-2","cd1-2","cd1");secondMenus.add(menuDTO);menuDTO = new MenuDTO("菜单2-1","cd2-1","cd2");secondMenus.add(menuDTO);Map<String, List<MenuDTO>> childMenuMap = secondMenus.stream().collect(Collectors.groupingBy(MenuDTO::getParentMenuCode));/**实现* 根节点* 菜单1  菜单2 菜单3*菜单1-1 菜单1-2 菜单2-1* *///1、定义根节点MenuComponent root = new MenuVO("根节点","root",null);//2、处理菜单层级for(MenuDTO  firstMenu : firstMenus){//二级菜单MenuComponent firstMenuVO = new MenuVO(firstMenu.getMenuName(),firstMenu.getMenuCode(),firstMenu.getParentMenuCode());//三级菜单List<MenuDTO> secondMenuVOs = childMenuMap.get(firstMenu.getMenuCode());if(!CollectionUtils.isEmpty(secondMenuVOs)){for(MenuDTO secondMenu : secondMenuVOs){MenuComponent secondMenuVO = new MenuVO(secondMenu.getMenuName(),secondMenu.getMenuCode(),secondMenu.getParentMenuCode());firstMenuVO.addMenu(secondMenuVO);}}root.addMenu(firstMenuVO);}return root;}
}

运行main方法 

2、文件夹:

(1)抽象构件Component

public abstract class FileComponent {//文件名称protected String name;//文件的层级 1 一级目录 2 二级目录 ...protected Integer level;//文件的类型 1 文件夹 2文件protected Integer type;//添加子文件/文件夹public abstract void add(FileComponent fileComponent);//移除子文件/文件夹public abstract void remove(FileComponent fileComponent);//获取指定的子文件/文件夹public abstract FileComponent getChild(int index);//打印子 子文件/子文件夹 名称的方法public abstract void print();
}

(2)树枝构件(Composite)

public class FileFolder extends FileComponent{//文件夹可以有多个子文件夹或者子文件private  List<FileComponent> fileComponentList;public FileFolder(String name, Integer level, Integer type) {this.name = name;this.level = level;this.type = type;this.fileComponentList = new ArrayList<>();}@Overridepublic void add(FileComponent fileComponent) {fileComponentList.add(fileComponent);}@Overridepublic void remove(FileComponent fileComponent) {fileComponentList.remove(fileComponent);}@Overridepublic FileComponent getChild(int index) {return fileComponentList.get(index);}@Overridepublic void print() {//打印菜单名称for (int i = 0; i < level; i++) {System.out.print("\t");}System.out.println(name);//打印子菜单或者子菜单项名称for (FileComponent component : fileComponentList) {component.print();}}
}

(3)树叶构件(Leaf)

public class FileItem extends FileComponent{public FileItem(String name, Integer level, Integer type) {this.name = name;this.level = level;this.type = type;}@Overridepublic void add(FileComponent fileComponent) {}@Overridepublic void remove(FileComponent fileComponent) {}@Overridepublic FileComponent getChild(int index) {return null;}@Overridepublic void print() {//打印文件的名称for (int i = 0; i < level; i++) {System.out.print("\t");}System.out.println(name);}
}

客户端:

public class Test {public static void main(String[] args) {//定义根目录FileComponent rootComponent = new FileFolder("我是根目录",1,1);//定义二级文件夹FileComponent secondLevelComponent = new FileFolder("我是二级目录",2,1);//定义文件FileComponent file = new FileItem("我是文件",3,2);//向根目录添加二级目录rootComponent.add(secondLevelComponent);//向二级目录添加文件secondLevelComponent.add(file);//打印rootComponent.print();}
}

更多推荐

设计模式(15)组合模式

本文发布于:2023-12-03 11:29:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1654855.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模式   组合

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!