为什么需要面向对象设计

从需求开始谈起

  • 需求总是不完整的,错误的,容易让人产生误解
  • 需求一直在变化
  • 用户对需求的看法,可能在与开发人员讨论以及看到软件新的可能性后发生变化
  • 随着对问题的熟悉, 开发人员对问题领域的看法也会变化

不是需求在变, 而是人们对需求的理解在变化
如何去应对变化?

例子

假设你在一个会议上担当讲师, 听课的人在课后还要去听其他课程, 但他们不知道下一堂课的听课地点,
你的责任就是, 确保大家都知道下一节课去哪儿上。

结构化的分析方法

  1. 获取听课人的名单
  2. 对于名单上的每个人 , 做如下事情
  • 找到他要听的下一堂课
  • 找到该课程的听课地点
  • 找到从你的教室到下一堂课的路线图
  • 告诉这个人怎么走、

    你很有可能会这么做

  1. 在教室的后面贴一张地图, 标出每个教室的位置和路线
  2. 告诉大家: “下课后大家自己去看后面的地图, 自己找下一节课的位置”

    到底谁来负责?

    责任的转移:
    第一种方法: 直接给每个人提供指示, 责任全在老师自己身上
    第二种方法:只给出通用的指示(调用接口), 让每个人自己去完成任务 (面向对象的思路), 责任在各个学生身上
    让责任划分到合适的对象当中!

    面向对象设计的好处

    老师只需要对Student发出一个“笼统”的指令:gotoNextClassroom() 即可, 不用关心实现细节
    思考: 假设出现了需求变更, 你讲的课有研究生作为助教, 它们需要把本节课的反馈收集一下,先交到会议办公室,然后再去下一个教室。对于结构化设计和OOD怎么应对?

    应对变更

  • 对于结构化设计, 不得不对控制程序进行修改, 加上if else 判断以区分研究生和普通学生, 给研究生以特殊指令 – 修改控制程序,容易产生bug
  • 对于OOD , 根本不区分研究生和普通学生, 只是对Student这个抽象概念说: gotoNextClassRoom()

    1. for (Student student : students){
    2. // Student 可能是普通学生,也可能是研究生助教
    3. student.gotoNextClassRoom();
    4. }

    总结

  • 职责转移

    • 把职责划分到合适的类中去
    • 把细节封装起来
  • 只对接口进行操作

    • student.gotoNextClassRoom();

      面向对象设计

      面向对象设计准则

  • 发现变化并且封装变化

    • 找出可变之处, 把它独立出来,不要和那些不需要变化的代码混在一起。
    • 一个抽象的过程。
  • 针对接口编程而不是针对实现编程
  • 优先使用组合而不是继承

    面向对象设计原则

    面向对象基本五大设计原则有:

  • 单一职责原则 (SRP,Single Responsibility Principle )

  • 开闭原则 (OCP,Open Closed Principle)
  • 里氏替换原则 (LSP,Liskov Substitution Principle)
  • 接口隔离原则 (ISP,Interface Segregation Principle)
  • 依赖倒置原则 (DIP,Dependence Inversion Principle)

把这五个原则的首字母联合起来就是 SOLID (solid,稳定的),其代表的含义就是这五个原则结合使用的好处:建立稳定、灵活、健壮的设计。
另外还有两个设计原则:

  • 迪米特法则 (LoD,Law of Demeter)
    • 又称最少知识原则(LKP,Least Knowledge Principle)
  • 合成复用原则 (Composite Reuse Principle,CRP)