简单分析下组合模式
2020/5/19 23:25:32
本文主要是介绍简单分析下组合模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
介绍
组合模式(Composite Pattern)也称为部分整体模式 (Part Whole Pattern) ,属于结构性设计模式,组合模式比较简单,它将一组相似的对象看做一个对象处理,并根据一个树状结构来组合对象,然后提供一个统一的方法去访问相应的对象,以此忽略掉对象与对象集合之间的差别。
定义
将对象组合成树形结构以表示 ”部分-整体“ 的层次结构,使得用户对整个对象和组合对象的使用具有一致性。
使用场景
- 表示对象的 ”部分-整体“ 层次结构时。
- 从一个整体中能够独立出部分模块或功能的场景。
UML 类图
- Component: 抽象根节点,为组合中的对象声明接口。在适当的情况下,实现所有类共有接口的缺省行为。声明一个接口用于访问和管理 Component 的子节点。可在递归结构中定义一个接口,用于访问一个父节点,并在合适的情况下实现它。
- Composite: 定义有子节点的那些枝干节点的行为,存储子节点,在 Component 接口中实现与子节点有关的操作。
- Leaf: 在组合中表示叶子节点对象,叶子节点没有子节点,在组合中定义节点对象的行为。
- Client: 通过 Component 接口操纵组合节点的对象。
代码示例
简单示例
抽象根节点:
public abstract class Component { /** * 节点名称 */ protected String name; public Component(String name) { this.name = name; } /** * 具体的逻辑方法由子类实现 */ public abstract void doSomething(); /** * 添加子节点 * @param component */ public abstract void addChild(Component component); /** * 移除子节点 * @param component */ public abstract void removeChild(Component component); /** * 获取子节点 * @param index * @return */ public abstract Component getChildren(int index); }复制代码
枝干节点:
public class Composite extends Component { /** * 存储节点的容器 */ private List<Component> mLists = new ArrayList<>(); public Composite(String name) { super(name); } @Override public void doSomething() { System.out.println("name: " + name); if (mLists != null && mLists.size() > 0) { for (Component component : mLists) { component.doSomething(); } } } @Override public void addChild(Component component) { mLists.add(component); } @Override public void removeChild(Component component) { mLists.remove(component); } @Override public Component getChildren(int index) { return mLists.get(index); } }复制代码
枝子节点:
public class Leaf extends Component { public Leaf(String name) { super(name); } @Override public void doSomething() { System.out.println("name: " + name); } @Override public void addChild(Component component) { throw new UnsupportedOperationException("叶子节点没有子节点"); } @Override public void removeChild(Component component) { throw new UnsupportedOperationException("叶子节点没有子节点"); } @Override public Component getChildren(int index) { throw new UnsupportedOperationException("叶子节点没有子节点"); } }复制代码
test:
@Test public void testComponent() { //构造一个根节点 Component root = new Composite("Root"); //构造枝干节点 Component branchA = new Composite("branchA"); Component branchB = new Composite("branchB"); //构造叶子节点 Component leafA = new Leaf("leafA"); Component leafB = new Leaf("LeafB"); //将叶子节点添加至枝干节点中 branchA.addChild(leafA); branchB.addChild(leafB); //将枝干节点添加进跟节点 root.addChild(branchA); root.addChild(branchB); root.doSomething(); } 复制代码
output:
name: Root name: branchA name: leafA name: branchB name: LeafB 复制代码
实战
业务背景: 用代码表示文件夹跟文件的组合关系;
文件和文件夹抽象类:
public abstract class Dir { /** * 声明一个 List 成员变量存储文件夹下面所有元素 */ protected List<Dir> mDirs = new ArrayList<>(); /** * 当前文件或文件夹名称 */ protected String name; public Dir(String name) { this.name = name; } /** * 添加一个文件或文件夹 * @param dir */ public abstract void addDir(Dir dir); /** * 移除一个文件或文件夹 * @param dir */ public abstract void removeDir(Dir dir); /** * 清空文件夹下面所有的元素 */ public abstract void clear(); /** * 输出文件夹下目录结构 */ public abstract void print(); /** * 获取文件夹下所有的文件或子文件夹 */ public abstract List<Dir> getFiles(); /** * 获取文件或文件夹名称 * @return */ public String getName(){ return name; } } 复制代码
具体文件夹类:
public class Folder extends Dir { public Folder(String name) { super(name); } @Override public void addDir(Dir dir) { mDirs.add(dir); } @Override public void removeDir(Dir dir) { mDirs.remove(dir); } @Override public void clear() { mDirs.clear(); } @Override public void print() { System.out.print(getName() + " ("); Iterator<Dir> iterator = mDirs.iterator(); while (iterator.hasNext()) { Dir dir = iterator.next(); dir.print(); if (iterator.hasNext()) { System.out.print(", "); } } System.out.print(")"); } @Override public List<Dir> getFiles() { return mDirs; } } 复制代码
具体文件类:
public class File extends Dir { public File(String name) { super(name); } @Override public void addDir(Dir dir) { throw new UnsupportedOperationException("文件对象不支持该操作"); } @Override public void removeDir(Dir dir) { throw new UnsupportedOperationException("文件对象不支持该操作"); } @Override public void clear() { throw new UnsupportedOperationException("文件对象不支持该操作"); } @Override public void print() { System.out.println("name: "+name); } @Override public List<Dir> getFiles() { throw new UnsupportedOperationException("文件对象不支持该操作"); } } 复制代码
test:
@Test public void testComponent2(){ //构造一个目录对象表示 sdcard 盘跟目录 Dir diskSdcard = new Folder("sdcard"); // sdcard 下有一个文件 diskSdcard.addDir(new File("bug.log")); //sdcard 下还有一个子目录 android Dir android = new Folder("android"); //android 目录下有一个目录 Dir data = new Folder("data"); data.addDir(new File("2019-09-14.log")); android.addDir(data); diskSdcard.addDir(android); //sdcard 下还有一个子目录 baidu Dir baidu = new Folder("baidu"); //android 目录下有一个目录 Dir cache = new Folder("cache"); cache.addDir(new File("offline.baidu")); baidu.addDir(cache); diskSdcard.addDir(baidu); //sdcard 下还有一个子目录 downloads Dir downloads = new Folder("downloads"); //android 目录下有一个目录 Dir f360 = new Folder("360"); f360.addDir(new File("360.log")); downloads.addDir(f360); diskSdcard.addDir(downloads); //打印文件结构 diskSdcard.print(); } 复制代码
output:
sdcard ( //文件 name: bug.log, //文件夹 android (data (name: 2019-09-14.log)), baidu (cache (name: offline.baidu)), downloads (360 (name: 360.log)) ) 复制代码
总结
优点:
- 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让高层模块忽略了层次的差异,方便对整个层次结构进行控制。
- 高层模块可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了高层模块的代码。
- 在组合模式中增加了新的枝干构件和叶子构件都很方便,无须对现有类库进行任何修改,符合 "开闭原则"。
- 组合模式为树状结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和树干对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
缺点:
早新增构件时不好对树干中的构件类型进行限制,不能依赖类型系统来施加这些约束,因为在大多数情况下,它们都来自于想听的抽象层,此时,必须进行类型检查来实现,这个实现过程较为复杂。
这篇关于简单分析下组合模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-01-18android.permission.read_media_video
- 2024-01-18android_getaddrinfo failed eai_nodata
- 2024-01-18androidmo
- 2024-01-15Android下三种离屏渲染技术
- 2024-01-09Android 蓝牙使用
- 2024-01-06Android对接华为AI - 文本识别
- 2023-11-15代码安全之代码混淆及加固(Android)
- 2023-11-10简述Android语音播报TTS
- 2023-11-06Android WiFi工具类
- 2023-07-22Android开发未来的出路