设计模式-组合模式(Composite)
一、概念
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
二、模式动机
组合模式,通过设计一个抽像的组件类,使它既代表叶子对象,又代表组合对象,将叶子对象和组合对象统一起来。使得客户端在操作时不再区分当前操作的是叶子对象还是组合对象,而是以一个统一方式来操作。
三、模式的结构
示意代码如下:
package composite.structure; /**
* 统一叶子和组件的抽象构件类
* @ClassName: Component
* @author beteman6988
* @date 2017年11月29日 下午10:48:18
*
*/
public abstract class Component { /**
* 叶子和树技构件都具备的商业逻辑
* @Title: sampleOperation
* @param
* @return void
* @throws
*/
public abstract void sampleOperation(); /**
* 向组合对象中添加组件对象
* @Title: addChild
* @param @param child
* @return void
* @throws
*/
public abstract void addChild(Component child); /**
* 向组合对象中删除组件对象
* @param child
* @roseuid 5A1EC291037D
*/
public abstract void removeChild(Component child) ; /**
* 从组合对象中取出第index个位置的组件对象
* @param index
* @return Component
* @roseuid 5A1EC2F2011B
*/
public abstract Component getChildren(Integer index) ;
}
package composite.structure; import java.util.ArrayList;
import java.util.List; /**
* 组合对像,通常存储子组件对象,实现抽象组件里面定义的与操作子组件对象有关的行为。
* @ClassName: Composite
* @author beteman6988
* @date 2017年12月3日 上午9:22:08
*
*/
public class Composite extends Component { List<Component> childComponent=new ArrayList<Component>(); /**
* 商业逻辑,这里样例迭代所有子组件的该方法
*/
@Override
public void sampleOperation() {
for(Component component:childComponent) {
component.sampleOperation();
} } @Override
public void addChild(Component child) {
this.childComponent.add(child);
} @Override
public void removeChild(Component child) {
this.childComponent.remove(child);
} @Override
public Component getChildren(Integer index) {
if(!childComponent.isEmpty() && childComponent.size()>index ) {
return this.childComponent.get(index);
}
return null;
} }
package composite.structure; /**
* 叶子组件对象
* @ClassName: Leaf
* @author beteman6988
* @date 2017年12月3日 上午9:25:42
*
*/
public class Leaf extends Component { /**
* 商业逻辑
*/
@Override
public void sampleOperation() {
//具体的商业逻辑
} /**
* 由于是叶子对象节点,不具备增加组件对象的功能,所以可以提供平庸实现
*/
@Override
public void addChild(Component child) { } /**
* 由于是叶子对象节点,不具备删除组件对象的功能,所以可以提供平庸实现
*/
@Override
public void removeChild(Component child) {
// TODO Auto-generated method stub } /**
* 由于是叶子对象节点,不具获取子组件对象的功能,所以可以提供平庸实现
*/
@Override
public Component getChildren(Integer index) {
// TODO Auto-generated method stub
return null;
} }
角色说明:
Component:抽象的组件对象,可以是一个抽象类或者是一个接口,它既代表叶子对象,也代组合对象,让客户端通过这个接口来管理整个对象结构,上面的样例代码定义的是一个抽象类,且管理组合对象的方法是抽象的,其实也可以提供默认的实现。不提供默认实现的好处就是叶子对象针对这些不支持的行为必须给出明确的处理方式。提供默认形为的好处,如果默认的是针对叶子对象的行为,那么针对叶子对象就不需要对这些不支持的形为提供明确的处理方式。并没有说哪种就好哪种就劣,各有优缺。
Composite:组合对象,通常存储子组件,并包含操作子组件的具体行为,如对子组件进行增删改查。
Leaf:叶子节点组件:定义和实现与叶子对象的行为,不能包含其它子组件。
在组合模式中,对象分为两种,一为Composite对象,它可以包含其它的Composite或叶子对象,就像一个容器,二为不能包含子组件的Leaf对象。对于Composite对像,为了管理子组件对象,就要定以一些管理子组件的操作行为,以上的例 子中将这些操作形为定义在了抽象的Component组件中,但是这些行为其实对于Leaf对象是没有意义的,这些行为可以放在Composite中,而非放在在Component中。所以跟据Composite对象中管理子组件的行为操作是放在Componnet或是Composite中,细分为了“透明模式”和“安全模式”
透明模式:上面的示例结构为透明模式,透明模式对于客户端来说,Leaf对象和Composite对象具有相同的行为,对于客户端而言,Leaf对角和Composite对象是透明的,他们都是Component对象,具有相同的接口行为,也可以在Leaf对象上使用增加子组件的行为,只是这些行为对于Leaf对象是无意义的,这也意为着是不安全的。
安全模式:针对透明模式中,管理子组件的行为如果不定义在Component中,而是定义在Composite中,这样对于Leaf对象就是安全的了。因为客户端对于Leaf对象,就无在调用管理子组件的行为。模式结构如下:
示意代码如下:
package composite.structure.safety; /**
* 统一叶子和组件的抽象构件类
* @ClassName: Component
* @author beteman6988
* @date 2017年11月29日 下午10:48:18
*
*/
public abstract class Component { /**
* 叶子和树技构件都具备的商业逻辑
* @Title: sampleOperation
* @param
* @return void
* @throws
*/
public abstract void sampleOperation(); }
package composite.structure.safety; import java.util.ArrayList;
import java.util.List; /**
* 组合对像,通常存储子组件对象,实现抽象组件里面定义的与操作子组件对象有关的行为。
* @ClassName: Composite
* @author beteman6988
* @date 2017年12月3日 上午9:22:08
*
*/
public class Composite extends Component { List<Component> childComponent=new ArrayList<Component>(); /**
* 商业逻辑,这里样例迭代所有子组件的该方法
*/
@Override
public void sampleOperation() {
for(Component component:childComponent) {
component.sampleOperation();
}
} /**
* 向组合对象中添加组件对象
* @Title: addChild
* @param @param child
* @return void
* @throws
*/
public void addChild(Component child) {
this.childComponent.add(child);
} /**
* 向组合对象中删除组件对象
* @Title: removeChild
* @param @param child
* @return void
* @throws
*/
public void removeChild(Component child) {
this.childComponent.remove(child);
} /**
* 从组合对象中取出第index个位置的组件对象
* @Title: getChildren
* @param @param index
* @param @return
* @return Component
* @throws
*/
public Component getChildren(Integer index) {
if(!childComponent.isEmpty() && childComponent.size()>index ) {
return this.childComponent.get(index);
}
return null;
} }
package composite.structure.safety; /**
* 叶子组件对象
* @ClassName: Leaf
* @author beteman6988
* @date 2017年12月3日 上午9:25:42
*
*/
public class Leaf extends Component { /**
* 商业逻辑
*/
@Override
public void sampleOperation() {
//具体的商业逻辑
} }
四、模式样例
打印出以常见学的学校组织架构为例,如下:
XX大学
信息工程学院
计算机科学系
电子与信息工程系
建筑工程学院
土木建筑系
工程管理系
透明模式:
package composite.sample; /**
* 院系抽像接口
* @ClassName: SCCompent
* @author beteman6988
* @date 2017年12月9日 下午8:15:46
*
*/
public interface SCComponent { /**
* get院系名称
* @Title: getName
* @param @return
* @return String
* @throws
*/
public String getName(); /**
* 设置院系名称
* @Title: setName
* @param @return
* @return
* @throws
*/
public void setName(String name); /**
* 添加下级院系
* @Title: addSCc
* @param @param scComponent
* @return void
* @throws
*/
public void addSCc(SCComponent scComponent); /**
* 移去下级院系
* @Title: removeSCc
* @param @param scComponent
* @return void
* @throws
*/
public void removeSCc(SCComponent scComponent); /**
* 打印院系名称
* @Title: printName
* @param @param preStr
* @return void
* @throws
*/
public void printName(String preStr); }
package composite.sample; /**
* 叶子系节点
* @ClassName: Department
* @author beteman6988
* @date 2017年12月9日 下午8:25:53
*
*/
public class Department implements SCComponent { private String departmentName; @Override
public String getName() {
// TODO Auto-generated method stub
return departmentName;
} @Override
public void setName(String name) {
this.departmentName=name;
} @Override
public void addSCc(SCComponent scComponent) {
System.out.println("Department不支持addSCc行为!");
} @Override
public void removeSCc(SCComponent scComponent) {
System.out.println("Department不支持removeSCc行为!"); } @Override
public void printName(String preStr) {
System.out.println(preStr+this.departmentName);
} }
package composite.sample; import java.util.ArrayList;
import java.util.List; /**
*院系设置的组合对象
* @ClassName: SCComposite
* @author beteman6988
* @date 2017年12月9日 下午8:37:44
*
*/
public class SCComposite implements SCComponent { private String name; private List<SCComponent> sCCList=new ArrayList<SCComponent>(); @Override
public String getName() {
return this.name;
} @Override
public void setName(String name) {
this.name=name;
} @Override
public void addSCc(SCComponent scComponent) {
if(sCCList.indexOf(scComponent)<0) {
sCCList.add(scComponent);
} } @Override
public void removeSCc(SCComponent scComponent) {
this.sCCList.remove(scComponent); } @Override
public void printName(String preStr) {
System.out.println(preStr+this.name);
for(SCComponent component:sCCList) {
component.printName(preStr+" ");
}
}
}
package composite.sample; public class Client {
public static void main(String[] args) {
SCComponent head=new SCComposite();
head.setName("XX大学"); SCComponent sCCOne=new SCComposite();
sCCOne.setName("信息工程学院"); SCComponent sCCTwo=new SCComposite();
sCCTwo.setName("建筑工程学院"); head.addSCc(sCCOne);
head.addSCc(sCCTwo); SCComponent dptOne=new Department();
dptOne.setName("计算机科学系"); SCComponent dptTwo=new Department();
dptTwo.setName("电子与信息工程系"); sCCOne.addSCc(dptOne);
sCCOne.addSCc(dptTwo); SCComponent dptThree=new Department();
dptThree.setName("土木建筑系"); SCComponent dptFour=new Department();
dptFour.setName("工程管理系"); sCCTwo.addSCc(dptThree);
sCCTwo.addSCc(dptFour); //sCCTwo.removeSCc(dptThree);
head.printName(""); } }
运行结果如下:
XX大学
信息工程学院
计算机科学系
电子与信息工程系
建筑工程学院
工程管理系
安全模式:
代码如下:
package composite.sample.safety; /**
* 院系抽像接口
* @ClassName: SCCompent
* @author beteman6988
* @date 2017年12月9日 下午8:15:46
*
*/
public interface SCComponent { /**
* get院系名称
* @Title: getName
* @param @return
* @return String
* @throws
*/
public String getName(); /**
* 设置院系名称
* @Title: setName
* @param @return
* @return
* @throws
*/
public void setName(String name); /**
* 打印院系名称
* @Title: printName
* @param @param preStr
* @return void
* @throws
*/
public void printName(String preStr); }
package composite.sample.safety; /**
* 叶子系节点
* @ClassName: Department
* @author beteman6988
* @date 2017年12月9日 下午8:25:53
*
*/
public class Department implements SCComponent { private String departmentName; @Override
public String getName() {
// TODO Auto-generated method stub
return departmentName;
} @Override
public void setName(String name) {
this.departmentName=name;
} @Override
public void printName(String preStr) {
System.out.println(preStr+this.departmentName);
} }
package composite.sample.safety; import java.util.ArrayList;
import java.util.List; /**
*院系设置的组合对象
* @ClassName: SCComposite
* @author beteman6988
* @date 2017年12月9日 下午8:37:44
*
*/
public class SCComposite implements SCComponent { private String name; private List<SCComponent> sCCList=new ArrayList<SCComponent>(); @Override
public String getName() {
return this.name;
} @Override
public void setName(String name) {
this.name=name;
} public void addSCc(SCComponent scComponent) {
if(sCCList.indexOf(scComponent)<0) {
sCCList.add(scComponent);
} } public void removeSCc(SCComponent scComponent) {
this.sCCList.remove(scComponent); } @Override
public void printName(String preStr) {
System.out.println(preStr+this.name);
for(SCComponent component:sCCList) {
component.printName(preStr+" ");
}
}
}
package composite.sample.safety; public class Client {
public static void main(String[] args) {
SCComposite head=new SCComposite();
head.setName("XX大学"); SCComposite sCCOne=new SCComposite();
sCCOne.setName("信息工程学院"); SCComposite sCCTwo=new SCComposite();
sCCTwo.setName("建筑工程学院"); head.addSCc(sCCOne);
head.addSCc(sCCTwo); SCComponent dptOne=new Department();
dptOne.setName("计算机科学系"); SCComponent dptTwo=new Department();
dptTwo.setName("电子与信息工程系"); sCCOne.addSCc(dptOne);
sCCOne.addSCc(dptTwo); SCComponent dptThree=new Department();
dptThree.setName("土木建筑系"); SCComponent dptFour=new Department();
dptFour.setName("工程管理系"); sCCTwo.addSCc(dptThree);
sCCTwo.addSCc(dptFour); //sCCTwo.removeSCc(dptThree);
head.printName(""); } }
运行结果如下:
XX大学
信息工程学院
计算机科学系
电子与信息工程系
建筑工程学院
土木建筑系
工程管理系
五、模式优缺点
优点:1.定义了包含基本对象和组合对象的类层次结构
2.统一了组合对象和叶子对象,在组合模式中,可以把叶子对象当成特殊的组合对象来看待,为他们定义统一的父类,从而把叶子对象和组合对象的行为统一起来。
3.方便扩展,只要是Component的子类对象,都可以很方便添加到组合对象中。
缺点:优点中的第3点既是优点,也是缺点,组合对象很难确定里面的具体组件类型,因为只要是Component的子类对象,都可以添加到组合对象中,所以当要确定组合对象中组件具体的类型时,就必须在运行期动态检测。
设计模式-组合模式(Composite)的更多相关文章
- 浅谈设计模式--组合模式(Composite Pattern)
组合模式(Composite Pattern) 组合模式,有时候又叫部分-整体结构(part-whole hierarchy),使得用户对单个对象和对一组对象的使用具有一致性.简单来说,就是可以像使用 ...
- 设计模式 - 组合模式(composite pattern) 迭代器(iterator) 具体解释
组合模式(composite pattern) 迭代器(iterator) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考组合模式(composit ...
- 设计模式组合模式(Composite)精华
23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例,他们帮助如何创建一个系统独立.这是一个这些对象和陈述的组合. 创建使用继承类的类架构更改实例.的对象类型模型的建 ...
- 设计模式 -- 组合模式 (Composite Pattern)
定义: 对象组合成部分整体结构,单个对象和组合对象具有一致性. 看了下大概结构就是集团总公司和子公司那种层级结构. 角色介绍: Component :抽象根节点:其实相当去总公司,抽象子类共有的方法: ...
- 设计模式--组合模式Composite(结构型)
一.概念 组合模式允许你将对象组合成树形结构来表现"整体/部分"层次结构.组合能让客户以一致的方式处理个别对象以及对象组合. 二.UML图 1.Component(对象接口),定义 ...
- C#设计模式——组合模式(Composite Pattern)
一.概述 在软件开发中,我们往往会遇上类似树形结构的对象体系.即某一对象既可能在树形结构中作为叶节点存在,也可能作为分支节点存在.比如在文件系统中,文件是作为叶节点存在,而文件夹就是分支节点.在设计这 ...
- 说说设计模式~组合模式(Composite)
返回目录 何时能用到它? 组合模式又叫部分-整体模式,在树型结构中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦.对于今天这个 ...
- 大话设计模式--组合模式 Composite -- C++实现实例
1. 组合模式: 将对象组合成树形结构以表示"部分--整体"的层次结构,组合模式使用户对单个对象和组合对象的使用具有一致性. 需求中是体现部分与整体层次的结构时,希望用户可以忽略组 ...
- 设计模式(七)组合模式Composite(结构型)
设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 ...
随机推荐
- UWP 使用Windows Community Toolkit 的OneDrive service上传下载文件
上一年年底写过两篇文章 UWP 使用OneDrive云存储2.x api(一)[全网首发] UWP 使用OneDrive云存储2.x api(二)[全网首发] 没想到半年之后,VS编译提示方法已经过时 ...
- Spring Cloud实践之服务注册与发现Eureka
一.简述: 服务提供者producer与服务消费者consumer都注册到eureka server,然后服务consumer在其应用内直接调用producer的服务名来调用服务,而不是像之前一样调用 ...
- Python -bs4介绍
https://cuiqingcai.com/1319.html Python -BS4详细介绍Python 在处理html方面有很多的优势,一般情况下是要先学习正则表达式的.在应用过程中有很多模块是 ...
- MariaDB 库的基本操作(2)
MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可MariaDB的目的是完全兼容MySQL,包括API和命令行,MySQL由于现在闭源了,而能轻松成为MySQ ...
- 使用json-server模拟REST API
https://segmentfault.com/a/1190000005793257 在开发过程中,前后端不论是否分离,接口多半是滞后于页面开发的.所以建立一个REST风格的API接口,给前端页面提 ...
- 深入理解java虚拟机读书笔记--java内存区域和管理
第二章:Java内存区域和内存溢出异常 2.2运行时数据区域 运行时数据区分为方法区,堆,虚拟机栈,本地方法栈,程序计数器 方法区和堆是线程共享的区域 虚拟机栈,本地方法栈,程序计数器是数据隔离的数据 ...
- WebDriver高级应用实例(10)
10.1控制HTML5语言实现的视频播放器 目的:能够获取html5语言实现的视频播放器视频文件的地址.时长.控制进行播放暂停 被测网页的网址: http://www.w3school.com.cn/ ...
- 在matlab中实现PCA算法
function [V,S,E]=princa(X) [m,n]=size(X); %计算矩阵的行m和列n %-------------第一步:标准化矩阵-----------------% mv=m ...
- ES代码总结2
本文部分转载于: http://www.cnblogs.com/luxiaoxun/p/4869509.html ElasticSearch的基本用法与集群搭建 一.简介 ElasticSearch ...
- JAVA框架之Hibernate【配置文件详解】
Hibernate配置文件主要功能是配置数据库连接和Hibernate运行时所需的各种属性,配置文件应该位于JAVA应用或者JAVA Web应用的类文件中,刚开始接触Hibernate的时候,感觉Hi ...