《图解设计模式》读书笔记

 关于设计模式的思想:

1.设计模式的作用,就是帮助我们编写可复用的类。通过设计,使代码解耦,响应变化。

2.不要使用具体类来编程,要优先使用抽象类和接口来编程

3.良好的实际模式,可以减少系统的复杂性,提高系统易用性

4.定义抽象类,抽象重要功能(API),把“定义”和“实现”分离开来,从而实现解耦和可复用

 

关于UML:

1.斜体方式显示:表示抽象类或者抽象方法

2.下划线方式显示:表示是静态类或者静态方法

3.使用箭头表示两个类关系的时候,可以在类名上面加上黑色三角表示关联关系

4.UML的时序图(sequence diagram)用来表示程序在工作时其内部方法的调用顺序,以及事件的发生顺序

5.类图表示的是“不因时间流逝而发生变化的关系(静态关系)”,时序图则相反,表示的是“随时间发生变化的东西(动态行为)”

理解角色——谁扮演了白雪公主

第1部分 适应设计模式

第一章、Iterator(迭代器)模式

角色:Iterator(迭代器)、ConcreterIterator(具体的迭代器)、Aggregate(集合)、ConcreterLterator(具体的集合)

个人理解:通过ConcreterLterator里实现具体hasNext接口和next接口,来定制化写集合的遍历逻辑

 好处:使遍历的实现与使用场景分离出来,遍历的实现,可以由集合的开发者自定义,而集合的使用者,则只需调用遍历的接口使用就行。

 

第二章、Adapter(适配器)模式

1.类适配器模式(使用继承的适配器)

 

角色:Target对象(Print)、Adaptee被适配(Banner)、Adapter适配(PrintBanner)、

个人理解:通过实现接口方法(需求)并调用基础类(实际情况)来实现

使用场景

       1)封装。测试封装好的类,为了不破坏原有组件,而直接继承\调用它

  2)复用。为了实现某些接口,而不用重复编写某些相同代码,可以使用适配器模式,把老代码引用过来。

  3)继承。为了能在新版本调用老版本的“组件”,可以通过加适配器,来使老版本的代码兼容新版本

 

第2部分 交给子类

第三章、Template method模式

 

 角色:AbstractClass(抽象类)、ConcreteClass(具体类)

个人理解:抽象类复杂声明抽象方法和模版方法(调用抽象方法)、具体类来实现抽象类里的抽象方法

使用场景

  算法。模版方法是定义算法主逻辑的好地方,一些抽象逻辑可以再根据实际情况来继承实现。

子类责任:子类具有实现父类抽象方法的责任。因此父类可以要求子类去实现他要求的内容!

 

第四章、Factory Method模式

 

角色:Creator(创建者)、Product(产品)、ConcreteCreator(具体的创建者)、ConcreteProduct(具体的产品)

注意:工厂模式是模版模式的典型应用

应用场景

  在需要产生类似功能的实例时使用,如JDBC。调用者不需要关心实例如何产生的。

扩展——父类要求子类生成实例的三种方法

  1.父类指定此方法为抽象方法,这样,子类就必须实现此方法,否则会编译报错(推荐)

  2.父类为其实现默认方法,这样,子类没有实现父类方法,就调用父类的默认方法

  3.父类在此方法中抛出异常,这样,子类没有实现此方法的话,执行的时候,就会主动抛出Exception

 

 第3部分 生成实例

第五章、singleton模式

注意

  1)构造函数是private的

  2)实例可以在类初始化的时候生成(懒汉模式),也可以在getInstance方法第一次被调用时生成(饿汉模式)。饿汉模式要注意加锁解决多线程的问题

 

第六章 Prototype模式

角色:Prototype(原型)、ConcretePrototype(具体的原型)、Client(调用者)

注意:浅拷贝、深拷贝的问题(把model克隆给DTO也采用了克隆,也是采用实例拷贝)

使用场景:

  1)需要生成很多个实例,而且实例可能是由同一个类/不同类new出来的

  2)生成的实例过程很复杂(如使用鼠标画的图),这时与其重现生成的过程,不如直接克隆实例来的方便

  3)可以通过封装成框架代码,来控制生成实例的规范

 

扩展1——在设计模式中,出现类名是束缚吗:

  因为设计模式的目标是把代码作为“组件”而复用,而组件,当然是不能经常修改源码,一旦设计模式中出现具体的类名,势必会破坏组件的封装性,和业务产生耦合。理想的情况是“组件”被打成lib包引入到项目中使用而不需要重新编译

扩展2——标记接口(marker interface):

  Cloneable并没有定义任何方法,像这种接口,被称为标记接口,只用来表示可以使用Object类里的clone方法来进行复制

 

 第七章 Builder模式

角色:Builder(建造者)、ConcreteBuilder(具体建造者)、Director(建工)、Client(使用者)

个人理解:建造者模式和模板模式很类似,都是把具体的实现交给实现类来处理,而逻辑,都是由抽象方法先模拟,然后由具体的实现类来根据实际业务实现。他们2者的区别是,模板方法,是通过子类继承父类,来实现抽象方法。而建造者模式,是通过组合的方式(Director类)。因为组合比基础更灵活,所以从这点上讲,建造模式比模板模式也更灵活。

扩展——谁知道什么:在面向对象的模式设计中,谁知道什么是很重要的一点,正因为好的设计模式屏蔽了很多细节,使组件解耦,开发者在调用组件的时候,才能不需要很多东西。正因为不知道才能够替换,正因为可以替换,组件才具有高价值。作为设计人员,我们必须时刻关注这种“可替换性”。

 

第八章 Abstract Factory 模式  

角色:AbstractProduct(抽象产品)、AbstractFactory(抽象工厂)、client(委托者)、ConcreteProduct(具体产品)、ConcreteFactory(具体工厂)

优点:易于增加工厂

缺点:难以增加零件

个人理解:抽象工厂模式和工厂模式(还有个简单工厂模式)类似,但是抽象工厂模式是在工厂模式上面又抽象了一层。在工厂级别就抽象出来了,就可以从实现具体产品,转变成实现哪类具体的产品。如果只生产某些具体的产品,可以用工厂模式,但如果是要区分生产某些类的产品,则应该用抽象工厂方法

扩展——JAVA生成实例的几种方法

  1)new

  2)clone

  3)newInstance:Object.getClass().newInstance()

 

第4部分 分开考虑

第9章 Bridge模式

类的功能层次结构:父类具有基本功能,在子类中增加新的功能

类的实现层次结构:父类通过声明抽象方法来定义接口,子类通过实现具体方法来实现接口

 

角色:Abstraction(抽象化)、RefinedAbstraction(改善后的抽象化,增加了新功能)、Implementor(实现类)、ConcreteImplmentor(具体实现类)

扩展——继承是强关联、委托是弱关联(Bridge模式中,RefinedAbstraction是继承关系、Implementor是委托关系)

优点:把类的功能层次结构和类的实现层次结构分离开了,这样有利于它们独立的扩展

举例:不同操作系统上,实现一个程序。程序可以不断扩展,实现可以不断增加

 

第10章 strategy模式

角色:Strategy(策略)、ConcreteStrategy(具体策略)、Context(上下文)

要点:在上下文中使用策略时,使用委托这种弱关系可以方便替换算法

举例:算法、根据具体业务状态选择不同策略(程序运行时)

 

第5部分 一致性

第11章 Composite模式

简介: 能够是容器和内容具有一致性,创造出地递归结构的模式

角色:Leaf(树叶,不能放入对象)、Composite(复合物,容器,可以放入对象)、Component(父类,抽象类)、Client(使用者)

使用场景:文件系统、联合测试、窗口、宏命令,其它一切树形数据结构

 

第12章Decorator模式

 

角色:Component(被装饰物、核心角色、抽象类)、ConcreteComponent(具体的被装饰物)、Decorator(装饰物、抽象类)、ConcreteDecorator(具体的装饰物)

核心思想:

  1)接口的透明性。装饰物和被装饰物,具有统一的接口(得益于他们都继承同一个抽象类)

  2)递归。和组合模式一样,装饰模式也是递归结构

  3)使用委托,利用递归调用,动态的增加功能

应用举例:java.IO new xxxReader( new BufferReader( new InputStreamReader(xxx) ) )

扩展:一致性

  1)继承:父类和子类一致性

  2)委托:自己和被委托的对象保持一致性

  3)实现:不同实现者之间保持一致性

 

第6部分

第13章 Visitor模式

 

角色:Visitor(访问者,抽象类)、ConcreteVisitor(具体的访问者,实现visit接口)、Element(访问对象、抽象类)、ConcreteElement(具体的访问对象)、ObjectStructure(对象结构,遍历Element,处理Element角色的集合)

 该模式的特点:

  1)可以很方便的增加ConcreteVisitor,难以增加ConcreteElement。因为具体的逻辑被交给了ConcreteVisitor,所以修改逻辑完全不需要改ConcreteElement。

  2)Visitor和Element有双重分发:visitor.visit(element)、element.accept(visitor)。借助这种互相调用的关系,加上递归调用,可以把逻辑都递归汇总到ConcreteVisitor的visit方法中。

 

第14章 Chain of Responsibility

核心思想:将许多对象组成一条职责链,然后按照它们在职责链上的顺序一个一个地找出到底应该谁来负责处理。

角色:Handle(处理者,抽象类)、ConcreteHandler(具体的处理者)、Client(请求者)

个人理解:核心是Handle类,里面使用模板方法定义好了调用链的逻辑,然后通过递归调用下一个处理人。其它ConcreteHandler只负责定义各自的业务处理逻辑,然后等待被调用就行

优点:

  1)弱化了发送请求人和处理请求人之间的关系,发送请求人不需要知道“下一个处理人是谁”。

  2)可以动态的改变责任链:因为处理者可以通过委托“推卸责任”,从而使自己只处理应该自己处理的任务(单一职责原则)

扩展:责任链模式虽然灵活和解耦,但是会降低效率,因为需要在链路上都走一遍。所以如果需要非常快的处理的时候,不应该使用此模式(类似Arrylist和LinkList那样,链表结构在查询的时候,速度是比较慢的)

 

第7部分 简单化  

第15章 Facade模式

角色:facde(窗口)、classX(构成系统的其它角色)、client(业务场景,调用者)

重点:对外的API(接口)变少了,client只需要关注facade的public接口,而不用关心它下面的那些复杂逻辑

优点:封装性好

使用举例:MVC中的controller层,框架代码里的对外接口

 

 第16章 Mediator模式

角色:Mediator(仲裁者、中介者、接口)、ConcreteMediator(具体的仲裁者、实现类)、Colleague(同事、抽象)、ConcreteColleague(具体的同事、实现类)

中心思想:把原本分散在各个colleague的(会互相影响其它colleague的)业务逻辑,集中化到Mediator去处理,通过触发Mediator的onChanger接口,监听变化。

优点:

  1)把复杂的互相关联的业务逻辑,集中化管来起来。避免业务逻辑分散在各个colleague类中

  2)colleague类可以复用和扩展

应用场景(个人猜测):服务注册、消息总线

 

第8部分 管理状体

第17章Observer(观察者)模式

角色:Subject(观察对象,抽象类)、ConcreteSuject(具体的观察者)、Observer(观察者)、ConcreteObserver(具体的观察者)

中心思想:观察对象,通过“注册”多个观察者,来消息通知(通过update接口)各个观察者。它的有一个延伸,叫订阅发布者模式。

思路拓展:设计模式的一个常用手段,就是利用抽象类,抽象具体类的关键方法。然后将实例作为参数传递至类中,或者在类的字段中保存实例时,不实用具体类型,而是使用抽象类型和接口。

这样的实现方式可以帮助我们轻松替换具体类,实现了解构。

 

第18章 Memento(备忘录)模式

角色:Originator(生成者,被保存的对象)、Memento(纪念品,存档)、Caretaker(责任人,调用者)

中心思想:Caretaker将Originator的状态,保存为Memento

优点:职责分担,caretaker只负责执行保存动作,Orginator负责保存的逻辑,Memento负责决定保存的信息(提供保存的接口)

扩展——宽接口、窄接口:根据职责的不同,限制不同接口的访问权限,只暴露自己必要的信息

应用场景:复制/粘贴、游戏存档

  

第19章 State 模式

角色:State(状态,抽象类)、ConcreteState(具体状态、实现类)、Context(状况,上下文)

中心思想:Contenxt调用State类,来根据不同情况处理不同逻辑。具体的处理逻辑,放在State的子类(ConcreteState)里来实现

核心思想:依赖于状体的处理,该模式下,通过定义抽象类(state)和具体的实现类(ConcreteState),可以实现“状态不同处理也不同”

 

第9部分 避免浪费

第20章 Flyweight(享元)模式

 

角色:Flyweight(共享类,轻量级)、FlyweightFactory(共享类工程)、Client(调用者)

中心思想:FlywightFactory通过pool(共享池)来保存共享Flyweight(单例模式),使得Flyweight可以被复用

优点:可以批量修改共享类,可以减少资源开销

应用举例:spring bean(个人猜测)

 

第21章 proxy模式

角色:subject(主体,抽象类)、proxy(代理人,只有在自己不能处理的时候,才交给RealSubject去处理)、RealSubject(实际的主体、在代理人无法处理时出场)、client(调用者,可以随意调用proxy或realSubject)

中心思想:通过设置统一的接口(subject),试client可以不直接调用realSuject,而是通过调用proxy来实现业务功能。而在proxy里,相当于做了一层缓存,只有才必要时才调用realsubject

优点:

  1)划分了proxy和realSubject两个角色,使得他们互相不影响,client可以选择单独使用realSubject或者使用代理来做,而不需要改变业务逻辑

  2)因为proxy和realSubject都实现了subject接口所以client可以不必在意,使用的是哪个具体类去实现逻辑。因此proxy可以说具有透明性,透过它就像可以直接看到realSubject一样

应用举例:http代理、缓存

 

第10部分 用类来表现

第22章 command(命令、事件)模式

 

 第23章 Interpreter模式

角色:AbstractExpression(抽象表达式)、TerminalExpression(终结表达式、具体实现)、NonterminalExpression(非终结表达式、具体实现)、Context(上下文,被解析对象)、Clinet(调用者)

个人理解:通过抽象接口,统一解析的方法,然后递归调用具体的解析类直到终结表达式

 

 

 

 

  

 

 

 

posted @ 2018-06-08 16:39  系统攻城狮  阅读(1219)  评论(0编辑  收藏  举报