




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Agenda概述概述 - 简要介绍模式的概念、地位、构成、分类以及描述方法。设计原则设计原则 - 设计原则是设计目标的高度抽象,模式是实现这些原则的具体方法。设计设计模式模式 - 主要介绍了GOF23种软件设计模式。架构模式架构模式 - 主要介绍了架构设计的几种模式。练习练习参考资料参考资料 - 培训只能入门,需要在日常工作中积累提高,请保持阅读习惯。概 述模式是什么 模式是指从生产经验和生活经验中经过抽象和升华提炼出来的核心知识体系核心知识体系。模式其实就是解决某一类问题的方法论方法论。把解决某类问题的方法总结归纳到理论高度,那就是模式。模式是一种指导,在一个良好的指导下,有助于你完成任务,
2、有助于你作出一个优良的设计方案,达到事半功倍的效果。而且,会得到解决问题的最佳办法。模式在知识理念中的地位抽象抽象的(的(abstract)具体具体的(的(concrete)模式的构成u ContextContext(语境)(语境) 设计问题产生的上下文背景u ProblemProblem(问题)(问题) 给定语境中重复出现的问题 - 解决方案必须满足的需求 - 你必须考虑的约束 - 解决方案必须具有期望的特性u SolutionSolution(解决方案)(解决方案) 针对该问题,证实有效的解决方案 - 规定了一个特定的结构 - 规定了运行期间的行为模式的作用u 一个模式关注一个在特定设计环
3、境中出现的重复设计问题一个模式关注一个在特定设计环境中出现的重复设计问题u 各种模式用文档方式记录现有的、经充分考验的设计经验各种模式用文档方式记录现有的、经充分考验的设计经验u 模式明确并指明处于单个类和实例层次或组件层次之上的抽象模式明确并指明处于单个类和实例层次或组件层次之上的抽象u 模式为设计原则提供一种公共的词汇和理解模式为设计原则提供一种公共的词汇和理解u 模式是为软件体系结构建立文档的一种手段模式是为软件体系结构建立文档的一种手段u 模式模式支持用已定义的属性来构造软件支持用已定义的属性来构造软件u 模式有助于建立一个复杂的和异构的软件体系结构模式有助于建立一个复杂的和异构的软件
4、体系结构u 模式有助于管理软件复杂度模式有助于管理软件复杂度 一个软件体系结构的模式描述了一个出现在特定设计语境中的特殊的再现设计问题,并为它的解决方案提供了一个经过充分验证的通用图式。解决方案图式通过描述其组成组件、它们的责任和相互关系以及它们的协作方式来具体指定。模式的层次分类架构模式架构模式(Architecture Styles)- 是系统的高层次策略 ,涉及到大尺度的组件以及整体性质- 可作为具体软件体系结构的模板,是开发一个软件系统时的基本设计决策 -规定了系统范围结构特性,架构模式的好坏影响到总体布局和框架性结构 设计设计模式模式(Design Patterns)-是中等尺度的结
5、构策略。实现了一些大尺度组件的行为和它们之间的关系 -模式的好坏不会影响到系统的总体布局和总体框架-设计模式定义出子系统或组件的微观结构 代码代码模式模式(Idioms)-是特定的范例和与特定语言有关的编程技巧 -处理特定设计问题的实现,关注设计和实现方面 -模式的好坏会影响中等尺度组件的内部、外部的结构或行为的底层细节 模式描述u 名称:模式的名称和一个简短的摘要名称:模式的名称和一个简短的摘要u 别名:模式的其他名称,如果知道的话别名:模式的其他名称,如果知道的话u 例子:用来说明问题存在和需要模式的一个真实世界的例子例子:用来说明问题存在和需要模式的一个真实世界的例子u 语境:模式可以应
6、用的情形语境:模式可以应用的情形u 问题:模式解决的问题,包括其相关强制条件的讨论问题:模式解决的问题,包括其相关强制条件的讨论u 解决解决方案:以该模式为基础的基本解决方案原理方案:以该模式为基础的基本解决方案原理u 结构:模式结构方面的详细的规格说明结构:模式结构方面的详细的规格说明u 动态特性:描述模式运行期间行为的典型场景动态特性:描述模式运行期间行为的典型场景u 实现:实现模式的指南实现:实现模式的指南u 已解决已解决的例子:针对解决没有包括在上述小节中例子的一些重要方面讨论的例子:针对解决没有包括在上述小节中例子的一些重要方面讨论u 变体:模式变体或特例的简短描述变体:模式变体或特
7、例的简短描述u 已知使用:从已存在的系统中给出模式使用的例子已知使用:从已存在的系统中给出模式使用的例子u 效果:模式提供的优点和模式存在的潜在不足效果:模式提供的优点和模式存在的潜在不足u 参见:参考那些解决相似问题的模式,并且参考其他一些模式,有助细化参见:参考那些解决相似问题的模式,并且参考其他一些模式,有助细化设计原则参考:Design Principles and Design Patterns, Robert C. Martinhttp:/ - SOLIDu * *开放开放封闭原则(封闭原则(OCP, Open Closed PrincipleOCP, Open Closed Pr
8、inciple) 模块应该对扩展开放,对更改封闭u 依赖倒置原则(依赖倒置原则(DIP, Dependency Inversion PrincipleDIP, Dependency Inversion Principle) 依赖抽象,不要依赖实现;高层模块(稳定)不应该依赖于底层模块(变化),二者都应该依赖于抽象;抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象u 单一职责原则(单一职责原则(SRP, Single Responsibility PrincipleSRP, Single Responsibility Principle) 一个类应该仅有一个引起它变化的原因,应该
9、只有一个职责;每一个职责都是变化的一个轴线,如果一个类有多个职责,这些职责就耦合在了一起u LiskovLiskov替换原则(替换原则(LSP, LSP, LiskovLiskov Substitution Principle Substitution Principle) 子类必须能够替换它们的基类(IS-A);如果调用的是父类的话,那么换成子类也完全可以运行u 接口隔离原则(接口隔离原则(ISP, Interface Segregation PrincipleISP, Interface Segregation Principle) 每一个接口应该是一种角色;多个客户特定的接口强于一个通用
10、目的的接口,不应该强迫客户程序依赖它们不用的方法面向对象设计原则(2)u * *最少知识原则(迪米特法则)最少知识原则(迪米特法则) 一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。一个软件实体应当尽可能少的与其他实体发生相互作用;每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。u 针对针对接口编程,而不是针对实现编程接口编程,而不是针对实现编程 客户无需知道所使用对象的特定类型,只需要知道对象拥有客户所期望的接口u 优先使用对象组合,而不是类继承优先使用对象组合,而不是类继承 类继承通常为“白箱复用”,对象组合通常为“黑箱复用”。继承在某种程度上
11、破坏了封装性,子类父类耦合度高;而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。u 封装变化点封装变化点 使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。面向对象设计原则(3:包结构原则)u The Release Reuse Equivalency PrincipleThe Release Reuse Equivalency Principle(REPREP) The granule of reuse is the granule of release(软件包的粒度与可重用的粒度保持一致)u The Com
12、mon Closure PrincipleThe Common Closure Principle(CCPCCP) Classes that change together, belong together(一致变化的类,应该属于同一个包)u The Common Reuse PrincipleThe Common Reuse Principle(CRPCRP) Classes that arent reused together should not be grouped together(不被一起重用的类,不放到一个包里)高内聚(Cohesion)面向对象设计原则(4:包结构原则)u Th
13、e Acyclic Dependencies PrincipleThe Acyclic Dependencies Principle(ADPADP) The dependencies between packages must not form cycles(软件包之间不能相互依赖,构成依赖循环)u The Stable Dependencies PrincipleThe Stable Dependencies Principle(SDPSDP) Depend in the direction of stability(包之间的依赖关系都应该是稳定方向依赖的,包要依赖的包要比自己更具稳定性)u
14、 The Stable Abstractions PrincipleThe Stable Abstractions Principle(SAPSAP) Stable packages should be abstract packages(稳定的包,应该是抽象的包,以此带来可变性)低耦合(Coupling)设计模式(Design Patterns)设计模式u 起源起源 Design Patterns: Elements of Reusable Object-Oriented Software,GOF23种设计模式。u 发展发展 增加了一些类别,最重要的是使涵盖范围扩展到更具体的问题类型。例如:
15、 -Patterns in Java增加了解决涉及诸如并发等问题的模式, -Core J2EE Patterns主要关注使用Java2企业技术的多层应用程序上的模式。GOF-23设计模式分类从目的来看从目的来看u 创建型模式(创建型模式(CreationalCreational):): 将对象的部分创建工作延迟到子类或者其他对象,从而应对需求变化为对象创建时具体类型实现引来的冲击。u 结构型模式(结构型模式(StructuralStructural):):通过类继承或者对象组合获得更灵活的结构,从而应对需求变化为对象的结构带来的冲击。u 行为型模式(行为型模式(BehavioralBehavi
16、oral):):通过类继承或者对象组合来划分类与对象间的职责,从而应对需求变化为多个交互的对象带来的冲击。从范围来看从范围来看u 类模式类模式处理类与子类的静态关系u 对象对象模式模式处理对象间的动态关系GOF-23设计模式概览创建型结构型行为型类Factory Method Adapter_Class InterpreterTemplate Method 对象Abstract FactoryBuilderPrototypeSingleton Adapter_ObjectBridgeCompositeDecoratorFacadeFlyweightProxy Chain of Responsi
17、bilityCommandIteratorMediatorMementoObserverStateStrategyVisitor 从封装变化角度对模式分类u 对象创建对象创建 Factory Method Abstract Factory Prototype Builderu 组件组件协作协作 Template Method Observer / Event Strategyu 单一职责单一职责 Decorator Bridgeu 对象对象性能性能 Singleton Flyweightu 接口接口隔离隔离 Facade Proxy Mediator Adaptoru 状态变化状态变化 Mem
18、ento Stateu 数据结构数据结构 Composite Iterator Chain of Responsibilityu 行为变化行为变化 Command Visitoru 领域问题领域问题 Interpreter来源:祝成科技软件开发培训“对象创建”模式u通过通过“对象创建对象创建”模式对象绕开模式对象绕开newnew,来避免对象创建(,来避免对象创建(newnew)过)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。它是接口抽象之后的第一步工作。u典型模式典型模式 Factory M
19、ethod Abstract Factory Prototype BuilderFactory Method模式u举例举例 你是一个ATM机软件的开发工程师,需要测试ATM软件的存取款功能,但在测试时不想产生实际的银行业务,该怎么办呢?public class ATMGui private Status doWithdrawal(Account account, float amount) Transaction transaction = new Transaction(); transaction.setSourceAccount(account); transaction.setDest
20、Account(myCashAccount(); transaction.setAmount(amount); cess(); if (transaction.successful() dispense(amount); return transaction.getStatus(); Public class ATMGuiTest public void testCheckingWithdrawal() float startingBalance = balanceForTestCheckingAccount(); AtmGui atm = new AtmGui(
21、); insertCardAndInputPin(atm); atm.pressButton(Withdraw); atm.pressButton(Checking); atm.pressButtons(1, 0, 0, 0, 0); assertContains($100.00, atm.getDisplayContents(); atm.pressButton(Continue); assertEquals(startingBalance - 100, balanceForTestCheckingAccount(); Factory Method模式Factory Method模式u动机动
22、机 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?u意图意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类Factory Method模式u结构结构u适用性适用性 当一个类不知道它所必须创建的对象的类的时候 当一个类希望由它的子类来指定它所创建的对象的时候 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候
23、。 解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同Template Method,具有实际的逻辑和意义该类型对客户端是否隐藏呢?Abstract Factory模式u举例举例 Java可以根据变成人员的要求改变界面风格,如Windows风格,Java风格等,这是怎么做到的呢?Abstract Factory模式Abstract Factory模式u动机动机 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象
24、创建工作”的紧耦合?u意图意图 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。Abstract Factory模式u结构结构u适用性适用性 一个系统要独立于它的产品的创建、组合和表示时。 一个系统要由多个产品系列中的一个来配置时。 当你要强调一系列相关的产品对象的设计以便进行联合使用时。 当你提供一个产品类库,而只想显示它们的接口而不是实现时。 主要用于应对“新系列”的需求变动。缺点在于难以应对“新对象”的需求变动Prototype模式u举例举例 细胞通常具有非常复杂的结构。在生物工程模拟细胞分裂时,如何快速实现从一个细胞到两个细胞的创建工作?Proto
25、type模式u动机动机 在软件系统中,经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。 如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得“依赖这些易变对象的客户程序”不随着需求改变而改变?u意图意图 使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。Prototype模式u结构结构u适用性适用性 当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者 为了避免创建一个与产品类层次平行的工厂类层次时;或者 当一个类的实例只能有几个不同状态组合中的一种时。建立
26、相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。Builder模式u举例举例 ProtocolBuffer中,要实现协议类的快速序列化与反序列化,在协议类的实现中封装了非常复杂的数据结构,而ProtocolBuffer的使用者,不希望用很复杂的方法来创建该协议类。message Request / RPC service full name required string service_name = 1; / RPC method name required string method_name = 2; / RPC request proto required by
27、tes request_proto = 3;Request.Builder builder = Request.newBuilder();builder.setServiceName();builder.setMethodName();builder.setRequestProto();Request request = builder.build();Builder模式u场景场景 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。Builder模式u
28、动机动机 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。 如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?u意图意图 将一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。Builder模式u结构结构u适用性适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。 当构造过程必须允许被构造的对象有不同的表示时。 (变化点在哪
29、里,封装在哪里)主要在于 “分步骤构建一个复杂的对象” 。其中“分步骤”是一个稳定的算法,复杂对象的各个部分则经常变化。缺点在于难以应对“分步骤构建算法”的需求变动。“组件协作”模式u现代软件专业分工之后的第一个结果是现代软件专业分工之后的第一个结果是“框架与应用程序的划分框架与应用程序的划分”,“组件协作组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式耦合,是二者之间协作时常用的模式。u典型模式典型模式 Template Method Observer / Event StrategyTemplate Me
30、thod模式u举例举例对于写Servlet的开发人员,常常只需要指定如何处理Get、Post、Put等几个少数的方法就可以了,而对于一些复杂的处理过程,如把字节流转换为ServletRequest对象,或从字节流中识别不同请求类型并分发到合适的处理方法,可以一概都不需要知道。public abstract class HttpServlet extends GenericServlet implements java.io.Serializable protected void doGet(HttpServletRequest req, HttpServletResponse resp)thr
31、ows ServletException, IOException /略略 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException String method = req.getMethod(); / 取得請求的方法取得請求的方法 if (method.equals(METHOD_GET) / HTTP GET / 略略. doGet(req, resp); / 略略 . else if (method.equals(METHOD_
32、HEAD) / HTTP HEAD / 略略 . doHead(req, resp); else if (method.equals(METHOD_POST) / HTTP POST / 略略 . doPost(req, resp); else if (method.equals(METHOD_PUT) / HTTP PUT / 略略 . Template Method模式u动机动机 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。 如何在确定稳定操作结构的前提下,来灵活
33、应对各个子步骤的变化或者晚期实现需求?u意图意图 定义一个操作中的算法的骨架(稳定),而将一些步骤(变化)延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义(override 重写)该算法的某些特定步骤。Template Method模式u结构结构u适用性适用性 一次性实现一个算法的不变的部分,将可变的行为留给子类来实现。 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。是“重分解以一般化”的一个很好的例子。 控制子类扩展。模板方法只在特定点调用“hook”操作(参见效果一节),这样就只允许在这些点进行扩展。 被Template Meth
34、od调用的虚方法一般推荐设置为protected。Observer / Event模式u举例举例Java NIO非堵塞技术是如何实现的?以下是采用Netty创建服务端的代码片段。public class HelloServer public static void main(String args) / Server服务启动器 ServerBootstrap bootstrap = new ServerBootstrap(); / 设置一个处理客户端消息和各种消息事件的类(Handler) bootstrap .setPipelineFactory(new ChannelPipelineFac
35、tory() Override public ChannelPipeline getPipeline() throws Exception return Channels .pipeline(new HelloServerHandler(); ); / 开放8000端口供客户端访问。 bootstrap.bind(new InetSocketAddress(8000); private static class HelloServerHandler extends SimpleChannelHandler / 当有客户端绑定到服务端的时候触发,打印Hello world, Im server.
36、 Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) System.out.println(Hello world, Im server.); Observer / Event模式u动机动机 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”,即一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构
37、的松耦合。u意图意图 定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新Observer / Event模式u结构结构u适用性适用性 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。Strategy模式u举举例例负载均衡是分布式计算中常见的问题,实现负载均衡有很多不同算法,如随机算法、RoundRobi
38、n算法、一致性Hash算法等。(1) 运维人员可能根据需要随时调整负载均衡策略;(2) 将来可能有更新更好的负载均衡算法。我们应该如何设计我们的分布式框架? Protected Node getNode(LoadBalanceType type) if (RANDOM = type) return getRandomNode(); else if (ROUNDROBIN = type) return getRoundRobinNode(); else if Strategy模式u动机动机 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异
39、常复杂;而且有时候支持不使用的算法也是一个性能负担。 如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?u意图意图 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。该模式使得算法可独立于使用它的客户而变化。Strategy模式u结构结构u适用性适用性 “策略”及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法间进行切换。 提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。 “单一职责”模式u在软件组件的设计中
40、在软件组件的设计中”,如果责任划分的不清晰,使用继承得到的,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任这时候的关键是划清责任。u典型模式典型模式 Decorator BridgeDecorator模式u举例举例SiteMesh是由一个基于Web页面布局、装饰以及与现存Web应用整合的框架。它能帮助我们在由大量页面构成的项目中创建一致的页面布局和外观,如一致的导航条,一致的banner,一致的版权,等等。 它不仅仅能处理动态的内容,如jsp,php,asp等产生
41、的内容,它也能处理静态的内容,如htm的内容,使得它的内容也符合你的页面结构的要求。甚至于它能将HTML文件象include那样将该文件作为一个面板的形式嵌入到别的文件中去。所有的这些,都是GOF的Decorator模式的最生动的实现。尽管它是由java语言来实现的,但它能与其他Web应用很好地集成。Decorator模式u动机动机 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。 如何使“对象功能的扩展”能够根据需要来动态地
42、实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?u意图意图 动态地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。Decorator模式u结构结构u适用性适用性 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。 处理那些可以撤消的职责。 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。 并非解决“多子类衍生的多继承”问题,应用的要点在于解决“主体类在
43、多个方向上的扩展能力”是为“装饰”的含义Bridge模式u举例举例手机品牌和软件是两个概念,不同的软件可以在不同的手机上,不同的手机可以有相同的软件,两者都具有很大的变动性。如果我们单独以手机品牌或手机软件为基类来进行继承扩展的话,无疑会使类的数目剧增并且耦合性很高。这时候我们应该怎么办?(如果更改品牌或增加软件都会增加很多的变动)两种方式的结构如下:手机这个例子可能很直观,想想关于状态的例子?当我们需要各种不同状态的复杂组合时,考虑一下Bridge模式吧。Bridge模式Bridge模式u动机动机 由于某些类型的固有逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。 如何应对这种“多维度
44、的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?u意图意图 将抽象部分与实现部分分离,使它们都可以独立地变化。Bridge模式u结构结构u适用性适用性 使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。 有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。 应用一般在“两个非常强的变化强度”“对象性能”模式u面向对象很好地解决了面向对象很好地解决了
45、“抽象抽象”的问题,但是必不可免地要付出一的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理但是某些情况,面向对象所带来的成本必须谨慎处理。u典型模式典型模式 Singleton FlyweightSingleton模式u举例举例每一个Java程序实际上都是启动了一个JVM进程。我们如何在Java程序中获取当前JVM的状态呢? Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相
46、连接。 一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用。 一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。 Runtime run = Runtime.getRuntime();System.out.println(“JVM最大内存:” + run.maxMemory();System.out.println(“JVM空闲内存:” + run.freeMemory();Singleton模式u动机动机 在软件系统
47、中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?这应该是类设计者的责任,而不是使用者的责任。u意图意图 保证一个类仅有一个实例,并提供一个该实例的全局访问点。Singleton模式u结构结构u适用性适用性 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。 实例构造器可以设置为protected以允许子类派生;一般不要支持序列化和ICloneable接口,因为有可能导致多个
48、对象实例。 不能应对多线程环境:在多线程环境下,仍然有可能得到多个实例对象(需要加信号量)Flyweight模式u举例举例 字符串在大多数应用程序中的出现频率较高,Java必须对字符串的执行进行优化以保证效率。执行以下代码,看看结果和你预期的是否一致?public class StringTest public static void main(String args) String fly = fly, weight = weight; String fly2 = fly, weight2 = weight; System.out.println(fly = fly2); / ? Syste
49、m.out.println(weight = weight2); / ? String distinctString = fly + weight; System.out.println(distinctString = flyweight); / ? String flyweight = (fly + weight).intern(); System.out.println(flyweight = flyweight); / ? Flyweight的另一个典型例子是Java Swing。请查阅相关资料,指出Swing树的速度是如何做到这么快的。(秘密在TreeCellRenderer.get
50、TreeCellRendererComponent()里)Flyweight模式u动机动机 采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价主要指内存需求方面的代价。 如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?u意图意图 运用共享技术有效地支持大量细粒度的对象。Flyweight模式u结构结构u适用性适用性 主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。 采用对象共享的做法降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。具体实现时,要注意对象状态的处理。对象的大多数状态都可变为
51、外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。 对象的数量太大从而导致对象内存开销加大什么样的数量才算大?需要根据具体应用情况进行评估,而不能凭空臆断。“接口隔离”模式u在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题、在组件构建过程中,某些接口之间直接的依赖常常会带来很多问题、甚至根本无法实现。采用添加一层间接接口,来隔离本来互相紧密甚至根本无法实现。采用添加一层间接接口,来隔离本来互相紧密关联的接口是一种常见的解决方案关联的接口是一种常见的解决方案。u典型模式典型模式 Facade Proxy Mediator AdaptorFacade模式u举例
52、举例汽车启动时,电瓶中的电能转化成起动机机械能,从而由曲轴带动发动机转动,同时点火、喷油在缸内燃烧,作工。发动机是一种能量转换机构,它将燃料燃烧产生的热能转变成机械能,发动机的一个工作循环包括四个过程:进气、压缩、作功、排气。发动机有很多种,如四行程汽油机、二行程汽油机等,工作机制又各有不同,其实说了这么多,开车司机点火的时候所要做的就是,把点火钥匙插入钥匙孔,轻轻一转就可以了。Facade模式u动机动机 上述A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的演化,这种过多的耦合面临很多变化的挑战。 如何简化外部客户程序和系统间的交互接口?如何将外部
53、客户程序的演化和内部子系统的变化之间的依赖相互解耦?u意图意图 为子系统中的一组接口提供一个一致的界面,Faade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。A方案方案B方案方案Facade模式u结构结构u适用性适用性 简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果内部子系统的任何变化不会影响到Faade接口的变化。 更注重从架构的层次去看整个系统,而不是单个类的层次 并非一个集装箱,可以任意地放进任何多个对象。Faade模式中组件的内部应该是“相互耦合关系比较大的一系列组件”,而不是一个简单的功能集合。Proxy模式u举例
54、举例(1)远程代理(Remote Proxy)(2)虚代理(Virtual Proxy)(3)保护代理(Protection Proxy)(4)智能指针(Smart Reference)Proxy模式u动机动机 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。 如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。u意图意图 为其他对象提供一种代理以控制对这个对象的访问。Proxy模式u结构结构u适用性适用性 在需要用比较通用和复
55、杂的对象指针代替简单的指针的时候,使用Proxy模式。 具体实现方法、实现粒度都相差很大。可能针对单个对象也可能针对组件模块做proxy 并不一定要求保持接口的一致性,只要能够实现间接控制,有时候损失一些透明性是可以接受的Mediator模式u举例举例试想繁忙的首都国际机场,每天进出港航班达上千次,如果没有机场飞行控制系统(就是传说中的塔台)是难以想象的。塔台具有绝对的权利,他可以控制任何一架飞机的起飞和降落时间以及地方,而飞机和飞机之间不允许通信。同事关系中介者Mediator模式u动机动机 在软件构建过程中,经常会出现多个对象互相关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇
56、到一些需求的更改,这种直接的引用关系将面临不断的变化。 在这种情况下,我们可使用一个“中介对象”来管理对象间的关联关系,避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化。u意图意图 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。Mediator模式u结构结构u适用性适用性 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。 想定制一个分布在多个类中的行为,而又不想生成太多的子类。 将多个对象间复杂的关联关系
57、解耦,将多个对象间的控制逻辑进行集中管理。Faade是解耦系统外到系统内(单向)的对象关联关系;Mediator模式是解耦系统内各个对象之间(双向)的关联关系。 随着控制逻辑的复杂化,可能需要对Mediator具体对象进行分解处理。Adapter模式u举例举例电源插座在不同国家有多种标准,如国标、美标、英标、南非标、德标、意标等,此外各国生活用电电压标准也各有不同,如美国的生活用电电压是110V,而中国的电压是220V。如果要在中国使用美国电器,你有什么好主意吗?我们有多款OBD设备,协议都各不相同,并且在某些项目中客户还不排除引入第三方厂商的OBD硬件,我们的OBD核心平台应该采取什么样的设
58、计模式呢?Adapter模式u动机动机 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。 如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?u意图意图 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。Adapter模式u结构结构u适用性适用性 你想使用一个已经存在的类,而它的接口不符合你的需求。 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作
59、。 (仅适用于对象Adaptor)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。 Adapter模式本身要求我们尽可能地使用“面向接口的编程风格”,这样才能在后期很方便地适配。“对象对象”适配器适配器推荐推荐“状态变化”模式u在组件构建过程中,某些对象的状态经常面临变化,如何对这些变在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?化进行有效的管理?同时又维持高层模块的稳定?“状态变化状态变化”模模式为这一问题提供了一种解决方案式为这一问题提供了一种解决方案。u典型模式典型模式 M
60、emento StateMemento模式u举例举例我们玩单机游戏的时候总会遇到MM大人的各种事情,一会儿陪逛街,一会儿去打个酱油,会耽误我们玩游戏的进程,但是此时我们能有“保存游戏”这个宝贝,我们的主基地就不会在我们打酱油的时候被对手拆掉。“保存游戏”的功能其实就是备忘录模式的很好应用,它在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以把该对象恢复到原先保存的状态。你能想到其它类似的例子吗?Memento模式u动机动机 在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年宠物殡葬师的创新技能与试题及答案
- 大学语文经典作品分析试题及答案2024
- 2024年无线网络安全试题及答案
- 2024年预算员面临的技术变革挑战试题及答案
- 黑龙江林业职业技术学院《英汉翻译实务》2023-2024学年第二学期期末试卷
- 黑龙江省五校联考2024-2025学年高三下学期月考(五)物理试题试卷含解析
- 黑龙江省佳木斯市重点中学2025届高三二诊模拟考试历史试题含解析
- 黑龙江省哈尔滨名校2025届高三高考物理试题系列模拟卷(9)含解析
- 黑龙江省哈尔滨市木兰县2025年小升初数学检测卷含解析
- 黑龙江省哈尔滨阿城区六校联考2025届第二学期初三摸底考试化学试题试卷含解析
- 对配合和服从总包管理的认识和协调方案
- 2025年上海市各区高三语文一模试题汇编之文言文阅读试题和答案
- 江苏省常州市金坛区2023-2024学年小升初语文试卷(有答案)
- 《桥梁工程中的预应力混凝土技术》课件
- DeepSeek介绍及其典型使用案例
- 危险性较大的分部分项工程安全监理实施细则
- 2025年四川省国有资产经营投资管理有限责任公司招聘笔试参考题库附带答案详解
- 安全驾驶培训:路标篇
- 《财政基础知识介绍》课件
- 西安电子科技大学《科技英语写作》2021-2022学年第一学期期末试卷
- 临床经鼻高流量湿化氧疗患者护理查房
评论
0/150
提交评论