码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式-可复用面向对象软件的基础 [读书笔记]

时间:2016-04-17 22:50:11      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

由于如下笔记中有直接描述是该书的第几节,因此将该书的封面贴下:

技术分享



1.将软件与设计模式比拟为城市与建筑模式,那么在面向对象的解决方案里,我们将对象和接口看成墙壁和门窗,模式的核心在于提供了相关问题的解决方案。

  在软件设计中可能会遇到很多类似的问题,在每次遇到类似问题时我们不必全都新想办法来解决,而可以复用之前解决类似问题的方案,解决问题多之后就

  会有针对特定问题有特定(相对固定)的方式方法来解决,这相对固定的方式方法就是设计模式,其也算是经验总结。

  开篇有两种在设计模式书籍里面很重要的表格和关系图,分别描述了各设计模式设计支持的可变方面以及各个设计模式之间的关系,具体如下:

 技术分享

技术分享


2.一般来讲,模式有四个基本要素:模式名称(pattern name),问题(problem),解决方案(solution),效果(consequences)。
3.设计模式确定了所包含的类和实例,他们的角色,协作方式以及职责分配。
4.经典的MVC模式主要用到了Observer,Composite和Strategy三种设计模式。
  MVC包括三类对象,模型Model是应用对象,视图View是它在屏幕上的表示,控制器Controller定义用户界面对用户输入的响应方式
5.1.4节设计模式的编目,简短描述了23中设计模式的作用
6.设计模式依据其目的可以分为创建型(Creational),结构型(Structural),行为型(Behavioral)三种类型。
  创建型:与对象的创建有关(5种) Factory Method,Abstract Factory,Builder,Prototype,Singleton
  结构型:处理类或对象的组合(7种)Adapter,Birdge,Composite,Decorator,Facade,FlyWeight,Proxy
  行为型:对类或对象怎样交互和怎样分配职责进行描述(11种) Interpreter,Template Method,Chain of Responsibility,Command,
                                                     Iterator,Mediator,Mementor,Observer,State,Strategy,Visitor
  设计模式如果根据范围来分,则可以分为类模式和对象模式。
  类模式:处理类和子类之间的关系,这些关系通过继承来建立,编译时刻就已经确定下类,属于静态的。(4种)
  对象模式:处理对象间的关系,这些关系在运行时刻是可以变化的,具有动态性。(20种)
7.各设计模式之间也是有关系的,参看1.5中的关系图,各个相关模式之间加上某些需求就可以转换为另外一个模式。
8.复用方式中类继承与对象组合的区别:
  类继承:白箱复用,父类的实现对子类来说完全是透明的,创建新的类很方便,子类只需要少量的扩展即可形成新的类。
        编译时已经决定继承关系,静态,破坏类的封装性,父类的实现有改动直接影响子类,有可能改动并不使用子类,有牵一发而动全身的影响,
        这个可以通过继承抽象类来缓解,这样父类会有较少的具体实现。
  对象组合:黑箱复用,被组合的对象中只能调用组成成员对象的接口,无法知道其它具体实现,可以通过多态对组合成员对象在运行时动态修改
        不破坏封装性。
  优先是用对象组合,而不是类继承。理想状态下,如果你不是想要去创建行的构件,你应该能够只使用对象组合技术,通过组装已有的构件就能够获得
  你需要的功能。
9.委托是一种组合方法,它使得组合具有与继承同样的复用能力,在委托方式下,有两个对象参与处理一个请求,接收请求的对象将操作委托给它的代理
  者(delegate).这类似于子类将请求将给它的父类处理。State,Strategy,Visitor三种模式较多的运用到委托模式,在State模式中,一个对象将请求
  委托给一个描述当前状态的State对象来处理,在Strategy模式中,一个对象将一个特定的请求委托给一个描述请求执行策略的对象,一个对象只有一个
  状态,但它对不同的请求可以有许多策略。这两种模式的目的都是通过改变委托对象来改变委托对象的行为。在Visitor模式中,对象结构的每个元素上
  的操作总是被委托到Visitor对象上。


  委托是对象组合的特例,它告诉你对象组合作为一个代码复用机制可以替代继承。
10.参数化类型提供了除了类继承和对象组合之外的第三种方法来组合面向对象系统中的行为。这三种复用技术存在着较大的差异,对象组合允许你在
   运行时刻改变被组合的行为,但是它存在间接性,比较低效。类继承允许你提供操作的缺省实现,并通过子类重定义这些操作。参数化类型允许你改变
   类所用到的类型,典型的就是模板类,泛型的使用。类继承和参数化类型都不能在运行时刻被改变,即为静态设计,写代码时可以预见执行结果的。
11.1.6.7节,一般容易导致软件重新设计的原因,在软件设计初期就应该注意在这些情况下采用一些设计模式来使得软件松耦合,能够较为容易的进行修
   改和扩展,总之让软件更加灵活,后期维护和扩充起来比较方便。
   1) 通过显示地指定一个类来创建对象。
      Abstract Factory,Factory Method, Prototype
   2) 对特殊操作的依赖
      Chain of Responsibility,Command
   3) 对硬件和软件平台的依赖
      Abstract Factory, Bridge
   4) 对对象表示或实现的依赖
      Abstract Factory, Bridge, Memento,Proxy
   5) 算法依赖
      Builder,Iterator,Strategy,Template Method,Visitor
   6) 紧耦合
      Abstract Factory, Command, Facade, Mediator,Observer,Chain of Responsibility
   7) 通过生成子类来扩充功能
      Bridge, Chain of Responsibility,Composite,Decorator,Observer,Strategy
   8) 不能方便的对类进行修改
      Adapter,Decorator,Visitor
12.参考1.7中表1-2设计模式所支持的设计的可变方面,通过查看这些内容确定是否有必要使用设计模式,以及使用那个设计模式。
13.skip chapter2
14.创建型模式抽象了实例化过程,它帮助一个系统独立于如何创建,组合和表示它的那些对象。一个类创建型模式是用继承来改变被实例化的类,而一个对象
   创建型模式通过将实例化委托给另一个对象。
   创建型模式有两个主旋律:第一,将系统使用哪些具体的类的信息封装起来。第二,隐藏了这些类的实例是如何被创建和放在一起的。因此创建型模式在什么
   时候被创建,谁创建它,它是怎样被创建的等这些方面给于了很大的灵活性。它允许你用结构和功能差别很大的“产品”配置一个系统。配置可以是静态的(编译
   时指定,类继承),也可以是动态的(在运行时,对象组合)。
   [From Chapter 3]
   Factory Method, 子类继承父类,通过子类实现父类中的抽象方法达到改变被实例化的类。

                   定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method是一个类的实例化延迟到子类。

技术分享

   Abstract Factory, 传递对象给构造“产品”的方法,通过传递不同的对象,构造出不同的“产品”

                     提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

技术分享

   Builder, 传递对象给构造“产品”的方法,这个对象可以在它所创建的“产品”中添加新的功能以生成新的“产品”,而可以通过继承的方式改变“产品”的一部分
           或者“产品”被创建的方式。

           将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

技术分享

   Prototype, “产品”的创建可能需要不同的部件,不同的部件应该需要具体的对象,而在创建时通过传入对应部件的对象,在创建“产品”的方法里拷贝这些传入
              的部件对象进行“产品”的创建,可以用不同的对象来替换这些部件的原型对象以达到创建不同的“产品”。

            用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

技术分享

   Singleton, 单例模式可以保证在系统中仅有一个该“产品”的实例,其它对象可以迅速的访问它而不需要求助与全局变量或者函数。单例模式同样使得“产品”易于
              扩展或替换,且不需要修改已有的代码。
            保证一个类仅有一个实例,并提供一个访问它的全局访问点。
            一个很好的能够让一个类只有一个实例并且这个实例易于被访问的方法是让类自身负责保存它的唯一实例,这个类可以保证没有其它实例可以被创建(
            通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法,这就是Singleton模式。
            既然要控制从外部直接实例化该类的对象,就需要在类的构造器上控制实例化权限,通过private,protected修饰限制外部的实例化请求。
技术分享

   创建型设计模式间的区别:
   1) Abstract Factory与Builder都可以创建复杂对象,主要区别是Builder模式着重于一步步构造一个复杂对象,而Abstract Factory着重于多个系列的产品对象
      (简单的或者复杂的)。Builder在最后的一步返回产品对象,而Abstract Factory则是立即返回的。
      Composite通常是用Builder生成的。
   2) Abstract Factory经常使用工厂方法来实现,工厂方法通常在Template Method中被调用。


15.结构型模式涉及到如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口和实现。结构型对象模式不是对接口和实现进行组合,而是描述如何对
   一些对象进行组合,从而实现新功能的一些方法。因而可以在运行时刻改变对象组合关系,从而对象组合方式更灵活,但是这种机制用静态类组合是不可能实现的


   Composite: 其描述了如何构造一个类层次式结构,该结构由两种类型的对象(基元对象和组合对象)所对应的类构成,组合对象使得你可以组合基元对象以及其它组合
             对象,从而形成任意复杂的结构

             将对象组合成树形结构以表示"部分-整体"的层次结构,Composite使得用户对单个对象和组合对象的使用具有一致性。

技术分享

   Proxy: proxy对象作为其它对象的一个方便的替代或占位符,使用有多种方式,如它可以在局部空间中代表一个远程地址空间中的对象,也可以表示一个要求被加载
          的较大的对象,还可以用来保护对敏感对象的访问。其还提供了对对象的一些特有性质的一定程度上的间接访问,从而它可以限制,增强或者修改这些性质。
          为其他对象提供一种代理以控制对这个对象的访问。其还可以避免在对速率要求比较高的流程中创建大的对象,这种情况下可以先创建小的代理对象,到需要
          的时候创建其实体对象。

          Proxy的常见情况:远程代理,虚代理,保护代理,智能指引。

技术分享

技术分享

   FlyWeight(享元): 为了共享对象(争取效率和一致性)定义了一个结构,其主要强调对象的空间效率使用很多对象的应用必须考虑每一个对象的开销,使用对象共享而
                   不是进行对象复制会节省大量的空间资源
                   运用共享技术有效的支持大量细粒度的对象。
                   FlyWeight负责对内部状态的维护,在外部需要使用FlyWeight内部的对象时需要传递外部状态。例子如FlyWeight负责26个字符的图形颜色等状态的
                   维护,而当文本编辑器需要使用某个字符时需要将该字符在正文中的位置状态传递过来,或者需要确定其外部状态。

                   使用FlyWeight模式时,传输,查找和/或计算外部状态都会产生运行时的开销,尤其当FlyWeight原先被存储为内部状态时。

技术分享

技术分享

             
   Adapter: 适配器使得一个接口与其他接口兼容,从而给出多个不同接口的统一抽象。类适配器采用多重继承适配接口,类适配器的关键是用一个分支继承接口,而用
            另外一个分支继承接口的实现部分。通常在C++作出这一区分的方法是用公共方式继承接口,用私有方式继承接口的实现。

            将一个类的接口转换为客户希望的另外一个接口。使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作起来。别名包装器(Wrapper)

技术分享

   Facade: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。将一个大的系统分为若干个子系统有利于
           降低系统的复杂性,一种使得子系统间的通信和相互依赖关系达到最小,为达到这种目标的途径之一就是引入一个外观(facade)对象,它为子系统中较一般的
           设施提供一个单一而简单的界面。
           一个大的系统中存在很多小的子系统,外观模式就想一个小地图,简单明了的告诉客户你想要做什么,直接告诉Facade,其会将请求转给对应的子系统。进而对

           于对系统内部实现不关系的客户可以更加便捷的使用系统功能。

技术分享

技术分享

   Bridge: 将抽象部分和它的实现部分分离,是它们都可以独立的变化。优点:分离接口及其实现部分,提高可扩充性,实现细节对客户透明。

技术分享

   Decorator: 描述了如何动态的为对象天际职责,其采用递归方式组合对象,从而允许你添加任意多的对象职责。每个Decorator对象必须与其组件的接口兼容并且保证
              将消息传递给它,Decorator模式在转发一条消息之前或之后都可以完成它的工作。
              动态地给一个对象添加额外的职责。就增加功能来说,Decorator模式相比生成子类来说更加灵活。别名包装器(Wrapper)
              如果一个组件需要将组件嵌入另一个对象中, 由这个对象添加边框,这个嵌入的组件对象叫做装饰

              优点:比静态继承更灵活,避免在层次结构高层的类有太多的特征,Decorator与它的Component不一样,有许多小对象。

技术分享

技术分享



   结构型模式之间的区别与联系:
   1) 如果说FlyWeight模式说明了如何生成很多较小的对象,那么Facade模式则描述了如何用单个对象表示整个系统,模式中的facade表示一组对象,facade的职责是
      将消息转发给它所表示的对象。Bridge模式将对象的抽象和其实现分离,从而可以独立的改变它们。
   2) Bridge模式与对象适配器类似,不过它们的出发点不同,Bridge模式目的是将接口部分和实现部分分离,从而对它们可以较为容易的也相对独立的加以改变。而Adapter
      则意味着改变一个已有对象的接口。Decorator模式增强了其它对象的功能而同时又不改变它的接口。Proxy模式在不改变其它对象的接口的条件下,为该对象定义了一个
      代理
   3) 通常部件-父部件连接用于Responsibility of Chain模式,Decorator模式与Composite模式经常一起使用,当装饰与组合一起使用时,他们通常有一个公共的父类。因
      此装饰必须支持具有Add,Remove和GetChild操作的Component接口。
      FlyWeight让你共享组件,但不再能引用他们的父部件。
      Iterator用来遍历Composite。
      Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。
   4) Decorator看作一个对象的外壳,它可以改变这个对象的行为,而Strategy模式是一个用于改变对象的内核的。基于Strategy的方法可能需要修改component组件以及适应
      新的扩充,另一方面,一个策略可以有自己特定的接口,而装饰的接口则必须与组件的接口一致。这就意味着Component类很庞大时,策略也可以很小。
   5) Decorator模式不同于Adapter模式,因为装饰仅改变对象的职责并不改变它的接口,而适配器将给对象一个全新的接口。可以将装饰视为一个退化的,仅有一个组件的组合,
      然而,装饰仅给对象添加一些额外的职责---其目地不在于对象聚集。改变对象的两种途径,一种改变对象的外表(装饰),另一种改变对象的内核(Strategy)
   6) Abstract Factory模式可以与Facade模式一起使用以提供一个接口,这一接口可用来以一种子系统独立的方式创建子系统,Abstract Factory也可以代替Facade模式隐藏
      那些与平台相关的类。Mediator模式与Facade模式相似之处是他们抽象了一些已有类的功能,而Mediator的目的是对同事之间的任意通讯进行抽象,通常集中不属于任何单
      个对象的功能。Mediator的同事对象知道中介者并与之通信,而不是值额接与其他类对象通信。相对而言,Facade模式仅对于系统对象的接口进行抽象,从而使它们更容易
      使用,它并不定义新功能,子系统也不知道Facade的存在。通常来讲,只需要一个Facade对象,因此Facade对象通常属于Singleton模式。
   7) FlyWeight模式通常和Composite模式结合起来,用共享叶结点的有向无环图实现一个逻辑上的层次结构。最好使用FlyWeight实现State和Strategy对象。
   8) 适配器Adapter为它所适配的对象提供一个不同的接口,相反,代理提供了与它的实体相同的接口。然而,用于访问保护的代理可能会拒绝执行实体会执行的操作,因此,它
      的接口实际上可能只是实体接口的一个子集。尽管Decorator的实现部分与代理相似,但decorator的目地不一样,Decorator为对象添加一个或多个功能,而代理是控制对对
      象的访问。


16.行为模式涉及到算法与对象行为职责的分配。行为模式不仅描述对象或类的模式,还描述了它们之间的通信模式。行为模式刻画了在运行时难以跟踪的复杂的控制流,将你的注意力
   从控制流转移到对象间的联系方式上来。
   行为类模式使用继承机制在类间分派行为。Template Method,Interpreter
   行为对象模式使用对象复合(组合)而不是继承。一些行为模式描述了一组对等的对象怎样相互协作以完成其中任何一个对象都无法单独完成的任务。正因为一组对等对象要在一起协作
   完成一个任务,对象之间必须互相了解,而这就不可避免了增加了程序的耦合度,而行为模式就是为了能尽量的让这种耦合度降低,从而达到程序的松耦合。
   Mediator,Chain of Responsibility,Observer,Strategy,Command,State,Visitor,Iterator
   
   Chain Of Responsibility: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处
                            理它为止。Android中用得比较典型的就是touch event在各个视图层次之间的传递。

                            要沿链转发请求,并保证接收者为隐式的,每个在链上的对象都有一致的处理请求和访问链上后继者的接口。


技术分享

技术分享

   Command: 将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。别名动作(Action),事务(Transaction)。
            Android中典型的用法就是Widget上的时间处理,如Button的onclick等回调形式的实现。如我们经常会自定义一个OnClickListener作为参数传入相关方法,其实这个自定义的

           Listener就是一个ConcreteCommand,真正处理请求的对象。

  技术分享

技术分享

   Interpreter: 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。解释器模式使用类来表示每一条文法规则。

                从书里的描述看起来解释器模式貌似通过正则表达式的形式在语言解释,语法解析等领域使用。

技术分享

   Iterator: 别名Cursor,提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
             对列表(list)的访问和遍历从列表对象中分离出来并放入一个迭代器(iterator)对象中。迭代器类定义了一个访问该列表元素的接口。迭代器对象负责跟踪当前的元素,即它知道
             哪些元素已经遍历过了。将遍历机制与列表对象分离使我们可以定义不同的迭代器来实现不同的遍历策略,而无需在列表接口中列举它们。本身迭代器是和列表对象耦合在一起的,
             Client要使用迭代器,必须知道遍历的列表对象,但是我们可以通过多态来实现,达到将这种耦合度降低。

             Java中的容器遍历,Android中数据库Cursor应该都算是迭代器使用的典型例子吧

技术分享

   Mediator: 用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显示的互相引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。

技术分享

技术分享

   Memento: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。别名Token

技术分享

技术分享

   Observer: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。别名依赖(Dependents)
             此模式中的关键对象是目标(subject)和观察者(observer),这中交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需知道谁是它的观察者,
            可以有任意数目的观察者订阅并接收通知。
            观察者模式更新目标状态的方式有两种,分别是push和pull。push是目标者向各个观察者push相关change,不管是否所有观察者都需要。而pull呢,是目标者会做最小的通知,告
            诉观察者我改变了,但是如果有对这个改变感兴趣的观察者可以通过pull获取改变的细节并根据改变做相关的Action。

            在改变的由目标者到观察者的通知过程中,将观察者和目标者耦合在一起了,那么这中情况下可以通过ChangeManager(Mediator模式)来作为中间的一个中介,降低耦合度。

 技术分享

   State: 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。别名状态对象(Objects for State)

技术分享

   Strategy: 定义一系列的算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。别名政策(Policy)

技术分享

技术分享

   Template Method: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

                    父类中将不变的部门实现并控制好,而将需要子类实现的留下hook,这个钩子由子类来具体实现,模板方法应该指明哪些操作是钩子操作(可以被重定义)以及哪些是抽 象操作(必须被重定义),要有效地重用一个抽象类,子类编写者必须明确了解哪些操作是设计为有待重定义的。

技术分享

   Visitor: 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

            个人理解访问者模式应该是用于将与本类的属性关系不是很大的行为接口分离出来放到该类的访问者类中,也即将类中经常需要改变的操作(行为)分离出来。

技术分享

技术分享

   行为模式之间的区别与联系
   1) 职责链常与Composite一起使用,这种情况下,一个构件的父构件可作为它的后继。
   2) Composite模式可被用来实现宏命令。Memento模式可用来保持某个状态,命令用这一状态来取消它的效果。在被放入历史列表前必须被拷贝的命令起到一种原型的作用。
   3) 抽象语法树是一个复合模式(Composite)的实例;FlyWeight模式说明了如何在抽象语法树中共享终结符;解释器可用一个迭代器(Iterator)遍历该抽象语法书结构;Visitor可用来在
      一个类中维护抽象语法树中的各节点的行为。
   4) 迭代器常被应用到像复合(Composite)这样的递归结构上;多态迭代器靠Factory Method来实例化适当的迭代器子类;Memento常与迭代器模式一起使用,迭代器可使用一个Memento对象
      来捕获一个迭代的状态。迭代器在其内部存储memento.
   5) Facade与中介者的不同之处在于它是对一个对象子系统进行抽象,从而提供了一个更为方便的接口。它的协议是单向的,即Facade对象对这个子系统类提出请求,但反之则不行。相反,
      Mediator提供了各Collegue对象不支持或者不能支持的协作行为,而且协议是多向的。
   6) 命令模式可使用备忘录(Memento)来为可撤消的操作维护状态;备忘录可用于迭代模式。
   7) 通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者(Mediator模式)。ChangeManager可以使用Singleton模式来保证它是唯一的并且是可全局访问的。
   8) 状态对象(State)通常是Singleton的。FlyWeight模式解释了何时以及怎样共享状态对象。
   9) Strategy对象经常是很好的轻量级对象(flyWeight)
   10) Factory Method模式常被模板方法调用。模板方法使用继承来改变算法的一部分。Strategy使用委托来改变整个算法。
   11) 访问者可以用于对一个由Composite模式定义的对象结构进行操作。访问者可以用于解释。
   12) 一个Strategy对象封装一个算法。一个State对象封装一个与状态相关的行为。一个Mediator对象封装对象间的协议。一个Iterator对象封装访问和遍历一个聚集对象中的

      各个构件的方法。


设计模式-可复用面向对象软件的基础 [读书笔记]

标签:

原文地址:http://blog.csdn.net/annaload/article/details/51172013

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!