发新话题
打印

[开发] 《设计模式的艺术》刘伟

《设计模式的艺术》刘伟

  软件开发是一门技术,更是一门艺术。设计模式是面向对象软件开发的入门功夫,是前人经验的积累,它为构建可维护性和可复用性俱佳的软件而诞生。《设计模式的艺术:软件开发人员内功修炼之道》结合大量应用实例分析和讲解每一个设计模式,力求通过最通俗易懂的方式让读者学习和理解设计模式,并且在真实项目实例的引导下学会选择和合理运用设计模式。

  

  《设计模式的艺术:软件开发人员内功修炼之道》分为4个部分,共26章内容:第1部分(第1章、第2章)为基础知识,包括设计模式概述、UML类图与面向对象设计原则等;第2部分(第3~8章)为创建的艺术,包括6种常用的创建型设计模式;第3部分(第9~15章)为组合的艺术,包括7种常用的结构型设计模式;第4部分(第16—26章)为交互的艺术,包括11种常用的行为型设计模式。

  

TOP

基础知识

设计模式
  • 模式:在特定环境下人们解决某类重复出现问题的一套成功或有效的解决方案
  • 设计模式:一套被反复使用的,多人知晓的,经过分类编目的,代码设计经验的总结,使用设计模式是为了可重用代码,让代码更容易被他人理解并保证代码的可靠性

关键要素
  • Pattern name 模式名称
  • Problem 问题
  • Solution 解决方案
  • Consequence 效果

分类
  • Creational Pattern 创建型模式
  • Structural Pattern 结构型模式
  • Behavioral Pattern 行为型模式

用途
  • 前人经验的总结,提高设计和开发效率
  • 提供通用的形式,提高交流效率
  • 兼顾系统可重用性合可扩展性,避免重复开发
  • 设计模式文档化,方便交接
  • 更深入理解面向对象思想
流浪了那么多年,终于发现,这里才是我唯一的家。我只想回到这个对自己是那样熟悉和那样亲切的环境里,在和自己极为相似的人群里停留下来,才能够安心地去生活,安心地去爱与被爱。

TOP

类之间的关系(UML)

1. Association 关联关系
用于表示一类对象与另一类对象之间有联系
UML:直线
其中包含以下几种形式:
  • 双向关联
    • 顾客购买商品,卖出的商品也属于顾客
  • 单项关联
    • 顾客拥有地址
    • UML:带箭头的直线
  • 自关联
    • 类的属性对象是该类本身
  • Multiplicity 多重关联
    • 两个关联对象在数量上的对应关系
    • UML:关联直线上用数字或者数字范围表示
  • Aggregation 聚合关系
    • 表示整体与部分的关系:成员对象是整体对象的一部分,但成员独享也可以脱离整体对象独立存在
    • UML:带空心菱形的直线
  • Composition 组合关系
    • 表示整体与部分的关系:整体对象决定成为对象的生命周期,一旦整体对象不存在,成员对象也将不存在
    • UML:带实心菱形的直线

2. Dependency 依赖关系
特定事物的改变有可能会影响到使用该事务的其他事物
UML:带箭头的虚线

3. Generalization 泛化关系
继承关系,描述父类合子类之间的关系
UML:带空心三角形的直线

4. Realization 接口与实现关系
接口与类之间的实现关系,类实现了接口,类中的操作实现了接口中所声明的操作
UML:带空心三角形的虚线
流浪了那么多年,终于发现,这里才是我唯一的家。我只想回到这个对自己是那样熟悉和那样亲切的环境里,在和自己极为相似的人群里停留下来,才能够安心地去生活,安心地去爱与被爱。

TOP

面向对象设计原则

SRP单一职责原则 Sigle Responsibility Principle
  • 一个类只负责一个功能领域中的相应职责
  • 一个类只有一个引起它变化的原因

OCP开闭原则 Open-Closed Principle
  • 一个软件提示应当对扩展开放,对修改关闭
  • 软件实体应尽量在不修改原有代码的情况下进行扩展

LSP里氏代换原则 Liskov Substitution Principle
  • 所有引用父类(基类)的地方,必须能透明的使用其子类的对象
  • 在软件中将一个父类(基类)对象替换成它子类对象,程序将不产生任何错误和异常
  • 如果软件实体使用的是一个子类对象,则不一定能够使用父类(基类)对象

DIP依赖倒转原则 Dependency Inversion Principle
  • 抽象不应该依赖于细节,细节应该依赖于抽象
  • 要针对接口编程,而不是针对实现编程
  • 代码中尽量引用层次高的抽象层类(接口合抽象类)进行变量类型声明,参数类型声明,方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些
  • 具体类应该只实现接口或抽象类中声明过的方法,而不要给出多余的方法
  • 对抽象类进行编程,对具体类的对象使用依赖注入的方式注入到其他对象中
  • Dependency Injection DI依赖注入
    • 当一个对象要与其他对象发生依赖关系时,通过抽象来注入所依赖的对象
    • 注入方式
      • 构造注入
        • 通过构造函数来传入具类的对象
      • 设值注入(Setter注入)
        • 通过setter方法来传入具体类的对象
      • 接口注入
        • 通过实现在接口中声明的业务方法来传入具体类的对象
    • 在定义时使用的是抽象类型,在运行时再传入具体类型的对象,由子类覆盖父类对象

ISP接口隔离原则 Interface Segregation Principle
  • 使用多个专门的接口,二不使用单一的总接口
  • 客户端不应该依赖那些它不需要的接口
  • 当一个接口太大时,需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可
  • 需要注意控制接口的粒度,接口不能太小,否则系统中接口泛滥不利于维护;接口不能太大,否则灵活性较差使用不便;一般接口仅包含某一类用户定制的方法

CRP合成复用原则 Composite Reuse Principle
  • 尽量使用对象组合,而不是继承来达到复用的目的
  • 新的对象里通过关联关系(组合/聚合关系)使用已有对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用功能的目的
  • 复用时尽量使用组合/聚合关系,少用继承
  • 如使用继承关系需严格遵守里氏代换原则
  • 白箱复用
    • 通过继承来复用会破坏系统的封装性,因为继承会将父类的实现细节暴露给子类,由于父类的内部细节通过对子类是可见的,如果父类发生改变,子类的实现也不得不发生改变
    • 从父类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性
  • 黑箱复用
    • 通过组合/聚合关系来复用,可以将已有的对象(成员对象)纳入到新对象中,使之成为新对象的一部分,同时该成员对象的内部实现细节对新对象不可见,,如果成员对象发生改变,对新对象的影响不大
    • 合成复用可以在运行时动态进行,新对象可以动态地引用与成员对象同类型的其他对象

LoD迪米特法则 Law of Demeter
  • 一个软件实体应该尽可能少的与其他实体发生相互作用
  • 不要和“陌生人”说话,只与你的直接"朋友"通信
  • “朋友”定义
    • 当前对象本身(this)
    • 以参数形式传入到当前对象方法中的对象
    • 当前对象的成员对象
    • 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友
    • 当前对象所创建的对象
  • 如果两个对象彼此直接通信,那么两个对象不应该发生任何直接的相互作用;如果其中一个对象需要调用另一个对象的方法,可以通过第三者转发这个调用
  • 类的结构设计上,每个类都应该尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应该设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应该降到最低
流浪了那么多年,终于发现,这里才是我唯一的家。我只想回到这个对自己是那样熟悉和那样亲切的环境里,在和自己极为相似的人群里停留下来,才能够安心地去生活,安心地去爱与被爱。

TOP

常用设计模式一览表

流浪了那么多年,终于发现,这里才是我唯一的家。我只想回到这个对自己是那样熟悉和那样亲切的环境里,在和自己极为相似的人群里停留下来,才能够安心地去生活,安心地去爱与被爱。

TOP

发新话题