文章目录
  1. 1. 文档更新说明
  2. 2. 读书笔记
    1. 2.1. 原则
      1. 2.1.1. 单一原则
      2. 2.1.2. 开发-封闭原则
      3. 2.1.3. 依赖倒转原则
      4. 2.1.4. 里氏代换原则
    2. 2.2. 模式
      1. 2.2.1. 装饰模式
      2. 2.2.2. 代理模式
      3. 2.2.3. 简单工厂模式与工厂方法模式
      4. 2.2.4. 模板方法模式
  3. 3. 说明

文档更新说明

  • 最后更新 2016年04月1日
  • 首次更新 2016年03月27日

读书笔记

原则

单一原则

单一原则

  1. 就一个类而言,应该只有一个引起它变化的原因.[ASD]例如,一个类里面包含了复杂的逻辑和针对调用者的权限判断,这就有两个引起这个类要修改的原因了.例如一个类中包含了本身逻辑,数据处理,数据库SQL语句等,这就有了多个引起类要修改的原因了.
  2. 类如果不单一,就可能面临经常要修改的问题.
  3. 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制这个类完成其他职责的能力.这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏.[ASD]
  4. 软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离,判断是否需要分离出类来,就是如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责.[ASD]

上面提起的职责动机数量问题其实关系到一个设计的粗细粒度问题.比如一个类负责管理用户资料,这时候你要修改头像的保存细节或者修改地址的保存方式,这都需要去修改用户资料管理的类,你总不能说把修改头像和修改地址都独立成一个类吧.粗细粒度问题,才是单一原则真正的设计难点!

开发-封闭原则

开发-封闭原则

  1. 无论模块是多么的’封闭’,都会存在一些无法对之封闭的变化.既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择.他必须先猜测出最有可能发生的变化种类,然后构建抽象来隔离那些变化 [ASD]

  2. 在我们最初编写代码时,假设不会发生变化.当变化发生了,我们就必须立即采取行动,创建抽象来隔离以后发生同类变化. [ASD]

  3. 面对需求,对程序的改动是通过新增代码进行的,而不是更改现有的代码 [ASD]

  4. 我们希望的是在开发工作展开不久就可以知道可能发生的变化.查明可能发生的变化所需要的时间越长,要创建正 确的抽象就越困难. [ASD]

  5. 对于程序中的每一个部分都刻意进行抽象同样不是一个好主意.拒绝不成熟的抽象和抽象本身一样重要. [ASD]

依赖倒转原则

依赖倒转原则 (Dependence Inversion Principle)

  1. 高层模块不应该依赖于低层模块,两个都应该依赖抽象.[ASD]
  2. 抽象不应该依赖于细节,细节应该依赖于抽象.[ASD]

其实这个原则就是我们经常说的,针对接口编程而不针对实现编程.

里氏代换原则

里氏代换原则

  1. 子类必须能够替换掉他的父类型.
  2. 程序运行时,具体的类对象可以替换抽象类型的对象,程序不会出现任何问题。

在大多数情况下,这三个设计原则会同时出现,开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段,它们相辅相成,相互补充,目标一致,只是分析问题时所站角度不同而已。

推荐阅读
面向对象设计原则之依赖倒转原则
面向对象设计原则之四:依赖倒置原则

模式

装饰模式

装饰模式

  1. 当系统需要新功能的时候,是向旧的类中添加新的功能的代码.这些新的功能通常装饰了原有类的核心职责或主要行为.在主类中加入新的属性,新的方法和新的逻辑,会增加主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要[大话].
  2. 装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要包装的对象,因此,当需要执行特殊行为时,客户代码就可以在运行的时候根据需要有选择地,按顺序地使用装饰功能包装对象了.[DP]

个人理解:

  1. Component是类的核心功能.那些拥有共同接口的核心功能类被设计成Component的子类,称为ConcretComponent.
  2. Decorator顾名思义就是起到装饰作用,类除了核心功能外可能还需要一些小细节的处理,可以放在装饰类中实现.装饰类继承自Component,可以理解成Decorator本质上也是一个Component,只是被修饰过的而已.所以一个装饰过别人的Decorator又可以被当作Component被别人再次装饰一下.
  3. 每一个Decorator里面又组合了一个Component,目的就是当一个Decorator被别人装饰时,可以把它放到要装饰它的Decorator里面.比如ConcreteDecoratorB要装饰ConcreteDecoratorA.执行=>ConcreteDecoratorB.setComponent(ConcreteDecoratorA)相当于把A组合到自己体内去了.

变种一下,何以把setComponent直接合并到构造方法里面,就变成了new ConcreteDecoratorB(new ConcreteDecoratorA()).另外,如果Component只有一个类或者Decorator只有一个类,可以简化一下把抽象接口去掉.
推荐阅读:
装饰模式

代理模式

代理模式

代理模式应该是很常见的,以至于你都没察觉到那就是代理模式.

代理模式的应用

  1. 远程代理,也就是为一个对象在不同的地址空间提供局部代表.这样可以隐藏一个对象存在于不同地址空间的事实[DP]
  2. 虚拟代理,是根据需要要创建开销很大的对象.通过它来存放实例化需要很长时间的真实对象[DP]
  3. 安全代理,用来控制真实对象的访问权限[DP]
  4. 智能指引,是指当调用真实的对象时,代理处理另外一些事[DP]

上面几种说法可能不好理解,推荐阅读
为什么要使用代理模式

简单工厂模式与工厂方法模式

简单工厂模式与工厂方法模式

简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖.比如计算器,客户端传进一个’+’给工厂,工厂就会去实例化一个有加法运算功能的实例.[大话]缺陷是违背了开放—封闭原则.

工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到子类.[DP]遵循了开放—封闭原则.
工厂方法模式实现时,以上面计算器为例,客户端需要决定实例化哪一个具体工厂来实现运算类.例如客户端实例化一个减法工厂,然后就可以通过减法工厂去实例化出减法运算的对象.同时也可以发现,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断转移到了客户端代码来进行.如果想要增加功能,在简单工厂中是修改工厂类的逻辑判断代码,而在工厂方法模式中则是修改客户端实例化工厂的代码.要完全去除逻辑代码可以使用反射.

推荐阅读:
三种工厂模式汇总

模板方法模式

Template Method Pattern

模板方法模式,定义了一个操作中的算法骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤.[DP]
平时在代码中应该经常见过这个设计模式,比如排序,让你定义一个排序的对比函数.在实际开发中,如果遇到了一系列构成步骤相似的,但是有些步骤的实现可能不同的,就适用模板方法模式了.

推荐阅读:
模板方法模式深度解析

说明

[ASD] 《敏捷软件开发:原则、模式与实践》 作者:Robert C.Martin
[大话] 《大话设计模式》作者:程杰
[DP] 《设计模式:可复用面向对象软件的基础》作者:Erich Gamm,Richard Helm,Ralph Johnson, John Vlissides

文章目录
  1. 1. 文档更新说明
  2. 2. 读书笔记
    1. 2.1. 原则
      1. 2.1.1. 单一原则
      2. 2.1.2. 开发-封闭原则
      3. 2.1.3. 依赖倒转原则
      4. 2.1.4. 里氏代换原则
    2. 2.2. 模式
      1. 2.2.1. 装饰模式
      2. 2.2.2. 代理模式
      3. 2.2.3. 简单工厂模式与工厂方法模式
      4. 2.2.4. 模板方法模式
  3. 3. 说明