设计模式-组合模式(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.问题 ...
随机推荐
- 【编程之外】从《海贼王》的视角走进BAT的世界
写在前面的话: 1.从写第一篇博客起到现在篇“纯”技术博客,所以呢-,就想写点不一样的东西,所以就有了这篇文章了 2.本文纯属瞎写,不代表任何第三方的观点.仅仅是出于我对于博客园和那部热血动漫的热爱. ...
- win7 docker 挂载共享目录
在 win7 下用 docker 不像 win10 那样方便,安装包都不一样. 在 win7 下共享一个目录的方法如下: 1. 先设置 win7 到 VirtualBox 中 docker 用的那个虚 ...
- Android自定义组合控件详细示例 (附完整源码)
在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...
- C#6.0语言规范(十一) 结构
结构与类类似,因为它们表示可以包含数据成员和函数成员的数据结构.但是,与类不同,结构是值类型,不需要堆分配.结构类型的变量直接包含结构的数据,而类类型的变量包含对数据的引用,后者称为对象. 结构对于具 ...
- Python-flask跨站请求伪造和跨站请求保护的实现
图中 Browse 是浏览器,WebServerA 是受信任网站/被攻击网站 A,WebServerB 是恶意网站/点击网站 B. (1) 一开始用户打开浏览器,访问受信任网站 A,输入用户名和密码登 ...
- 【dpdk】使用libpcap-PMD驱动收发包
ref: Dpdk programmer’s guide 1. 概述 dpdk不仅提供针对物理和虚拟网卡的pmd驱动(Poll Mode Drivers),还提供两个纯软件的pmd驱动,libpca ...
- Scala的Trait详解
http://article.yeeyan.org/view/178378/358355
- Install vsftpd on centos
安装vsftpd程序. sudo yum -y install vsftpd 启动ftp服务. sudo service vsftp start 添加ftp用户,并设置密码. sudo useradd ...
- CentOS安装Nginx 以及日志管理
环境:CentOS-6.4 Nginx版本:nginx-1.6.2.tar Linux连接工具:XShell VMWare虚拟机上准备两台CentOS: 两台机器做同样操作(后边做负载均衡.高可用的时 ...
- spring cloud(服务消费者(利用ribbon实现服务消费及负载均衡)——初学二)
Ribbon是一个基于HTTP和TCP客户端的负载均衡器,利用ribbon实现服务消费,并实现客户端的负载均衡. 一.准备工作(利用上一节的内容) 启动服务注册中心 启动computer-servic ...