结构类模式(三):组合(Composite)
定义
将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
比较常见的有文件系统:文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。如果你想要描述这样的数据结构,那么你可以使用组合模式。
另外如果使用过Flash,会知道Flash所使用的显示列表就是一个树形结构,每个显示容器都可以包含任意多的显示对象,而显示对象又可以是显示容器。
UML
优点
- 使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
- 更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利。
缺点
- 组合模式不容易限制组合中的构件。
应用场景
- 当你发现需求中是体现部分与整体层次的结构时,以及你希望可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑使用组合模式了。
- 你想表示对象的部分-整体层次结构。
- 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
示例
使用组合模式构建一个树形结构。
Java
import java.util.ArrayList;
import java.util.List; public class Main
{
public static void main(String[] args)
{
try
{
//所有结点都使用基类类型定义
Component root = new Composite(); Component c1 = new Composite();
Component c2 = new Composite(); Component leaf1 = new Leaf();
Component leaf2 = new Leaf();
Component leaf3 = new Leaf(); //添加到树形结构上
root.addChild(c1);
root.addChild(leaf1); c1.addChild(leaf2);
c1.addChild(c2); c2.addChild(leaf3); //执行指定的一个叶子结点
root.getChildAt(0).getChildAt(1).getChildAt(0).doSomething();
}
catch (Exception e)
{
e.printStackTrace();
}
} /**
* 组合组件的基类, 所有树形结构上的结点都必须继承自该类
*/
public static abstract class Component
{
public abstract void addChild(Component child) throws Exception;
public abstract Component getChildAt(int index) throws Exception;
public abstract void removeChild(Component child) throws Exception;
public abstract void doSomething();
} /**
* 容器类
*/
public static class Composite extends Component
{
private List<Component> _children; public Composite()
{
_children = new ArrayList<>();
} @Override
public void addChild(Component child)
{
_children.add(child);
} @Override
public Component getChildAt(int index)
{
return _children.get(index);
} @Override
public void removeChild(Component child)
{
_children.remove(child);
} @Override
public void doSomething()
{
System.out.println("容器对象处理了某个事务");
}
} /**
* 叶子类
*/
public static class Leaf extends Component
{
@Override
public void addChild(Component child) throws Exception
{
throw new Exception("叶子对象不能添加子对象");
} @Override
public Component getChildAt(int index) throws Exception
{
throw new Exception("叶子对象不能获取子对象");
} @Override
public void removeChild(Component child) throws Exception
{
throw new Exception("叶子对象不能移除子对象");
} @Override
public void doSomething()
{
System.out.println("叶子对象处理了某个事务");
}
}
}
结构类模式(三):组合(Composite)的更多相关文章
- 设计模式之结构类模式大PK
结构类模式大PK 结构类模式包括适配器模式.桥梁模式.组合模式.装饰模式.门面模式.享元模式和代理模式.之所以称其为结构类模式,是因 ...
- 设计模式之结构类模式PK
结构类模式包括: 适配器模式 桥梁模式 组合模式 装饰模式 门面模式 享元模式 代理模式 结构类模式着重于如何建立一个软件结构 为什么叫结构类模式呢? 因为他们都是通过组合类或对象产生更大结构以适应更 ...
- 八、结构模式之组合(Composite)模式
组合模式属于对象的结构模式,有时又叫做部分-整体模式,组合模式将对象组织到树结构中,可以用来描述整体与部分的联系.其可以使客户端将单纯元素和组合元素同等对待. 当需求中是体现部分与整体层次的结构时,以 ...
- 结构类模式(四):装饰(Decorator)
定义 动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 特点 装饰对象和真实对象有相同的接口.这样客户端对象就能以 ...
- 结构类模式(七):代理(Proxy)
定义 为其他对象提供一种代理以控制对这个对象的访问. 代理模式也叫做委托模式,它是一项基本设计技巧.许多其他的模式,如状态模式.策略模式.访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应 ...
- 结构类模式(六):享元(Flyweight)
定义 运用共享技术有效的支持大量细粒度的对象. 两个状态 内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的. 外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保 ...
- 结构类模式(五):外观(Facade)
定义 为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用. UML 优点 对客户屏蔽了其子系统组件,因而减少了客户处理对象的数目,并使得子系统实用起来更方便. ...
- 结构类模式(二):桥接(Bridge)
定义 将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化. 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维 ...
- 结构类模式(一):适配器(Adapter)
定义 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 类适配器模式 使用继承的方式实现没有提供的接口从而达到适配到新系统的需求. ...
随机推荐
- UVA 11354 Bond 邦德 (RMQ,最小瓶颈MST)
题意: n个城市,m条路,每条路有个危险值,要使得从s走到t的危险值最小.回答q个询问,每个询问有s和t,要求输出从s到t最小的危险值.(5万个点,10万条边) 思路: 其实要求的是任意点对之间的最小 ...
- HDU 5273 Dylans loves numbers(水题)
题意:给出一个0≤N≤1018,求其二进制中有几处是具有1的,假设相连的1只算1处,比如1101011就是3处. 思路:一个个数,当遇到第一个1时就将flag置为1:当遇到0就将flag置为0.当遇到 ...
- UML时序图
时序图定义 : 描述了对象之间传递消息的时间顺序, 用来表示用例中的行为顺序, 是强调消息时间顺序的交互图; 时序图描述的事物: 时序图描述系统中类和类之间的交互, 将这些交互建模成消息交换, 时序图 ...
- unity, 在保持场景根节点Transform不变且Hierarchy结构不变的前提下整体旋转场景
比如我们摆出下面结构: 其Hierarchy如下: 其中根节点road的Transform是如下干净的原始状态: 现在想保持road的Hierarchy和Transform都不变的情况下将road旋转 ...
- Red and Black ---路线问题
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A ...
- XHTML学习进度备忘
书签:XHTML 高级教程没有看:另外跳过的内容有待跟进 __________________ 学习资源:W3School. _________________ 跳过的内容: 1.“XHTML 简介” ...
- OPENGL学习笔记整理(五):着色语言
有些事情本身就是十分奇怪的.在传统上,图形硬件的设计目的是用于快速执行相同的硬编译指令集.不同的计算步骤可以被跳过,参数可以被调整,但计算本身确实固定不变的.然而,随着技术的发展,却越来越变得可以编程 ...
- C#缓存的一点想法及测试
项目开发中,用到了缓存,其中的一个列表项,可能要多线程处理,就有了下面的想法,具体的问题在代码中有详细说明,见下文. static void Main(string[] args) { 测试缓存的想法 ...
- web前端笔试题
1, 判断字符串是否是这样组成的,第一个必须是字母,后面可以是字母.数字.下划线,总长度为5-20 var reg = /^[a-zA-Z][a-zA-Z_0-9]{4,19}$/; reg.test ...
- Windows Azure存储容器私有,公共容器,公共Blob的区别
当我们在Windows Azure中创建或编辑存储的容器时,需要选择访问类型,本文将描述一下这三个选项的区别. 1. 私有: 默认选项,顾名思义,用户不能通过URL匿名进行访问容器或容器内的任何Blo ...