1. 攻玉集

诗经·小雅·鹤鸣 有云:「他山之石,可以为错。」,又云:「他山之石,可以攻玉」。现在用来指他人的长处可以拿來磨练自己,使自己更加精进。


1.1. M$篇

TechEd2004:

  • SDM231:
    • 项目的五个流程阶段——启动->计划->执行->控制->结束,软件开发的流程特点是循环式的控制阶段——功能需求>设计规范>程序开发>测试;

    • 软件开发项目管理的十大精华指南——1.理解用户和市场要求,明确功能需求和范围。2.撰写完整的设计规范书,包括使用方案和界面。3.制定从下到上的项目进度时间表对其进行追踪。4.以设计规范书为准制定构架设计及开发设计。5.进行源代码审核、提交、版本的管理。6.编程以测试为目标、将测试作为编程的一部分。7.制定完整的测试方案,进行执行的追踪和把关。8.进行严格的更改控制管理。9.设定发行合格标准,进行发行管理。10.记录项目的历程,建立项目历史档案。
    • 软件开发管理的七大关键理念——1.整个开发历程是个循环性的重复过程(将一个开发周期分成多个段里程,多做短阶段的“发行”)。2.注重灵活机动进行调整、避免死板计划。3.设计三步法:使用方案->功能需求->功能设计。4.将测试设计到程序里去。5.渐进发行:镇定纠错,降低失误率、提高稳定性。6.更改控制建立在“三国会议”的意见基础上。7.任何项目都受“金三角”的影响:功能、时间、资源。

  • DAT322:
    • 典型的数据挖掘任务:1.分类-将个体按照预先定义好的标准进行分类。2.规约-规约非顺序类型数。3.聚类-将相同个体分割成组。4.关联-高兴相关性统计。5.时序预测-预测另一组相关数据。6.偏差分析-颤沼数据相区别的原因。7.可视化-图形化显示。
  • DEV343:
    • 性能方面的设计考虑
      • 在适当的时候缓存数据:1.缓存频繁检索的数据以减少往返进程。2.缓存只读引用数据。3.缓存发送给Web服务的数据。4.尽量少地缓存高度不稳当的数据。5.尽量少地缓存敏感数据。
      • 优化网络通讯:1.倾向批量的数据传送。2.避免发送整个数据集。3.将大型数据集分解。4.区分静态和动态数据。
      • 线程处理:1.优先选择异步调用。2.使用线程池代替手工创建线程。3.使用后台线程而不是UI线程。
      • 使用多线程的时机:1.进行网络通信。2.执行长时间的本地操作。3.区分任务的优先级。4.提高应用程序启动和初始化的性能。
      • 事务原则:1.避免网络上的分布式事务。2.将事务限制在某一端执行。3.使用补偿事务替代。
      • 管理可用资源
      • 优化应用程序启动时间:1.优化主窗体类中的成员变量。2.尽可能使用惰性加载。3.使用集中的程序集,但功能独立的类。4.使用预编译。
      • 优化Windows窗体性能:1.小心创建句柄。2.避免创建太多控件。3.使用分页和惰性加载。
      • 性能调整和诊断:1.制定性能目标。2.考虑用户的观点。3.考虑应用程序操作环境。
      • 性能调整过程:1.建立基准。2.收集数据。3.分析结果。4.调整应用程序。5.测试和度量。
  • DEV371:
    • 何时使用多线程:1.通过网络(例如,与Web服务器、数据库或远程对象)进行通信。2.执行需要较长时间因而可能导致UI冻结的本地操作。3.区分各种优先级的任务。4.提高应用程序启动和初始化的性能。
  • SDM244:
    • 灵活性模式
      • 轻型计划:1.奉行改变:从整个的项目开始起就期望计划、需求、和设计都会改变。2.整个开发过程有客户的经常参与,甚至邀请客户来到开发团队的工作处,对正在进行开发的半成品使用、审核、提意见。3.客户直接参加项目的计划的修改。4.整个开发计划是个不断更新的过程。
      • 经常性的发行:1.短期的重复开发周期。2.采取所谓的“时间盒”方法-将预定的预期锁定为一个发行周期。3.保持产品接近发行的状态。
      • 简化的设计:1.先对那些已经确定了的功能进行设计。2.意识到任何多余的功能,一旦加入到软件产品中,会增加修改和维护的费用。
      • 以测试为驱动的开发:1.编写产品的程序前先写测试的程序。2.单元测试应该全部自动化。3.单元测试的运行应该成为开发的日常工作。
      • 重新组合:1.重组:在不改变功能和行为的前提下,对软件的内部结构为更容易和更方便改动而进行设计和编程上的改动。2.采用渐进式的设计方式来逐渐完善程序。
      • 连续性的整合:1.将开发团队多人开发的各功能组件进行整合,最后生成完整的软件系统或产品,应该是一个经常进行的、连续不断的过程。2.每天或每几小时进行总汇编和产品建造(Daily Build)
      • 及时文件的编辑:1.将产品或系统的使用手册、维护条例、使用参考等等一系列文档根据各功能开发的进度进行编辑。2.趁着概念新鲜明确,将它们写入文档。
  • SDM302:
    • 什么是“BUG”:1.造成系统崩溃,或停止运行。2.实现的功能与设计不一致。3.界面、消息、提示不够准确,不标准,不友好。4.与该兼容的系统不兼容。5.文档与帮助信息不准确,不完整,可读性不好。尚有未完成的工作,或为实现的功能。6.建议和有助于改善产品的信息。
  • DEV365:
    • 性能管理:
      • 顺其自然:1.更注重功能开发&希望程序足够快。2.开发人员最通常采用的方法。3.负面因素:<1>性能问题经常源于最初的设计。<2>性能问题往往不能依靠简单的调整解决。<3>在软件开发后期解决构架与设计问题将非常昂贵,容易导致错过最后期限与结束日期的低信心。

      • 优化所有代码:1.开发人员尽力使所有代码以最快速度运行。2.负面因素:<1>高度优化的源代码很少被执行(10/90)。<2>过度漫长的开发周期。<3>贻误甚至失去市场机会。

      • 性能工程:1.把性能与伸缩性的考虑融入开发周期中。2.定义性能与伸缩性的目标。3.针对目标进行定期测试。3.根据测试结果进行调整。4.有的放矢。
    • 构架设计的主要考虑因素:1.Scale Up vs Scale Out。2.逻辑分区。3.充分利用多处理器的力量。4.线程模型。5.最大限度地减少不同组件之间的序列化。6.客户端与中间层缓冲。7.无状态与全状态。
    • 单进程与多进程:
      • 单进程:1.可靠性与安全性较好。2.进程间通讯(IPC)比较昂贵。3.在32字节的硬件上可以访问>4GB的地址。

      • 使用多线程的单进程:1.异常情况处理能俘获出错的线程。2.避免了进程间通讯的消耗。3.在32字节的硬件上可利用AWE访问高达64GB的地址空间。
    • 线程模型:
      • 理想模型:线程数=CPU数并且线程永不阻塞;实现:1.用线程来简化编程,而不是提高并行性。2.没有使用I/O异步处理。3.在不同的功能区不加分辨地使用不同的线程池。
      • 优化方案:1.总线程数不应比CPU数高很多。2.主要线程不应阻塞,除非等待工作项目。3.尽可能使用异步I/O。4.在无法避免同步I/O时,转手到专门的线程池。5.根据不同线程池的特性设置合适的线程优先权。
      • 线程与同步:多条线程改变共享数据,从而需要使用同步物体(锁定);系统构架应尽量减少使用同步物体:1.线程应主要更新私有数据。2.尽可能使用无锁定技术。
      • 同步:1.避免在不必要的情况下使用锁定。2.通过分区来减少锁定。3.在持有锁定时:<1>把持有时间减至最低。<2>避免I/O,SetEvent。4.尽量避免同时获得多个锁定:在必要的前提下,可运用锁定排序来减少死锁。5.假如绝大多数数据访问是读,使用读写锁定。

    • 网络I/O:
      • 1.应尽量使用异步I/O。2.尽可能复合连接。3.消息成批发送可减低协议消耗的比例。4.在高流量的连接上,一次读取大量数据。5.简明有效的协议。6.连接限制/节流。7.避免引起连续饥饿。8.不要进行额外的数据拷贝。9.适当调节连接的TCP发送与接受缓冲区大小。10.连接管理。
    • 存储与缓冲:
      • 1.服务器系统应永不分页。2.预先分配存储池,并循环使用。3.考虑每条线程拥有单独的存储堆:甚至考虑每个用户连接拥有一个小的存储堆。4.存储碎片化。5.注意不分页存储池的设置。6.避免不必要的存储拷贝。7.减少使用Virtual Alloc/Free的频率。
  • OFC281:
    • 搜索的四项关键技术:信息采集,建立索引,查询,回应。
    • Google的PageRank算法:假设1,一个从页面A到页面B的链接是页面A作者对页面B的一个推荐。假设2,如果页面A和页面B相互链接,那么它们很有可能是关于一个主题的。假设3,如果页面C既链接了页面A有链接了页面B,那么可能是页面A和页面B联合链接。如果A和B被多次联合链接,那么A和B和C有可能相关。

1.2. 设计模式

1.2.1. JAVA

创建模式:

  • Factory:
    • 定义:提供创建对象的接口。
    • 工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
    • 工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory)。这两个模式区别在于需要创建对象的复杂程度上。
  • Prototype:
    • 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
    • Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
    • 因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单。
  • Builder:
    • 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们。用户不知道内部的具体构建细节。Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到。
    • 是为了将构建复杂对象的过程和它的部件解耦.注意: 是解耦过程和部件.因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开。
    • 首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部件的创建分别开来,分别用Builder类和Director类来表示。首先,需要一个接口,它定义如何创建复杂对象的各个部件;用Director构建最后的复杂对象,而在上面Builder接口中封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就是说Director的内容是如何将部件最后组装成成品;Builder的具体实现"ConcreteBuilder":通过具体完成接口Builder来构建或装配产品的部件,定义并明确它所要创建的是什么具体东西,提供一个可以重新获取产品的接口;

    • Builder模式的应用:在Java实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池."池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能.修改Builder模式中Director类使之能诊断"断肢"断在哪个部件上,再修复这个部件。
  • Singleton:
    • 定义:Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。还有, singleton能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛中的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加1,如果你要把这个数字永久保存到数据库,你可以在不修改单态接口的情况下方便的做到。另外方面,Singleton也能够被无状态化。提供工具性质的功能,Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection)。我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的,因为被装入的类实际也属于资源。
    • 有时在某些情况下,使用Singleton并不能达到Singleton的目的,如有多个Singleton对象同时被不同的类装入器装载;在EJB这样的分布式系统中使用也要注意这种情况,因为EJB是跨服务器,跨JVM的。
    • Singleton模式看起来简单,使用方法也很方便,但是真正用好,是非常不容易,需要对Java的类 线程 内存等概念有相当的了解。

结构模式:

  • Facade:
    • 定义: 为子系统中的一组接口提供一个一致的界面。
    • Jsp中最通常的对数据库操作办法.在应用中,经常需要对数据库操作,每次都写上述一段代码肯定比较麻烦,需要将其中不变的部分提炼出来,做成一个接口,这就引入了facade外观对象.如果以后我们更换Class.forName中的<driver>也非常方便,比如从Mysql数据库换到Oracle数据库,只要更换facade接口中的driver就可以。

  • Proxy:
    • 定义: 为其他对象提供一种代理以控制对这个对象的访问。
    • Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理。
    • 1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive中就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限.2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.举例两个具体情况:(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy来代替真正的图片.(2)如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存. 所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系。

    • Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用。
  • Adapter:
    • 定义:将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份。
    • 我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口。使用Adapter,在这两种接口之间创建一个混合接口。
    • 实现Adapter方式,其实"think in Java"的"类再生"一节中已经提到,有两种方式:组合(composition)和继承(inheritance)。
  • Composite:
    • 定义:将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
    • Composite比较容易理解,想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时,Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。所以Composite模式使用到Iterator模式,和Chain of Responsibility模式类似。
    • 1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
    • 首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多,Composite却有个规定,那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们(或称部件Component)。
  • Decorator:
    • 定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。
    • 我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了"即插即用"的方法,在运行期间决定何时增加何种功能。
  • Bridge:
    • 定义:将抽象和行为划分开来,各自独立,但能动态的结合。
    • 通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以下两种:1. 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了.2.实际应用上,常常有可能在这多个concrete class之间有概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为。
    • Bridge模式在EJB中的应用:EJB中有一个Data Access Object (DAO)模式,这是将商业逻辑和具体数据资源分开的,因为不同的数据库有不同的数据库操作.将操作不同数据库的行为独立抽象成一个行为接口DAO。
  • Flyweight:
    • 定义:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类)。
    • 面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight中两个重要概念内部状态intrinsic和外部状态extrinsic之分.说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,很显然,在这里需要产生不同的新对象,所以Flyweight模式中常出现Factory模式.Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个Flyweight pool(模式池)来存放内部状态的对象.Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度.应用场合很多:比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们可以将这些字符串储存在Flyweight池(pool)中。

行为模式:

  • Template:
    • 定义:定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中。
  • Memento:
    • memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态。
    • Memento模式的缺点是耗费大,如果内部状态很多,再保存一份,无意要浪费大量内存。
    • Memento模式在Jsp+Javabean中的应用:在Jsp应用中,我们通常有很多表单要求用户输入,比如用户注册,需要输入姓名和Email等, 如果一些表项用户没有填写或者填写错误,我们希望在用户按"提交Submit"后,通过Jsp程序检查,发现确实有未填写项目,则在该项目下红字显示警告或错误,同时,还要显示用户刚才已经输入的表项。
  • Observer:
    • 观察者,观察对象的变化并报告。
  • Chain of Responsibility:
    • 定义:Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。
    • CoR的优点:因为无法预知来自外界的请求是属于哪种类型,每个类如果碰到它不能处理的请求只要放弃就可以。无疑这降低了类之间的耦合性。
    • 缺点是效率低,因为一个请求的完成可能要遍历到最后才可能完成,当然也可以用树的概念优化。 在Java AWT1.0中,对于鼠标按键事情的处理就是使用CoR,到Java.1.1以后,就使用Observer代替CoR。扩展性差,因为在CoR中,一定要有一个统一的接口Handler.局限性就在这里。
  • Command:
    • 定义:不少Command模式的代码都是针对图形界面的,它实际就是菜单命令,我们在一个下拉菜单选择一个命令时,然后会执行一些动作.将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command模式,换句话说,本来用户(调用者)是直接调用这些命令的,如菜单上打开文档(调用者),就直接指向打开文档的代码,使用Command模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了.显然这样做的好处是符合封装的特性,降低耦合度,Command是将对行为进行封装的典型模式,Factory是将创建进行封装的模式,(好象喜欢将简单的问题复杂化, 喜欢在不同类中增加第三者,当然这样做有利于代码的健壮性 可维护性 还有复用性)
    • 具体的Command模式代码各式各样,因为如何封装命令,不同系统,有不同的做法.下面事例是将命令封装在一个Collection的List中,任何对象一旦加入List中,实际上装入了一个封闭的黑盒中,对象的特性消失了,只有取出时,才有可能模糊的分辨出。典型的Command模式需要有一个接口.接口中有一个统一的方法,这就是"将命令/请求封装为对象"。
    • 使用Command模式的一个好理由还因为它能实现Undo功能.每个具体命令都可以记住它刚刚执行的动作,并且在需要时恢复.Command模式在界面设计中应用广泛.Java的Swing中菜单命令都是使用Command模式,由于Java在界面设计的性能上还有欠缺,因此界面设计具体代码我们就不讨论,网络上有很多这样的示例。
  • State:
    • 定义: 不同的状态,不同的行为;或者说,每个状态有着相应的行为。
    • State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了.不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在数据库系统中出现频率比较高,我们经常会在一个数据表的尾部,加上property属性含义的字段,用以标识记录中一些特殊性质的记录,这种属性的改变(切换)又是随时可能发生的,就有可能要使用State。
    • 在实际使用,类似开关一样的状态切换是很多的,但有时并不是那么明显,取决于你的经验和对系统的理解深度。
  • Strategy:
    • Strategy是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类。
    • Stratrgy应用比较广泛,比如, 公司经营业务变化图, 可能有两种实现方式,一个是线条曲线,一个是框图(bar),这是两种算法,可以使用Strategy实现。
    • 实际整个Strategy的核心部分就是抽象类的使用,使用Strategy模式可以在用户需要变化时,修改量很少,而且快速。
    • Strategy和Factory有一定的类似,Strategy相对简单容易理解,并且可以在运行时刻自由切换。Factory重点是用来创建对象。
    • Strategy适合下列场合:1.以不同的格式保存文件;2.以不同的算法压缩文件;3.以不同的算法截获图象;4.以不同的格式输出同样数据的图形,比如曲线 或框图bar等。
  • Mediator:
    • 定义:用一个中介对象来封装一系列关于对象交互行为。
    • 各个对象之间的交互操作非常多;每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉及到修改很多其他对象的行为,如果使用Mediator模式,可以使各个对象间的耦合松散,只需关心和 Mediator的关系,使多对多的关系变成了一对多的关系,可以降低系统的复杂性,提高可修改扩展性。
    • 每个成员都必须知道Mediator,并且和 Mediator联系,而不是和其他成员联系.至此,Mediator模式框架完成,可以发现Mediator模式规定不是很多,大体框架也比较简单,但实际使用起来就非常灵活.Mediator模式在事件驱动类应用中比较多,例如界面设计GUI.;聊天,消息传递等,在聊天应用中,需要有一个MessageMediator,专门负责request/reponse之间任务的调节.MVC是J2EE的一个基本模式,View Controller是一种Mediator,它是Jsp和服务器上应用程序间的Mediator。

  • Interpreter:
    • 定义:定义语言的文法 ,并且建立一个解释器来解释该语言中的句子。
    • Interpreter似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个语言的文法。
  • Visitor:
    • 定义:作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作。在Java中,Visitor模式实际上是分离了collection结构中的元素和对这些元素进行操作的行为。
    • Java的Collection(包括Vector和Hashtable)是我们最经常使用的技术,可是Collection好象是个黑色大染缸,本来有各种鲜明类型特征的对象一旦放入后,再取出时,这些类型就消失了.那么我们势必要再来判断。
    • 前提:前提对象群结构中(Collection) 中的对象类型很少改变,也就是说访问者的身份类型很少改变,如上面中Visitor中的类型很少改变,如果需要增加新的操作,比如上例中我们在ConcreteElement具体实现外,还需要新的ConcreteElement2 ConcreteElement3.可见使用Visitor模式是有前提的,在两个接口Visitor和Visitable中,确保Visitor很少变化,变化的是Visitable,这样使用Visitor最方便.如果Visitor也经常变化, 也就是说,对象群中的对象类型经常改变,一般建议是,不如在这些对象类中逐个定义操作.但是Java的Reflect技术解决了这个问题。