什么时候应该使用复合devise模式?

我不明白什么时候应该使用复合devise模式我将从这种devise模式中获得哪些好处? 我访问了这个网站,但它只告诉我关于devise模式的结构,而不是使用它的场景。 我希望对于像我这样开始学习devise模式的程序员来说,这是有好处的。

从devise模式引用,

使用复合模式时

  • 你想表示对象的部分 – 整体层次结构。
  • 您希望客户能够忽略对象和个别对象的组合之间的差异。 客户将统一处理复合结构中的所有物体。

书中常用的一个例子是graphics窗口的显示系统,它可以包含其他窗口和graphics,文本等graphics元素。 组合可以在运行时编写,客户端代码可以操作所有的元素,而不用考虑绘制等常见操作的types。

复合模式是一种非常有用的模式,无论何时您可能需要select性地将一组属于对象的对象视为“相同”,而这些对象实际上是不同的。 通常所使用的例子在处理叶节点方面是相同的,但是该模式也可以扩展到异构列表。

例如,考虑医生访问。 当你去看医生的时候会发生各种各样的事情,你通常首先会看护士或助手,他们会采取你的体温等,然后医生进行检查并做出诊断。 然后医生可以做一些治疗,但是护士经常回来完成。 访问期间进行不同的活动。 你有像重量和温度的观察。 但是,例如,实验室将是一个不同的对象,因为它通常需要一个样本,然后可能被发送出去,并要求在日后logging结果。

所以我们有可以logging所有这些的软件,通常会创build一些类似于以下节点的层次结构:

遭遇:
PreExam
考试
治疗

在这些节点的每一个之下,您将有各种各样的条目,如诊断,观察,实验室程序,诊断,注射等。

这一切都很好,最终你会得到一个结构化的,虽然非常复杂的相遇logging。

现在假设您需要生成结算。 突然间,你面临着一个非常不同的要求。 你的病历需要创build一个非常准确的相遇的画面。 在计费过程中,尽pipe您不关心是谁做了什么或按照什么顺序,实际上您并不在意计费代码以外的活动。 您只需要一个可结算活动列表,即代码。

这个信息不仅embedded到logging中,而且logging也很难遍历,因为它包含了大量不同的对象。 它在分层结构上也是可变的 – 如果你头上有钉子,他们可能会跳过任何一种预检,或考试,然后去治疗。 如果你去拆针,可能没有任何考前或考试。 一年一次的身体没有治疗。 很难枚举这种types的对象图。

复合模式解决了这一切。 您为所有对象定义一个通用接口或基类。 我们称之为“CareEntry”。 CareEntry有一个属性BillingCode。 现在你的Encounter可以看起来像一个简单的容器,里面只有CareEntry对象。 您的结算服务现在可以简单地列举所有内容,而无需担心某个节点(PreExam,Exam)与叶子(体重温度),对象所在的节点(PreExam Exam等)或实际types的目标是(实验室,注射等)。 一切都是一个CareEntry,并统一处理 – 您只需枚举Encounter中的所有CareEntry对象,然后收集每个具有非空账单代码的对象,即可完成。 它是如此简单。

复合模式可让客户统一处理单个对象以及单个对象的组合。
比如双击文件夹就应该打开文件夹。 在文件的两倍,应在相应的程序中打开。
操作是相同的,但基于它是单个对象还是作曲

单个对象和复合对象的通用接口

interface Data{ public void doubleClick(); } 

个别对象实现

 class File implements Data { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void doubleClick() { System.out.println(this.getName()+" file is Opened in a Program "); } } 

综合实施

 class Folder implements Data { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } private List<Data> folder = new ArrayList<Data>(); @Override public void doubleClick() { System.out.println(this.getName() + " folder is Opened"); for(Data data : folder) { data.doubleClick(); } } public void add(Data data) { folder.add(data); } public void remove(Data data) { folder.remove(data); } } 

客户程序

 public class CompositePattern { public static void main(String[] args) { Folder f1 = new Folder();f1.setName("Folder 1"); Folder f2 = new Folder();f2.setName("Folder 2"); Folder f3 = new Folder();f3.setName("Folder 3"); File file1 = new File();file1.setName("File 1"); File file2 = new File();file2.setName("File 2"); File file3 = new File();file3.setName("File 3"); File file4 = new File();file4.setName("File 4"); f1.add(file1); f2.add(file2); f3.add(f2); f3.add(file3); f3.add(file4); f1.doubleClick();f2.doubleClick();f3.doubleClick(); } } 

我经常使用复合devise模式来隐藏集合。 在许多情况下,我们使用完全相同的方式处理集合,因为有很多元素,而且只有一个元素。

那就是问题所在,因为包含集合的类然后成群的foreach循环基本上做同样的事情 – 遍历所有元素并应用一些聚合函数。

为了解决这个问题,我介绍了一个由单个元素实现的接口,以及隐藏这些元素集合的类。 然后复合类的目的是包含所有在客户类中的聚合函数。

您可以在本文中find一些有用的示例: 使用集合

这里的共同点是Composite不一定代表部分 – 整体的关系。 有可能引入复合元素只是为了将循环移出客户端。

下面是一个应用Composite模式来隐藏复合元素背后部分的书籍示例: Composite Design Pattern

当你使用binary trees或其他complex data structures like list of lists of lists等)时,你可能会发现它是必须的,那么当每个元素(类)实现1个接口时,你可以做同样的事情方法在1叶或整个群体 – copping,添加,删除,移动…任何,你已经正确实施。 这非常有用和简单。

答案应该是 –

将对象组成树结构来表示整个部分的层次结构。 复合让客户可以统一处理单个对象和对象的组合。

  • recursion组合
  • “目录包含条目,每个条目都可以是一个目录。”
  • 一对多“有一个”上“是一个”层次“

从论坛复制。

希望这个简单的例子帮助

复合devise模式真实世界的例子,当我们有有相同的父types的实例里面或组件types的机会。

例如: 在外汇交易系统Ex1中

您可能有一个交叉货币对(AUD / EUR) = (AUD / USD和1 /(EUR / USD)) ,这里您的仪器(交叉)可以有两个仪器(直接)。

在另一个例子中有

一个仪器(十字)和仪器(直接)和仪器(十字),可以进一步分为牵引仪器(直接)。 SGD / CZK = USD / SGD(直接)和USD / CZK(交叉)= USD / SGD(直接)和(1 / EUR / USD)

这里的重点是你继续分,直到你没有find所有的直接货币对。

以上可以使用复合devise模式轻松实现。

如果要构build嵌套的类似对象意味着您可以使用复合devise模式,例如:实时如果要基于层次结构显示办公室员工的树结构

在最近学习和尝试过之后,我认识到了一个强大的概念,要记住复合材料。

复合材料隐藏了collections中涉及的复杂性,即通过它们循环,将它们整理出来,过滤一些等,并允许您将它看作是一个单一的有机体。

比如,你在一个狗窝里有一只狗,在另一个狗上有许多狗。 你想给他们喂食并给他们接种疫苗,但是如果他们在一个小时内吃了东西,或者如果他们在过去五个小时内接种了疫苗,他们就不能喂他们,或者如果他们呕吐,给他们接种疫苗等等。

更重要的是,狗品种A在品种B之前吃的包装规则是有规则的,除非品种C狗在其周围并吠叫到肺的顶部。

这很快就会达到一个你根本不想在乎的地步,而只是打电话给一个帮手,告诉他喂“所有的狗”。 或者更好的是,三名助手跟踪喂养,疫苗接种和呕吐,吠叫和包装等所有其他令人敬畏的东西。

通过调用助手,你依赖于组合模式。 你只要去喂养每个狗窝,不pipe是一只狗还是十只狗。 你只是想要狗舍的狗舍自己整理出来,弄清楚它们是如何喂养的,因为你手中的收银员太多了。

所以,对于你来说,Dog是一个IDog,它们是Feed(),Bark(),Vomit()和GetVaccine()。 一个狗窝也是一个狗,你叫狗窝。饲料()。 你完成了。 养犬室必须弄清楚现在要在内部做什么。 它可能有一个计时机制来跟踪每只狗的喂食和其他身体机能的时间。 它全部封装得很整齐。