首页 java高手真经ch10

java高手真经ch10

举报
开通vip

java高手真经ch10 第 10课 设计模式概述 在实际的工作和生活中,我们经常会遇到如下的说法:生产模式、管理模式、应用模式等。所谓的模 式,就是从不断重复出现的事件中发现和抽象出的规律,是解决问题的经验的总结。只要再次重复出现, 就可以使用原有的经验去解决。 模式是一种规律的抽象,模式可以使用“模型”来表述。因此,软件的模式就是软件模型。与软件架 构和建筑设计的对比关系相似,软件的模式就好比生产模具,使用模具可以生产出无数个相似的产品,而 使用软件模式则可以解决无数个相似的软件设计问题。 设计模式是一种软件设计思路,...

java高手真经ch10
第 10课 设计模式概述 在实际的工作和生活中,我们经常会遇到如下的说法:生产模式、管理模式、应用模式等。所谓的模 式,就是从不断重复出现的事件中发现和抽象出的规律,是解决问题的经验的总结。只要再次重复出现, 就可以使用原有的经验去解决。 模式是一种规律的抽象,模式可以使用“模型”来表述。因此,软件的模式就是软件模型。与软件架 构和建筑设计的对比关系相似,软件的模式就好比生产模具,使用模具可以生产出无数个相似的产品,而 使用软件模式则可以解决无数个相似的软件设计问题。 设计模式是一种软件设计思路,它与编程语言无关,可以运用在任意的设计语言中,因此你经常可以 看到在各种语言中都有模式的身影。接下来我们将从模式的概念出发,讲解软件模式的整体框架、设计原 则和设计要素。 z 了解设计模式:讲解设计模式的概念、产生历史、核心思想和使用优势。 z 设计模式的分类:将 GoF所著的《设计模式》一书中列举的 23种设计模式分为创建型模式、结 构型模式和行为型模式。另外,近来这一清单又增加了一些类别,例如,并发型模式、线程池模 式、Java EE企业技术上的模式等。 z 设计模式六大原则:包括开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、迪米特法则、 合成复用原则。 在最后讲解本书讲解模式的思路和特点。 10.1 了解设计模式 首先从以下几个方面来了解设计模式: z 设计模式的概念。 z 设计模式的产生—23种设计模式与 GoF“四人帮”。 z 设计模式不是技术而是思想—构建可重用的程序。 z 为什么要使用设计模式。 10.1.1 设计模式的概念 模式,即 Pattern,其实就是解决某一类问题的 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 论。把解决某类问题的方法总结归纳到理论 高度,那就是模式。Alexander给出的经典定义是:每个模式都描述了一个在我们的环境中不断出现 的问题,然后描述了该问题的解决 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 的核心。通过这种方式,你可以无数次地使用那些已有的解 决方案,无须再重复相同的工作。模式有不同的领域,建筑领域有建筑模式,软件设计领域也有设 计模式。当一个领域逐渐成熟的时候,自然会出现很多模式。 设计模式(Design Pattern)这个术语是在 20世纪 90年代,由 Erich Gamma等人从建筑设计领 域引入到计算机科学中的,是对软件设计中普遍存在(反复出现)的各种问题所提出的解决方案。 设计模式并不直接用来完成程序代码的编写,而是描述在各种不同情况下要怎么解决问题的一种方 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 132 UML建模+设计模式+面向服务架构 案。面向对象设计模式通常以类别或物件来描述其中的关系和相互作用,但不涉及用来完成应用程 序的特定类别或物件。算法不能算是一种设计模式,因为算法主要用来解决计算上的问题,而非设 计上的问题。设计模式主要是使不稳定的依赖于相对稳定、具体依赖于相对抽象,避免会引起麻烦 的紧耦合,以增强软件适应变化的能力。并非所有的软件模式都是设计模式,设计模式特指软件设 计层次上的问题。还有其他非设计模式的模式,如架构模式。 10.1.2 设计模式的产生—23种设计模式与 GoF“四人帮” 1977 年到 1979 年,建筑师克里斯托佛·亚历山大编制了一本汇集设计模式的书。但是这种设 计模式的思想在建筑设计领域里的影响,远没有后来在软件开发领域里传播得广泛。 在 1987年,肯特·贝克和沃德·坎宁安利用克里斯托佛·亚历山大在建筑设计领域里的思想开 发了设计模式,并把此思想应用在 Smalltalk中的图形用户接口的生成中。一年后,Erich Gamma在 他的苏黎世大学博士毕业 论文 政研论文下载论文大学下载论文大学下载关于长拳的论文浙大论文封面下载 中开始尝试把这种思想改写为适用于软件开发。James Coplien在 1989 年至 1991年也在利用相同的思想致力于 C++的开发,而后于 1991年发表了他的著作《Advanced C++ Idioms》。就在这一年 Erich Gamma 得到了博士学位,然后去了美国,在那与 Richard Helm、Ralph Johnson、John Vlissides 合作出版了《Design Patterns-Elements of Reusable Object-Oriented Software》 一书,中文名为《设计模式—可重用的面向对象软件设计》,在此书中共收录了 23个设计模式。 这 4位作者在软件开发领域里也以他们的匿名著称 Gang of Four(四人帮,简称 GoF),并且 是他们在此书中的协作导致了软件设计模式的突破。有时这个匿名 GoF 也会用于指《设计模式》 这本书。 10.1.3 设计模式不是技术而是思想—构建可重用的程序 就 Java语言体系来说,GoF的设计模式是 Java基础知识和 J2EE框架知识之间一座隐形的桥。 学习 Java的人越来越多,但是一直徘徊在语言、语法、功能、API层次的开发者不在少数,真正掌 握 Java中接口或抽象类的不是很多。实际上,Java的接口或抽象类是真正体现 Java思想的核心所在。 GoF 的设计模式表面上好像也是一种具体的技术,而且新的设计模式也在不断出现。实际上, GoF 的设计模式并不是一种具体的技术,它讲述的是思想,不仅仅展示了接口或抽象类在实际案例 中的灵活应用和智慧,还让你能够真正掌握接口或抽象类的应用,从而在原来的 Java语言基础上跃 进一步。更重要的是,GoF的设计模式反复向你强调一个宗旨:要让你的程序尽可能“可重用”。 10.1.4 为什么要使用设计模式 面向对象的语言(如 Java、C++等)使软件的开发效率得到很大的提升,开发成本和开发难度 得到很大的降低,同时软件的质量也在不断提升。面向对象的特点是抽象、继承、多态,因此评判 面向对象的软件的一个很重要的 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 就是可重用性。一个可重用的软件就需要有一个可重用的良好 的设计。良好的软件设计需要具有丰富经验的设计者不断积累经验,这些经过无数开发人员筛选最 后留下来的就是我们可以安心重用的设计,即模式。 设计模式是一个非常强大的工具,开发人员或架构师可使用它参与任何开发项目。使用设计模 式具有以下优势: z 快速解决问题—设计模式可确保通过熟知和公认的解决方案解决常见问题。大多数问题 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 133 可能已经被其他个人或开发小组解决了。因此,模式提供了一种在开发人员和组织之间共 享可使用的解决方案的机制。 z 提高正确率—可确保更快地开发正确的代码,并降低在设计或实现中出现错误的可能性。 z 沟通作用—设计模式在工程小组成员之间提供了通用的语义。使用一组共同的设计术语 和准则对成功完成项目来说是至关重要的。 z 节省时间—设计模式可以节省大量的时间。 我们学习模式的目的不仅仅是利用这些模式进行重用且设计良好的软件,而是要从中得到灵感, 用新的模式来弥补软件中现有模式不能完成的软件设计,优化重用软件。 10.2 设计模式的分类 在《设计模式》这本书中列举并描述了 23种设计模式,分为创建型模式、结构型模式和行为型 模式。另外,近来这一清单又增加了一些类别,例如,并发型模式、线程池模式、Java EE企业技术 的多层应用程序上的模式等。下面来看看每一种类型包含哪些设计模式。 10.2.1 创建型模式 GoF中共描述了 5种创建型模式。 1.工厂方法模式(Factory Method) 定义一个接口用于创建对象,但是让子类决定初始化哪个类。工厂方法把一个类的初始化下放 到子类。 2.抽象工厂模式(Abstract Factory) 为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂 中选出相应的系列创建一个具体的工厂类。 3.单例模式(Singleton) 确保一个类只有一个实例,并提供对该实例的全局访问。 4.建造者模式(Builder) 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 5.原型模式(Prototype) 用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。 此外,扩展的创建型模式还包括如下。 z 懒惰初始化模式:推迟对象的创建、数据的计算等需要耗费较多资源的操作,只有在第一 次访问的时候才执行。 z 对象池模式:通过回收利用对象避免获取和释放资源所需的昂贵成本。 10.2.2 结构型模式 GoF中共描述了 7种结构型模式。 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 134 UML建模+设计模式+面向服务架构 1.适配器模式(Adapter) 将某个类的接口转换成客户端期望的另一个接口表示。适配器模式可以消除由于接口不匹配所 造成的类兼容性问题。 2.装饰器模式(Decorator) 向某个对象动态地添加更多的功能。装饰器模式是除类继承外另一种扩展功能的方法。 3.代理模式(Proxy) 为其他对象提供一个代理以控制对这个对象的访问。 4.外观模式(Facade) 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这 一子系统更加容易使用。 5.桥接模式(Bridge) 将一个抽象与实现解耦,以便两者可以独立变化。 6.组合模式(Composite) 把多个对象组成树状结构来表示局部与整体,这样用户可以一样地对待单个对象和对象的组合。 7.享元模式(Flyweight) 通过共享以便有效地支持大量小颗粒对象。 此外,扩展的结构型模式还包括如下。 z 单次访问者(Single-serving Visitor):优化被分配的执行访问者,让它只使用一次然后删除。 z 层次访问者(Hierarchical Visitors):提供一种方法访问每个节点层次的数据结构,如一 棵树。 10.2.3 行为型模式 GoF中共描述了 11种行为型模式。 1.策略模式(Strategy) 定义一个算法的系列,将其各个分装,并且使它们有交互性。策略模式使得算法在用户使用的 时候能独立改变。 2.模板方法模式(Template Method) 模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,然后声明 一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而 对剩余的逻辑有不同的实现。先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。 3.观察者模式(Observer) 在对象间定义一个一对多的联系,当一个对象改变了状态时,所有其他相关的对象会被 通知 关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知 并 且自动刷新。 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 135 4.迭代子模式(Iterator) 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需暴露该对象的内部表示。 5.责任链模式(Chain of Responsibility) 为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求,需要将这些 对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。 6.命令模式(Command) 将一个请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化,对请求排队或记 录请求日志,以及支持可取消的操作。 7.备忘录模式(Memento) 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破 坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这 个对象还原到存储起来的状态。 8.状态模式(State) 让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取 得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。 9.访问者模式(Visitor) 封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改,接受这个操作的数据 结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的 操作之间的耦合解脱开,使得操作集合可以相对自由的演化。 10.中介者模式(Mediator) 包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶 合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用 可以彼此独立的变化。 11.解释器模式(Interpreter) 给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语 言中的句子。 10.2.4 并发型模式 后来扩展的并发型模式有: z 主动对象模式(Active Object)。 z 阻碍模式(Balking)。 z 双重检查锁定(Double Checked Locking)。 z 守卫模式(Guarded)。 z 领导者/追随者模式(Leaders/Followers)。 z 监测对象模式(Monitor object)。 z 读写锁模式(Read write lock)。 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 136 UML建模+设计模式+面向服务架构 z 调度模式(Scheduler)。 10.2.5 线程池模式 后来扩展的线程池模式有: z 线程特定存储模式(Thread-Specific Storage)。 z 反应器(Reactor)。 10.3 设计模式六大原则 我们已经了解到,设计模式体现的是软件设计的思想,而不是软件技术,它重在使用接口与抽 象类来解决各种问题。在使用这些设计模式时,应该首先遵守如表 10-1所示的六大原则。 表 10-1 设计模式六大原则 原 则 含 义 具 体 方 法 开闭原则 对扩展开放,对修改关闭 多使用抽象类和接口 里氏代换原则 基类可以被子类替换 使用抽象类继承,不使用具体类继承 合成复用原则 要依赖于抽象,不要依赖于具体 针对接口编程,不针对实现编程 接口隔离原则 使用多个隔离的接口,比使用单个接口好 建立最小的接口 迪米特法则 一个软件实体应当尽可能少地与其他实体发生相互作用 通过中间类建立联系 依赖倒转原则 尽量使用合成/聚合,而不是使用继承 尽量使用合成/聚合,而不是使用继承 下面我们通过简单的实例来讲解这六大原则的具体含义。 10.3.1 开闭原则(Open Closed Principle) 通常,对于开发完的代码都需要多种测试才能够投入使用,这包括: z 首先要经过开发人员的单元测试、集成测试。 z 然后再到测试人员的白盒测试、黑盒测试。 z 最后还要由用户进行一定的测试。 经过漫长的测试,代码才能够投入使用。但是软件产品的维护和升级又是一个永恒的话题,在 维护的过程中,你可能要不断地增加一些小功能;在升级的过程中,你要增加一些较大的功能。 因此,软件产品随时都有扩展功能的要求。这种功能的扩展,就要求我们改变原有的代码。但 是,对原代码的修改就会深刻地影响到原来的功能的方方面面: z 可能对旧代码引入了新的错误,使你不得不对旧代码进行大规模的修改。 z 可能引起你不得不重新构造系统的架构。 z 即使新增的代码对旧代码没有影响,你也不得不对原来的系统做一个全面的测试。 所有上述列出来的问题,都是对系统功能进行扩展所不能承受的代价。换句话说,我们设计出 来的系统,一定要是扩展性良好的系统。如何才能够设计出扩展性良好的系统呢?这就需要在软件 系统设计时遵守开闭原则: 软件系统必须对扩展开放,对修改关闭。 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 137 换句话说,我们的系统必须是可扩展的系统,而不是可修改的系统。 做到开闭原则,就注意以下两点。 1)多使用抽象类 在设计类时,对于拥有共同功能的相似类进行抽象化处理,将公用的功能部分放到抽象类中, 所有的操作都调用子类。这样,在需要对系统进行功能扩展时,只需要依据抽象类实现新的子类即 可。如图 10-1所示,在扩展子类时,不仅可以拥有抽象类的共有属性和共有函数,还可以拥有自定 义的属性和函数。 抽象类 共有属性 共有函数() 子类1 属性1 共有属性 函数1() 共有函数() 子类2 属性2 共有属性 函数2() 共有函数() 子类3 属性3 共有属性 函数3() 共有函数() 图 10-1 继承抽象类 2)多使用接口 与抽象类不同,接口只定义子类应该实现的接口函数,而不实现公有的功能。在现在大多数的 软件开发中,都会为实现类定义接口,这样在扩展子类时实现该接口。如果要改换原有的实现,只 需要改换一个实现类即可。如图 10-2所示,各子类由接口类定义了接口函数,只需要在不同的子类 中编写不同的实现即可,当然也可以实现自有的函数。 图 10-2 实现接口 以上两点将会在后续的各个设计模式中得到充分的体现。 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 138 UML建模+设计模式+面向服务架构 10.3.2 里氏代换原则(Liskov Substitution Principle) 里氏代换原则是由麻省理工学院(MIT)计算机科学实验室的Liskov女士,在 1987年的OOPSLA 大会上发表的一篇文章《Data Abstraction and Hierarchy》里面提出来的,主要阐述了有关继承的一些 原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中的蕴涵的原理。2002年, 软件工程大师Robert C. Martin,出版了一本《Agile Software Development Principles Patterns and Practices》,在文中他把里氏代换原则最终简化为一句话:“Subtypes must be substitutable for their base types”,也就是说,子类必须能够替换成它们的基类。 我们把里氏代换原则解释得更完整一些:在一个软件系统中,子类应该可以替换任何基类能够 出现的地方,并且经过替换以后,代码还能正常工作。子类也能够在基类的基础上增加新的行为。 里氏代换原则是对开闭原则的补充,它讲的是基类和子类的关系。只有当这种关系存在时,里 氏代换关系才存在。 “正方形是长方形”是一个理解里氏代换原则的最经典的例子。在数学领域里,正方形毫无疑 问是长方形,它是一个长宽相等的长方形。所以,应该让正方形继承自长方形。 长方形类如程序 10-1所示。 程序 10-1 长方形类 Rectangle.java package principle.liskovsubstitution; public class Rectangle { private int height; private int width; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } } 继承了长方形的正方形类如程序 10-2所示。 程序 10-2 正方形类 Square.java package principle.liskovsubstitution; public class Square extends Rectangle { public void setWidth(int width) { 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 139 super.setWidth(width); super.setHeight(width); } public void setHeight(int height) { super.setWidth(height); super.setHeight(height); } } 由于正方形的长度和宽度必须相等,所以在方法 setLength()和 setWidth()中,对长度和宽度赋值 相同。程序 10-3所示的测试类中的函数 zoom()用来增加长方形的长和宽。 程序 10-3 测试类 TestRectangle.java package principle.liskovsubstitution; public class TestRectangle { public void zoom(Rectangle rectangle, int width, int height) { rectangle.setWidth(rectangle.getWidth() + width); rectangle.setHeight(rectangle.getHeight() + height); } } 显然,当增加的长度和宽度不同时,不能够将其中的长方形换成其子类正方形。这就违反了里 氏代换原则。 为了符合里氏代换原则,我们可以为长方形和正方形创建一个父类 Base,并在其中定义好共有 的属性,并定义一个 zoom()抽象函数,如程序 10-4所示。 程序 10-4 父类 Base.java package principle.liskovsubstitution; public abstract class Base { private int height; private int width; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public abstract void zoom(int width, int height); } Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 140 UML建模+设计模式+面向服务架构 长方形类继承自该父类,并编写自己的 zoom()实现函数,如程序 10-5所示。 程序 10-5 修改后的长方形类 BaseRectangle.java package principle.liskovsubstitution; public class BaseRectangle extends Base { public void zoom(int width, int height) { setWidth(getWidth() + width); setHeight(getHeight() + height); } } 正方形类也继承自该父类,并编写自己的 zoom()实现函数,如程序 10-6所示。 程序 10-6 修改后的正方形类 BaseSquare.java package principle.liskovsubstitution; public class BaseSquare extends Base { public void setWidth(int width) { super.setWidth(width); super.setHeight(width); } public void setHeight(int height) { super.setWidth(height); super.setHeight(height); } public void zoom(int width, int height) { int length = (width + height) /2; setWidth(getWidth() + length); setHeight(getHeight() + length); } } 编写测试函数如程序 10-7所示。 程序 10-7 修改后的测试类 BastTest.java package principle.liskovsubstitution; public class BastTest { public void zoom(Base base, int width, int height) { base.zoom(width, height); } } 此时的 Base类可以被它的子类 Rectangle和 Square所替代,而不用改变测试代码。这就是符合 里氏代换原则的编写方式。 由此可见,在进行设计的时候,我们尽量从抽象类继承,而不是从具体类继承。如果从继承等 级树来看,所有叶子节点应当是具体类,而所有的树枝节点应当是抽象类或者接口。当然这只是一 个一般性的指导原则,使用的时候还要具体情况具体分析。 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 141 10.3.3 依赖倒转原则(Dependence Inversion Principle) 开闭原则的主要机制就是依赖倒转原则,这个原则的内容是:要依赖于抽象,不要依赖于具体, 即要针对接口编程,不针对实现编程。 依赖也就是耦合,共分为下面 3种。 z 零耦合(Nil Coupling)关系:两个类没有依赖关系。 z 具体耦合(Concrete Coupling)关系:两个具体的类之间有依赖关系,如果一个具体类直接 引用另外一个具体类,就是这种关系。 z 抽象耦合(Abstract Coupling)关系:这种关系发生在一个具体类和一个抽象类之间,这样 就使必须发生关系的类之间保持最大的灵活性。 依赖倒转原则要求客户端依赖于抽象耦合,抽象不应当依赖于细节,细节应当依赖于抽象。这 个原则的另外一个表述就是:要针对接口编程,不要对实现编程。程序在需要引用一个对象时,应 当尽可能地使用抽象类型作为变量的静态类型,这就是针对接口编程的含义。依赖倒转原则是达到 开闭原则的途径。 要做到依赖倒转原则,使用抽象方式耦合是关键。由于一个抽象耦合总要涉及具体类从抽象类 继承,并且需要保证在任何引用到某类的地方都可以改换成其子类,因此,里氏代换原则是依赖倒 转原则的基础,依赖倒转原则是 OOD的核心原则,设计模式的研究和应用都是用它作为指导原则的。 再拿上一节的正方形和长方形为例,在最后的测试函数中,正确的方式是使用抽象类作为函数 参数: public class BastTest { public void zoom(Base base, int width, int height) { base.zoom(width, height); } } 即针对抽象类编程,如果将它换成如下的针对具体类的操作: public class BastTest { public void zoom(Rectangle rectangle, int width, int height) { rectangle.zoom(width, height); } } 这样该类就违反了依赖倒转原则,就不能够复用做正方形的操作了。 依赖倒转原则虽然强大,但是也很难实现。另外,依赖倒转原则是假定所有的具体类都会变化, 这也不是全对,有些具体类就相当稳定。使用这个类的客户端就完全可以依赖这个具体类,而不用 再弄一个抽象类。 10.3.4 接口隔离原则(Interface Segregation Principle) 接口隔离原则的意思是:使用多个隔离的接口,比使用单个接口好。也就是说,一个类对另外 一个类的依赖性应当是建立在最小的接口上的。 在我们进行设计的时候,一个重要的工作就是恰当地划分角色和角色对应的接口。因此,这里 的接口往往有两种不同的含义。 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 142 UML建模+设计模式+面向服务架构 1.接口对应的角色 指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象,接口的划分就直接带来类型 的划分。这里,我们可以把接口理解成角色,一个接口只是代表一个角色,每个角色都有它特定的 一个接口,这里的这个原则可以叫做角色隔离原则。 例如,我们将电脑的所有功能角色集合为一起,构建了一个接口,如图 10-3所示。 图 10-3 接口混合 此时,我的电脑和你的电脑要实现该接口,就必须实现所有的接口函数,显然接口混乱,并不 能够满足实际的需求:我的电脑可能是用来工作和学习的,你的电脑可能是用来看电影、上网和打 游戏等娱乐活动的,那我们就可以将电脑的角色划分为两类,如图 10-4所示。 图 10-4 划分接口对应的角色 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 143 2.角色对应的接口 指某种语言具体的接口定义,有严格的定义和结构。比如 Java语言里面的 Interface结构。对不 同的客户端,同一个角色提供宽窄不同的接口,也就是定制服务,仅仅提供客户端需要的行为,客 户端不需要的行为则隐藏起来。 对于图 10-4中的接口定义,如果我的电脑除了工作和学习之外,还想上网,那就没办法了,必 须实现娱乐电脑的接口,这样就必须实现它的所有接口函数了。此时我们需要将对应角色中的接口 再进行划分,如图 10-5所示。 图 10-5 划分角色对应的接口 这样,经过以上的划分,如果我的电脑想增加某一项功能,只需要继承不同的接口类即可。 由此可见,对接口角色的划分,是从大的类上进行划分的;对角色的接口进行的划分,是对类 的接口函数的划分。它们两者由粗到细,实现了接口的完全分离。 10.3.5 迪米特法则(最少知道原则)(Demeter Principle) 迪米特法则(Law of Demeter)又叫最少知道原则(Least Knowledge Principle),1987年秋天由 美国 Northeastern University的 Ian Holland提出,被 UML的创始者之一 Booch等普及。后来,因为 在经典著作《 The Pragmatic Programmer》中提出而广为人知。 迪米特法则可以简单说成:talk only to your immediate friends。 对于面向 OOD来说,又被解释 为下面几种方式: z 一个软件实体应当尽可能少地与其他实体发生相互作用。 z 每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软 件单位。 迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容 易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。 迪米特法则不希望类直接建立直接的接触。如果真的有需要建立联系,也希望能通过它的友元 类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 144 UML建模+设计模式+面向服务架构 之所以存在完全是为了传递类之间的相互调用关系—这在一定程度上增加了系统的复杂度。 例如,购房者要购买楼盘 A、B、C中的楼,他不必直接到楼盘去买楼,而是可以通过一个售楼 处去了解情况,这样就减少了购房者与楼盘之间的耦合,如图 10-6所示。 图 10-6 迪米特法则 后文中的外观模式(Facade)和中介者模式(Mediator),都是如上这种迪米特法则应用的例子。 10.3.6 合成复用原则(Composite Reuse Principle) 合成(Composition)和聚合(Aggregation)都是关联(Association)的特殊种类。聚合表示整 体和部分的关系,表示“拥有”;合成则是一种更强的“拥有”,部分和整体的生命周期一样。合成 的新的对象完全支配其组成部分,包括它们的创建和销毁等。一个合成关系的成分对象是不能与另 一个合成关系共享的。 在面向对象设计中,有两种基本的办法可以实现复用: z 第一种是通过合成/聚合,即合成复用原则,含义是指,尽量使用合成/聚合,而不是使用继 承。 z 第二种就是通过继承。 要正确地选择合成/复用和继承的方法是,只有当以下的条件全部被满足时,才应当使用继承关 系: z 子类是超类的一个特殊种类,而不是超类的一个角色,也就是区分“Has-A”和“Is-A”。 只有“Is-A”关系才符合继承关系,“Has-A”关系应当用聚合来描述。 z 永远不会出现需要将子类换成另外一个类的子类的情况。如果不能肯定将来是否会变成另 外一个子类的话,就不要使用继承。 z 子类具有扩展超类的责任,而不是具有置换掉(override)或注销掉(Nullify)超类的责任。 如果一个子类需要大量的置换掉超类的行为,那么这个类就不应该是这个超类的子类。 z 只有在分类学角度上有意义时,才可以使用继承。不要从工具类继承。 错误的使用继承而不是合成/聚合的一个常见原因是错误地把“Has-A”当成了“Is-A”。“Is-A” 代表一个类是另外一个类的一种;“Has-A”代表一个类是另外一个类的一个角色,而不是另外一个 类的特殊种类。 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 145 例如,我们需要办理一张银行卡,如果银行卡默认都拥有了存款、取款和透支的功能,那么我 们办理的卡都将具有这个功能,此时使用了继承关系,如图 10-7所示。 图 10-7 继承关系 为了灵活地拥有各种功能,此时可以分别设立储蓄卡和信用卡两种,并有银行卡来对它们进行 聚合使用。此时采用了合成复用原则,如图 10-8所示。 图 10-8 合成复用原则 10.4 模式的讲解思路 根据作者的不同,表述一个软件设计模式的格式,划分和名称等都会有所不同。常用的 GoF描 述模式的格式大致分为以下这些部分。 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 146 UML建模+设计模式+面向服务架构 z 模式名:每一个模式都有自己的名字,模式的名字使得我们可以讨论我们的设计。 z 问题:在面向对象的系统设计过程中反复出现的特定场合,它导致我们采用某个模式。 z 解决方案:上述问题的解决方案,其内容给出了设计的各个组成部分,即它们之间的关系、 职责划分和协作方式。 z 别名:一个模式可以有超过一个以上的名称,这些名称应该要在这一节注明。 z 动机:该模式应该利用在哪种情况下是本节提供的方案(包括问题与来龙去脉)的责任。 z 适用性:模式适用于哪些情况、模式的背景等。 z 结构:这部分常用类图与互动图阐述此模式。 z 参与者:这部分提供一份本模式用到的类与物件清单,以及它们在设计下扮演的角色。 z 合作:描述在此模式下,类与物件间的互动。 z 影响:采用该模式对软件系统其他部分的影响,比如对系统的扩充性、可移植性的影响。 影响也包括负面的影响。这部分应描述使用本模式后的结果、副作用与权衡(trade-off)。 z 实作:这部分应描述实现该模式、该模式的部分方案、实现该模式的可能技术、或者建议 实现模式的方法。 z 示例:简略描绘出如何以编程语言来使用模式。 z 已知应用:业界已知的实作范例。 z 相关模式:这部分包括其他相关模式,以及与其他类似模式的不同。 目前市面上也有几本介绍设计模式比较好的书,总结一下可以分为如下几类。 z 原理式图书:这种书多从设计模式的基本原理进行讲解,是设计模式的精髓。 z 故事式图书:由于设计模式本身代表的是一种思想,于是通过生活故事的方式简单直白的 讲解,这种方式很容易理解设计模式的思想。 本书接下来将从另外一个角度进行讲解,即针对每一种设计模式,通过与该设计模式最适用的 实例来进行讲解。 1.模式的核心思想 讲解模式的精髓思想,并通过最切合的实例进行讲解,使得想到该模式就能够想到该实例,并 能够由该实例延伸进行扩展。 2.何时使用 讲解该模式适用的场景,应该在什么时候使用,使用它的优缺点,以及应该注意的要点。 3.Java中的应用 讲解 Java中体现该设计模式思想的经典 API设计,通过这种 API的展示告诉读者该模式的适用 场景。 10.5 本课小结 10.5.1 总结本课的知识点 本课首先讲解了设计模式的基本概念及发展历史,然后详细讲解了设计模式的分类和 23种设计 第 10课 设计模式概述 UML建模+设计模式+面向服务架构 147 模式,以及设计模式的六大原则。本节课共包含 4 个大节,每一个大节分多个小节,每一个小节都 对应了一个知识点,共包含 18个知识点,如表 10-2所示。 表 10-2 本课知识点列表 大 节 内 容 小 节 内 容 对应知识点 时间安排(分钟) 设计模式的概念 设计模式的产生 23种设计模式与 GoF“四人帮” 设计模式不是技术而是思想 构建可重用的程序 了解设计模式 为什么要使用设计模式 10 创建型模式 5种 结构型模式 7种 行为型模式 11种 并发型模式 设计模式的分类 线程池模式 10 开闭原则 里氏代换原则 依赖倒转原则 接口隔离原则 迪米特法则 设计模式六大原则 合成符用原则 30 模式的核心思想 何时使用 模式的讲解思路 Java中的应用 10 合计 60 培训讲师可以参照表中最后一列的参考时间控制讲解进度,即 60分钟讲完本课内容。参加培训 的学生在听完讲课后,最好再回顾一遍。对于自学者来说,相对要花费差不多 2 倍的时间来学习这 些知识点。 对于本章知识点的学习,除了要学习理论知识点以外,还应该注重实践操作。下面的两个小节 分别从理论和实践两个方面来为你提出学习的要求。 10.5.2 要掌握的关键点 对于本节课的内容,我们应该掌握如下的关键点。 z 设计模式不是技术而是思想—构建可重用的程序。 z 在《设计模式》这本书中列举并描述了23种设计模式,分为创建型模式、结构型模式和行 为型模式。另外,近来这一清单又增加了一些类别,例如并发型模式、线程池模式、Java EE 企业技术的多层应用程序上的模式等。 z GoF中共描述了 5种创建型模式: ¾ 工厂方法模式(Factory Method)。 ¾ 抽象工厂模式(Abstract Factory)。 ¾ 单例模式(Singleton)。 Java高手真经(系统架构卷):Java Web系统设计与架构 (UML建模+设计模式+面向服务架构) 148 UML建模+设计模式+面向服务架构 ¾ 建造者模式(Builder)。 ¾ 原型模式(Prototype)。 z GoF中共描述了 7种结构型模式: ¾ 适配器模式(Adapter)。 ¾ 装饰器模式(Decorator)。 ¾ 代理模式(Proxy)。 ¾ 外观模式(Facade)。 ¾ 桥接模式(Bridge)。 ¾ 组合模式(Composite)。 ¾ 享元模式(Flyweight)。 z GoF中共描述了 11种行为型模式: ¾ 策略模式(Strategy)。 ¾ 模板方法模式(Template Method)。 ¾ 观察者模式(Observer)。 ¾ 迭代子模式(Iterator)。 ¾ 责任链模式(Chain of Responsibility)。 ¾ 命令模式(Command)。 ¾ 备忘录模式(Memento)。 ¾ 状态模式(State)。 ¾ 访问者模式(Visitor)。 ¾ 中介者模式(Mediator)。 ¾ 解释器模式(Interpreter)。 z 设计模式的六大原则: ¾ 开闭原则对扩展开放,对修改关闭。 ¾ 里氏代换原则:基类可以被子类替换。 ¾ 合成复用原则:要依赖于抽象,不要依赖于具体。 ¾ 接口隔离原则:使用多个隔离的接口,比使用单个接口好。 ¾ 迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用。 ¾ 依赖倒转原则:尽量使用合成/聚合,而不是使用继承。 Tips 这些知识点是本课的精华语录,不仅要记住,还应该转化为自己的东西。 10.5.3 继续下一课:5种创建型模式 本课对设计模式进行了简要介绍,重点讲解了设计模式的分类和设计原则,在后文中我们将重 点讲解 GoF 中提到的 23 种设计模式,将分为 3 课进行讲解。首先以农场养殖为例来讲解 5 种创建 型模式。 第10课 设计模式概述 10.1 了解设计模式 10.1.1 设计模式的概念 10.1.2 设计模式的产生—23种设计模式与GoF“四人帮” 10.1.3 设计模式不是技术而是思想—构建可重用的程序 10.1.4 为什么要使用设计模式 10.2 设计模式的分类 10.2.1 创建型模式 1.工厂方法模式(Factory Method) 2.抽象工厂模式(Abstract Factory) 3.单例模式(Singleton) 4.建造者模式(Builder) 5.原型模式(Prototype) 10.2.2 结构型模式 1.适配器模式(Adapter) 2.装饰器模式(Decorator) 3.代理模式(Proxy) 4.外观模式(Facade) 5.桥接模式(Bridge) 6.组合模式(Composite) 7.享元模式(Flyweight) 10.2.3 行为型模式 1.策略模式(Strategy) 2.模板方法模式(Template Method) 3.观察者模式(Observer) 4.迭代子模式(Iterator) 5.责任链模式(Chain of Responsibility) 6.命令模式(Command) 7.备忘录模式(Memento) 8.状态模式(State) 9.访问者模式(Visitor) 10.中介者模式(Mediator) 11.解释器模式(Interpreter) 10.2.4 并发型模式 10.2.5 线程池模式 10.3 设计模式六大原则 10.3.1 开闭原则(Open Closed Principle) 1)多使用抽象类 2)多使用接口 10.3.2 里氏代换原则(Liskov Substitution Principle) 10.3.3 依赖倒转原则(Dependence Inversion Principle) 10.3.4 接口隔离原则(Interface Segregation Principle) 1.接口对应的角色 2.角色对应的接口 10.3.5 迪米特法则(最少知道原则)(Demeter Principle) 10.3.6 合成复用原则(Composite Reuse Principle) 10.4 模式的讲解思路 1.模式的核心思想 2.何时使用 3.Java中的应用 10.5 本课小结 10.5.1 总结本课的知识点 10.5.2 要掌握的关键点 10.5.3 继续下一课:5种创建型模式
本文档为【java高手真经ch10】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_886435
暂无简介~
格式:pdf
大小:383KB
软件:PDF阅读器
页数:18
分类:互联网
上传时间:2010-01-18
浏览量:25