设计模式
一、设计模式
| 创建型 | 结构型 | 行为型 |
|
|
|
二、创建型设计模式
(一)创建型设计模式介绍:
创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。
随着系统演化得越来越依赖于对象复合而不是类继承,创建型模式变得更为重要。当这种情况发生时,重心从对一组固定行为的硬编码(Hard-coding) 转移为定义一个较小的基本行为集,这些行为可以被组合成任意数目的更复杂的行为。这样创建有特定行为的对象要求的不仅仅是实例化一一个类。
在这些模式中有两个不断出现的主旋律。
第一,它们都将关于该系统使用哪些具体的类的信息封装起来。
第二,它们隐藏了这些类的实例是如何被创建和放在一起的。 整个系统关于这些对象所知道的是由抽象类所定义的接口。
因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以及何时创建这些方面给子了很大的灵活性。它们允许用结构和功能差别很大的“产品”对象配置个系统。配置可以是静态的(即在编译时指定),也可以是动态的(在运行时)。
(二)创建型设计模式比较:
用于系统创建的那些对象的类对系统进行参数化有两种常用方法:生成创建对象的类的子类和对系统进行参数化的方法。前者对应于使用Factory Method模式,其主要缺点是仅为了改变产品类就可能需要创建一 个新的子类。这种改变可能级联发生,例如,如果产品的创建者本身是一一个工厂方法创建的,那么也必须重定义它的创建者。后者更多地依赖于对象的复合,定义一一个对象负责明确产品对象的类,并将它作为该系统的参数。这是Abstract Factory、Builder和Prototype模式的关键特征,都涉及创建一个新的负责创建产品对象的“工厂对象”。AbstractFactory由这个工厂对象产生多个对象。Builder 由这个工厂对象使用一个相对复杂的协议,逐步创建个复杂产 品。Prototype 由该工厂对象通过复制原型对象 来创建产品对象。在这种情况下,由于原型负责返回产品对象,所以工厂对象和原型是同一个对象。
四、结构型设计模式
(一)结构型设计模式介绍
结构型设计模式涉及如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口或实现。一个简单的例子是采用多重继承方法将两个以上的类组合成一个类, 结果这个类包含了所有父类的性质。这一模式尤其 有助于多个独立开发的类库协同工作。其中一个例子是类形式的Adapter 模式。一般来说, 适配器使得一个接口 与其他接口兼容,从而给出了多个不同接口的统一抽象。 为此,类适配器对一个adaptee 类进行私有继承。这样,适配器就可以用adaptee的接口表示它的接口。
结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合, 从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态类组合是不可能实现的。
Composite模式是结构型对象模式的一个实例。它描述了如何构造一个类层次式结构,这一结构由两种类型的对象所对应的类构成。其中的组合对象使得用户可以组合基元对象以及其他的组合对象,从而形成任意复杂的结构。在Proxy模式中,proxy 对象作为其他对象的一个方便的替代或占位符。它的使用可以有多种形式,例如可以在局部空间中代表一个远程地址空间中的对象,也可以表示一个要求被加载的较大的对象,还可以用来保护对敏感对象的访问。Poxy模式还提供了对对象的一一些特有性质的 一定程度上的间接访问,从而可以限制、增强或修改这些性质。Flyweight 模式为了共享对象定义了一一个结构。 至少有两个原因要求对象共享:效宰和一致性。Flyweight的对象共享机制主要强调对象的空间效率。使用很多对象的应用必须考虑每一一个对象的开销。使用对象共享而不是进行对象复制,可以节省大量的空间资源。但是,仅当这些对象没有定义与上下文相关的状态时,它们才可以被共享。Flywight的对象没有这样的状态。任何执行任务时需要的其他一些信息仅 当需要时才传递过去。由于不存在与上下文相关的状态,因此Flyweight对象可以被自由地共享。
如果说Flyweight模式说明了如何生成很多较小的对象,那么Facade 模式则描述了如何用单个对象表示整个子系统。模式中的facade用来表示一组对象, facade 的职责是将消息转发给它所表示的对象。Bridge 模式将对象的抽象和其实现分离,从而可以独立地改变它们。
Decorator模式描述了如何动态地为对象添加职责。Decorator 模式是一种结构型模式,这一模式采用递归方式组合对象,从而允许添加任意多的对象职责。例如,一个包含用户界面组件的Decorator对象可以将边框或阴影这样的装饰添加到该组件中,或者它可以将窗口滚动和缩放这样的功能添加到组件中。可以将-个Decorator对象嵌套在另外一个对象中,就可以很简单地增加两个装饰,添加其他的装饰也是如此。因此,每个Decorator 对象必须与其组件的接口秉容并且保证将消息传递给它。Decorator模式在转发条信息之前或之后都可以完成它的工作(例如绘制组件的边框)。许多结构型模式在某种程度上具有相关性。
(二)结构型设计模式比较
Adapter模式和Bridge模式具有些功能特征, 都给另一个对象提供了一 定程度 上的间接性,因而有利于系统的灵活性,另外都涉及从自身以外的一个接口向这个对象转发请求。 Adapter模式主要是为解决两个已有接口之间不匹配的问题,不考虑这些接口是怎样实现的,也不考虑它们各自可能会如何演化。这种方式不需要对两个独立设计的类中的任何-一个进行重新设计,就能够使它们协同工作。Bridge 模式则对抽象接口与它的(可能是多个)实现部分进行桥接。虽然这一模式运行使用者修改实现它的类,但是它仍然为用户提供了一个稳定的接口,也会在系统演化时适应新的实现。Adapter 模式和Bridge模式通常被用于软件生命周期的不同阶段,针对不同的问题。Adapter 模式在类已经设计好后实施;而Bridge模式在设计类之前实施。Composite模式和Decorator模式具有类似的结构,说明它们都是基于递归组合来组织可变数目的对象。Decorator 旨在能够不需要生成子类即可给对象添加职责,这避免了静态实现所有功能组合而导致子类急剧增加。Composite 旨在构造类,使多个相关的对象能够以统的方式处理,而多重对象可以被当作一个对象来处理,重点在于表示。两者通常协同使用。
Decorator 模式和Proxy模式都描述了怎样为对象提供一定程度 上的间接引用。Proxy模式构成一一个对象并为用户提供一致的接口, 与Decorator模式不同的是,Proxy模式不能动态地添加或分离性质,也不是为递归组合而设计的,它强调-种关系(Proxy与它的实体之间的关系),这种关系可以静态地表达。其目的是,当直接访问一个实体不方便或不符合需要时,为这个实体提供一个替代者, 例如,实体在远程设备上,访问受到限制或者实体是持久存储的。在Proxy模式中,实体定义了关键功能,而Proxy提供(或拒绝)对它的访问。在Decorator模式中,组件仅提供了部分功能,而一个或多 个Decortor负责完成其他功能。Decorator 模式适用于编译时不能(至少不方便)确定对象的全部功能的情况。
五、行为型设计模式
(一)行为型设计模式介绍
行为模式涉及算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻画了在运行时难以跟踪的、复杂的控制流。它们将用户的注意力从控制流转移到对象间的联系方式上来。
行为类模式使用继承机制在类间分派行为。本小节包括两个这样的模式。其中Template Method较为简单和常用。模板方法是一个算法的抽象定义,它逐步地定义该算法,每一步调用 一个抽象操作或- 个原语操作,子类定义抽象操作以具体实现该算法。另种行为类模式是Interpreter,它将一个文法表示为一个类层次, 并实现一个解释 器作为这些类的实例上的一个操作。
行为对象模式使用对象复合而不是继承。一些行为对象模式描述了一组对等的对象怎样相互协作以完成其中任一个对象 都无法单独完成的任务。这里一一个重要的问题是对等的对象。如何互相了解对方。对等对象可以保持显式的对对方的引用,但那会增加它们的耦合度。
在极端情况下,每一个对象都要 了解所有其他的对象。Mediator在对等对象间引入一个 mediator对象以避免这种情况的出现。mediator 提供了松耦合所需的间接性。Chain of Responsibility提供更松的耦合。它让用户通过一条候选对象 链隐式地向一个对象发送请求。根据运行时刻情况任候选者 都可以响应相应的请求。候选者的数目是任意的,可以在运行时刻决定哪些候选者参与到链中。
Observer模式定义并保持对象间的依赖关系。典型的Observer的例子是Smalltalk中的模司性型/视图/控制器,其中,一旦模型的状态发生变化,模型的所有视图都会得到通知。
其他的行为对象模式常将行为封装在一个对象中并将请求指派给它。 Strategy 模式将算法封装在对象中,这样可以方便地指定和改变-一个对象所使用的算法。 Command模式将请求封装在对象中,这样它就可作为参数来传递,也可以被存储在历史列表中,或者以其他方式使用。State模式封装- 个对象的状态,使得这个对象的状态对象变化时,该对象可改变它的行为。
Visitor封装分布于多个类之间的行为,而Iterator抽象了访问和遍历一个集合中的对象的方式。
(二)行为型设计模式比较
很多行为模式注重封装变化。当一个程序的某个方面的特征经常发生改变时,这些模式就定义-一个封装这个方面的对象。这样,当该程序的其他部分依赖于这个方面时,它们都可以与此对象协作。这些模式通常定义-个抽象类来描述这些封装变化的对象,并且通常该模式依据这个对象来命名。例如:
●个Strategy 对象封装一个算法。
●一个 State对象封装个与状态相关的行为。
●一个Mediator 对象封装对象间的协议。
●一个Iterator对象封装访问和遍历一个聚集对象中的各个组件的方法。
这些模式描述了程序中很可能会改变的方面。大多数模式有两种对象:封装该方面特征的新对象和使用这些新对象的已有对象。但并非所有的对象行为模式都有这样的分割功能,例如,Chain of Responsibility可以处理任意数目的对象(即一个链),而所有这些对象可能已经存在于系统中了。这也说明了行为模式的另个不同点:并非所有的行为模式都定义类之间的静态通信关系。
一些模式引入总 是被用作参数的对象。例如Visitor, 一个 Visitor 对象是一个多态的 Acept操作的参数,这个操作作用于该Visitor 对象访问的对象。其他模式定义一些可 作为令牌进行传递的对象,这些对象将在稍后被调用。例如,Command和Memento.在Command中,令牌代表一个请求:在Memento中,两台代表在一个对象在某个特定时刻的内部状态。在这两种情况下,令牌都可以有一个复杂的内部表示,但客户并不会意识到这一点。另外,在Command模式中多态特别重要,这是因为执行Command对象是一个多态操作。而Memento接口非常小,以至于备忘录只能作为一个值传递, 因此,它很可能根本不给它的客户提供任何多态操作。
Mediator和Observer是相互竞争的模式,它们之间的差别是: Observer 通过引入Observer和Subject对象来分布通信,而Mediator 对象则封装了其他对象间的通信。Observer 模式中不存在封装一个约束的单个对象,而必须是Obserer和Subjet对象相互协作来维护这个约束。通信模式由Observer和Subject连接的方式决定:一个Subject通常有多个Observer,并且有时一个Subjiet的Observer也是另一个Observer的目标。Observer模式有利于Observer和Subjet之间的分割和松耦合,易于产生更细粒度且更易于复用的类。Mediator 模式的目的是集中而不是分布,它将维护一个约束的职责直接放在.个中间者中。
Command、Observer、 Mediator 和Chain of Responsibility等模式都涉及如何对发送者和接收者解耦,但各自有不同的权衡考虑。
Command模式使用一个Command对象来定义.个发送者 和一个接收者之间的绑定关系,从而支持解耦。Command对象提供了一个提交请求的简单接口 (即Exccute 操作),将发送者和接收者之间的连接定义在一个对象, 使得该发送者可以与不同的接收者一起工作, 达到将发送者和接收者解耦,使发送者更易于复用。此外,可以复用Command对象,用不同的发送者参数化一个接收者。
Observer模式通过定义-个接口来通 知目标中发生的改变, 从而将发送者(目标)与接收者(观察者)解耦。Observer 定义了-个比Command更松的发送者-接收者绑定,这是因为一个目标可能有多个观察者,并且其数目可以在运行时变化。此模式中的Subject和Observer接口是为了处理Subject的变化而设计的,因此,当对象间有数据依赖时,最好用此模式来对它们进行解耦。
Mediator模式让对象通过一- 个Mediator 对象间接相互引用,从而对它们进行解耦。- -个Mediator对象为各Colleague对象间的请求提供路由,并集中它们的通信。因此,各Colleague对象仅能通过Mediator接口相互通信。Mediator 接口是固定的,为了增加灵活性,Mediator 可能不得不实现它自己的分发策略。可以用定方式对请求编码并打包参数, 使得Colleague 对象可以请求的操作数目不限。由于此模式将通信行为集中到一个类中而不是将其分布在各个子类中,所以它可以减少一一个系统的子类生成。
Chain of Rsponsibility模式通过沿一个潜在接收者链传递请求而将发送者与接收者解耦。因为发送者和接收者之间的接口是固定的,责任链可能也需要一个定制的分发策略。

浙公网安备 33010602011771号