面向对象分析与设计

面向对象分析与设计

概述

  • 面向过程

    1. 分析出解决问题的步骤,然后逐步实现。-----“自己干活”

      • 解决问题的步骤
    2. 例如:婚礼筹办

      • 发请柬(选照片、措词、制作)

      • 宴席(场地、找厨师、准备桌椅餐具、计划菜品、购买食材)

      • 婚礼仪式(定婚礼仪式流程、请主持人)

    3. 公式:程序 = 算法 + 数据结构

    4. 优点:所有环节、细节自己掌控。

    5. 缺点:考虑所有细节,工作量大。

  • 面向对象

    1. 找出解决问题的人,然后分配职责,建立之间的交互。-----”雇人干活“

    2. 例如:婚礼筹办

      • 发请柬:找摄影公司(拍照片、制作请柬)

      • 宴席:找酒店(告诉对方标准、数量、挑选菜品)

      • 婚礼仪式:找婚庆公司(对方提供司仪、制定流程、提供设备、帮助执行)

    3. 公式:程序 = 对象 + 交互

    4. 优点

      • 思想层面:

        • 可模拟现实情景,更接近于人类思维。

        • 有利于梳理归纳、分析解决问题。

      • 技术层面:

        • 高复用:对重复的代码进行封装,提高开发效率。

        • 高扩展:增加新的功能,不修改以前的代码。

        • 高维护:代码可读性好,逻辑清晰,结构规整。

封装

定义:
  • 数据角度讲,将一些基本数据类型复合成一个自定义类型。

    • 将多个描述同一种事物的数据复合一个新的数据类型
  • 行为角度讲,向类外提供必要的功能,隐藏实现的细节。

    • 隐藏细节后,能更加专注一件事情
  • 设计角度:考虑封装方式,考虑封装程度,考虑类的内部,考虑类与类关系

    1. 分而治之()

      • 将一个大的需求分解为许多类,每个类处理一个独立的功能。

      • 拆分好处:便于分工,便于复用,可扩展性强。

      • 活字印刷:错字容易修改、文字能复用

      • 雕版印刷:错字难修改、文字不能复用

    2. 封装变化(一个变化点一个类)

      • 变化的地方独立封装,避免影响其他类。
    3. 高内聚

      • 类中各个方法都在完成一项任务(单一职责的类)。
    4. 低耦合

      • 类与类的关联性与依赖度要低(每个类独立),让一个类的改变,尽少影响其他类。
  • 作用

    • 松散耦合,降低了程序各部分之间的依赖性。

    • 数据和操作相关联,方法操作的是自己的数据。

    • 简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。

  • [例如:硬件高度集成化,又要可插拔]

    • 最高的内聚莫过于类中仅包含1个方法,将会导致高内聚高耦合。
    • 最低的耦合莫过于类中包含所有方法,将会导致低耦合低内聚。

继承

  • 作用 :隔离客户端代码与功能的实现方式(隔离用和做)。 隔离变化,当子类存在变化时,可抽象出父类用来约束子类,为之后的扩展子类固定模板。

  • 适用性:多个类在概念上是一致的,且需要进行统一的处理。

  • 设计角度:先有子类 再有父类 抽象化过程

  • 编码角度:先有父类 再有子类 具体化过程

多态

  • 定义:父类的同一种动作或者行为,在不同的子类上有不同的实现。

  • 作用:

    • 继承将相关概念的共性进行抽象,多态在共性的基础上,体现类型的个性化(一个行为有不同的实现)。

    • 增强程序扩展性,体现开闭原则。

  • 重写:子类实现了父类中相同的方法(方法名、参数),在调用该方法时,实际调用的是子类的方法。

设计原则

  1. 开闭原则(目标、总的指导思想)Open Closed Principle

    • 对扩展(新功能)开放,对修改(原代码)关闭。
  2. 类的单一职责(一个类的定义) Single Responsibility Principle

    • 一个类有且只有一个改变它的原因。
  3. 依赖倒置(依赖抽象) Dependency Inversion Principle

    • 客户端代码(调用的类)尽量依赖(使用)抽象的组件(父类)。 而不是依赖变化的子类。

    • 抽象的是稳定的。实现是多变的。

      """
        手雷爆炸了,可能伤害敌人、玩家、还可能伤害未知的事物(鸭子,树木)
        要求:如果在增加事物,不影响手雷的代码
        体会原则:开闭原则 依赖倒置
      """
      # ---------------使用者---------------
      class Grenade:
        def explode(self, target):
          # 如果对象没有继承InjuredObject父类,则报错
          if isinstance(target, InjuredObject):
            print("手雷爆炸了")
            target.injured()
          else:
            raise NotImplemented
      
      # 父类起到隔离变化的作用
      class InjuredObject:
        def __init__(self, name):
          self.name = name
      
        #如果子类没有该方法就会报错
        def injured(self):
          raise IndentationError
      
      # ------------定义者-------------
      class Emeny(InjuredObject):
        def injured(self):
          print("%s受伤了" % self.name)
      
      class Player(InjuredObject):
        def injured1(self):
          print("%s受伤了" % self.name)
      
  4. 组合复用原则(复用的最佳实践) Composite Reuse Principle

    • 如果仅仅为了代码复用优先选择组合复用,而非继承复用。

    • 组合的耦合性相对继承低。

  5. 里氏替换(继承后的重写,指导继承的设计) Liskov Substitution Principle

    • 父类出现的地方可以被子类替换,在替换后依然保持原功能(重写)。

    • 子类要拥有父类的所有功能。

    • 子类在重写父类方法时,尽量选择扩展重写(使用super()先调用父类方法),防止改变了功能。

  6. 迪米特法则(类与类交互的原则:低耦合) Law of Demeter

    • 不要和陌生人说话。

    • 类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因为这样可能降低耦合度。

类与类的关系
  • 作用域:起作用的范围

  • 泛化:子类与父类的关系,概念的复用,耦合度最高;

    • 特化(从父到子)B类泛化A类,意味B类是A类的一种;

    • 做法:B类继承A类

  • 关联(聚合/组合):部分与整体的关系,功能的复用,变化影响一个类;

    • A与B关联,意味着B是A的一部分;

    • 做法:在A类中包含B类型成员。

  • 依赖:合作关系,一种相对松散的协作,变化影响一个方法;

    • A类依赖B类,意味A类的某些功能靠B类实现;

    • 做法:B类对象作为A类中方法的参数,并不是A的成员。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值