1、CH23 第二次迭代,在多个开发周期中,后续开发周期中往往是在前面开发周期中模型的细化和精化。逐渐实现业务的完善。需求的细化考虑 第三方外部服务的支持 税率计算器问题 复杂的定价策略 打折策略人机界面对销售总额的变化的监视 系统接口 外部协作系统:税率计算、帐务、库存。基本需求中已经提到,但是没有在迭代1中实现,CH24 第二次迭代的模型更新,补充规格说明 接口 对于大部分的外部协作系统, 应能够插入这些系统及其接口. 第三方外部服务的支持 规则 购买者打折规则 复杂的定价策略,多种接口变化的处理销售的场景,CH25 更多的职责分配模式,多态(polymorphism) 中介(indirect
2、ion) 纯虚构(pure fabrication) 受保护变化(protected variations),多态(polymorphism),OO中的多态: 通过继承,实现类型的变化。(多种表现形态) 一个具体问题: POS需要进行税率计算,在不同的地区和国家,提供税率计算服务的方式可能有所不同。 接口的方式的不同、协议不同。 多态模式: 基于类型的选择 If else选择的弊病,多态模式实现基于类型的选择 可嵌入的软件组件 服务器组件的变化不应该影响到客户端软件。 许多(GoF)模式都是依赖于多态模式的,多态的实例,纯虚构(pure fabrication),概念模型的概念类到软件类的映射
3、 一些在领域讨论中没有的概念: 数据库 网络 协议 面临的问题: Sale对象中需要对销售进行持久化存储 其他对象也需要持久化存储自己的信息 解决的方法: 虚构一个持久化存储对象 该对象抽象的处理持其他对象的久化存储问题,纯虚构(pure fabrication),优点: 高内聚 可重用 虚构对象的构造 行为分离 表示分离 一般用于特定的计算机设备、软件的操作接口避免滥用 一个功能一个类(过渡分离),中介(indirection),将职责分配给中间对象,协调组件、服务的工作,以避免他们之间直接耦合。组件、服务的变化导致的系统的可重用性问题。,中介实例,受保护变化(protected varia
4、tions),不要和陌生人说话通过识别不稳定的变化,将职责分配给稳定的中间接口。在接口中进一步去处理已知的和未知的变化情况。以保护和隐藏内部结构。使之受变化的冲击减少。,CH26 GoF设计模式,GoF (gang of four) 来源于一本著名的书 这本书有4位作者 这本书中介绍了OOD的23种最常用(通用)的23种模式。本章将介绍其中的一部分模式。,GoF设计模式空间,GoF模式概览,创建型模式 一个类创建型模式使用继承改变被实例化的类, 而一个对象创建型模式将实例化委托给另一个对象 结构型模式 对象和组件之间的结构关系。 行为模式 行为模式涉及到算法和对象间职责的分配。 行为模式不仅描
5、述对象或类的模式,还描述它们之间的通信模式。这些模式刻划了在运行时难以跟踪的复杂的控制流。 它们将你的注意力从控制流转移到对象间的联系方式上来。,ADAPTER(适配器),将一个类的接口转换成客户希望的另外一个接口。 Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。,ADAPTER(适配器),Target 定义C l i e n t使用的与特定领域相关的接口。 Client 与符合Target接口的对象协同。 Adaptee 一个预先定义的接口,这个接口需要适配。 Adapter 对Adaptee的接口与Target接口进行适配,ADAPTER(适配器),以下情况使
6、用Adapter模式你想使用一个已经存在的类,而它的接口不符合你的需求。你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。(仅适用于对象A d a p t e r)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。,POS的适配器实现(利用多态性),ADAPTER(适配器),下例的适配器实现了和SAP财务软件系统的SOAP通信,FACTORY METHOD(工厂方法),意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子
7、类。在下列情况下可以使用Factory Method模式: 当一个类不知道它所必须创建的对象的类的时候。 当一个类希望由它的子类来指定它所创建的对象的时候。 当类将创建对象的职责委托给多个帮助(Helper)子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。,FACTORY METHOD(工厂方法),FACTORY METHOD(工厂方法),FACTORY METHOD(工厂方法),FACTORY METHOD(工厂方法),Product(Document) 定义工厂方法所创建的对象的接口。其作用是使各种具体的产品具有同样的创建和使用方法。 ConcreteProduct
8、(MyDocument) 实现Product接口。一种具体的产品。 Creator(Application) 声明工厂方法,该方法返回一个Product类型的对象。Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象。 可以调用工厂方法以创建一个Product对象。 ConcreteCreator(MyApplication) 重定义工厂方法以返回一个ConcreteProduct实例。,POS中的工厂方法,ABSTRACT FACTORY(抽象工厂),意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 在以下情况可以使用A
9、bstract Factory模式一个系统要独立于它的产品的创建、组合和表示时。一个系统要由多个产品系列中的一个来配置时。当你要强调一系列相关的产品对象的设计以便进行联合使用时。当你提供一个产品类库,而只想显示它们的接口而不是实现时。,ABSTRACT FACTORY(抽象工厂),ABSTRACT FACTORY(抽象工厂),A b s t r a c t F a c t o r 声明一个创建抽象产品对象的操作接口。C o n c r e t e F a c t o r y 实现创建具体产品对象的操作。 A b s t r a c t P r o d u c t 为一类产品对象声明一个接口。
10、C o n c r e t e P r o d u c t 定义一个将被相应的具体工厂创建的产品对象。 实现A b s t r a c t P r o d u c t接口。 C l i e n t 仅使用由A b s t r a c t F a c t o r y和A b s t r a c t P r o d u c t接口声明的类。,ABSTRACT FACTORY(抽象工厂),A b s t r a c t F a c t o r y模式有下面的一些优点和缺点:,它分离了具体的类: Abstract Factory模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和
11、过程,它将客户与类的实现分离。客户通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。它使得易于交换产品系列: 一个具体工厂类在一个应用中仅出现一次即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。在我们的用户界面的例子中,我们仅需转换到相应的工厂对象并重新创建接口,就可实现从M o t i f窗口组件转换为Presentation Manager窗口组件。它有利于产品的一致性 当一个系列中的产品对象被设计成一起工作时,一个应用一
12、次只能使用同一个系列中的对象,这一点很重要。而A b s t r a c t F a c t o r y很容易实现这一点。难以支持新种类的产品难以扩展抽象工厂以生产新种类的产品。 这是因为A b s t r a c t F a c t o r y接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及A b s t r a c t F a c t o r y类及其所有子类的改变。我们会在实现一节讨论这个问题的一个解决办法。,SINGLETON(单件独身),意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点。在下面的情况下可以使用Singleton模式 当类只能有一
13、个实例而且客户可以从一个众所周知的访问点访问它时。 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。,SINGLETON的实现,Class Singleton Private static Singleton _instance = 0; /一个静态的属性 Public static Singleton instance() /一个实例化静态方法if (_instance = 0)_instance = new Singleton();return _ instance ; ; Protected Singleton(); ,SINGLETON(单件独
14、身),S i n g l e t o n 定义一个I n s t a n c e操作,允许客户访问它的唯一实例。 I n s t a n c e是一个类操作(即一个类方法或C + +中的一个静态成员函数)。 他能负责创建它自己的唯一实例。,SINGLETON的UML表示,适配器、工厂、独身的使用,适配器、工厂、独身的使用,STRATEGY(策略),定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。,假设一个Composition类负责维护和更新一个正文浏览程序中显示的正文换行。换行策略不是Composition类实现的,而是由抽象的Com
15、positor类的子类各自独立地实现的。 Compositor各个子类实现不同的换行策略: SimpleCompositor实现一个简单的策略,它一次决定一个换行位置。 TeXCompositor实现查找换行位置的T E X算法。这个策略尽量全局地优化换行,也就是,一次处理一段文字的换行。 ArrayCompositor实现一个策略, 该策略使得每一行都含有一个固定数目的项,STRATEGY(策略),一个例子,说明不同的价格打折策略:,STRATEGY(策略),说明不同的价格打折策略的顺序图:(见需求),STRATEGY(策略),价格策略对销售对象的参数可见性:利用工厂创建策略:,POS打折扣
16、策略工厂,COMPOSITE(组合),将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 组合的例子:,COMPOSITE(组合),COMPOSITE(组合),组合的一般表示:,COMPOSITE(组合),组合的初始化操作顺序,COMPOSITE(组合),迭代操作,COMPOSITE(组合),Component (Graphic) 为组合中的对象声明接口。 在适当的情况下,实现所有类共有接口的缺省行为。 声明一个接口用于访问和管理C o m p o n e n t的子组件。 (可选)在递归结构中定义一个接口,用于访问一个父部件,
17、并在合适的情况下实现它。 Leaf (Rectangle、L i n e、Te x t等) 在组合中表示叶节点对象,叶节点没有子节点。 在组合中定义图元对象的行为。 Composite (Picture) 定义有子部件的那些部件的行为。 存储子部件。 在C o m p o n e n t接口中实现与子部件有关的操作。 Client 通过C o m p o n e n t接口操纵组合部件的对象。,COMPOSITE(组合),C o m p o s i t e模式的效果 定义了包含基本对象和组合对象的类层次结构基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去。客
18、户代码中,任何用到基本对象的地方都可以使用组合对象。 简化客户代码客户可以一致地使用组合结构和单个对象。通常用户不知道(也不关心)处理的是一个叶节点还是一个组合组件。这就简化了客户代码, 因为在定义组合的那些类中不需要写一些充斥着选择语句的函数。 使得更容易增加新类型的组件新定义的Composite或Leaf子类自动地与已有的结构和客户代码一起工作,客户程序不需因新的Component类而改变。 使你的设计变得更加一般化容易增加新组件也会产生一些问题,那就是很难限制组合中的组件。有时你希望一个组合只能有某些特定的组件。使用Composite时,你不能依赖类型系统施加这些约束,而必须在运行时刻进
19、行检查。,POS打折扣策略的组合,FACADE(外观),为子系统中的一组接口提供一个一致的界面, F a c a d e模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。FACADE主要用于将其他子系统(面向对象的和非面向对象的)的各种操作重新封装为一个新的对象界面。,FACADE(外观),例如: 将ODBC的数据库访问操作封装成为一个DBFacade,OBSERVER(观察者),定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。,OBSERVER(观察者),观察者的结构,OBSERVER(观察者),OBSERVER(观察者),图形用户界面中使用观察者 Observer.vb 定义Observer接口 Public Interface ObserverSub sendNotify(ByVal mesg As String) 用于发送更新通知 End InterfaceSubject.vb 定义Subject接口 Public Interface SubjectSub registerInterest(ByVal obs As observer) 用于注册观察者 End Interface,销售总额的观察者,