编程思想

本文最后更新于:2024年11月10日 下午

编程思想

面向对象编程

  • 对象所带有的数据被称为对象的属性(property),对象所带有的功能函数被称为对象的方法(method),当你定义一个类时,你可以定义类的属性名称,并写出类方法的相应代码。
  • 如果你使用了类封装的方法,调试和维护程序会变得容易很多,封装的思路是:一个类提供特定的类方法给其他要使用这个类的代码来调用,外部的代码不能直接访问对象的数据,这样调试就变得简单了,因为你知道要在类里哪部分代码中找出BUG(只有某些特定的类方法才能改变对象的数据,所以直接找这部分代码即可),维护也变得容易,因为你改变一个类内部的功能代码后可以不需要改变调用这个类的代码。
  • 基本上所有的面向对象设计都会用到继承(inheritance),继承是通过声明"类似"于已存在的类来定义一个新的类的过程,但新的类可以有它自己特有的属性或者方法,已存在的类称为父类或父类(superclass,base,class),新定义的类称为子类(subclass)或派生类(derived class),继承是一种不需要复制粘贴就可以重用父类代码的方法,任何对父类的改进或修改都会自动传递给子类。

OOP 三大要素

  • 继承:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性的继承父类,通过使用继承我们能够方便的复用以前的代码,大大的提高开发效率。

    • 继承所描述的是"is-a”的关系,如果有两个对象A和B,若可以描述为"A是B”,则可以表示A继承B,其中B是被继承者,称之为父类或者超类,A是继承者称之为子类或者派生类。
    • 实际上继承者是被继承者的特殊化,它除了拥有被继承者的特性外,还拥有自己独有的特性,例如猫有抓老鼠,爬树等其他动物没有的特性,同时在继承关系中,继承者完全可以替换被继承者,反之则不可以,例如我们可以说猫是动物,但是不能说动物是猫就是这个道理,其实对于这个我们称之为向上转型
    • 面向对象的设计原则–里氏替换原则与向上转型息息相关。
    • 诚然,继承定义了类如何相互关联,共享特性,对于若干个相同或者相识的类,我们可以抽象出他们共有的行为或者属性并将其定义成一个父类,然后用其他类继承父类,他们不仅拥有父类的属性,方法还可以定义自己特有的属性或者方法。
  • 封装:封装从字面上理解就是包装的意思,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能的隐藏内部的细节,只保留一些对外接口使之与外部发生联系,系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互,也就是说用户是无需知道对象内部的细节,但可以通过该对象对外提供的接口来访问对象。

  • 多态性:所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能确定,也就是说多态最根本的作用就是把过程化的条件分支语句转化为对象的多态性,从而消除这些机构的条件分支语句。

    • 多态背后的思想是将"做什么”和"谁去做以及怎样去做”分离开来,也就是将"不变的事物"与”可能改变的事物"分离开来,– 《JavaScript设计模式与开发实践》
    • 多态最根本的好处在于,你不必再像对象询问"你是还是什么类型”而后根据得到的答案调用对象的某个行为——你只管调用该行为就是了,其他的一切多态机制都会为你安排妥当,– 《重构:改变既有代码的设计》

OOP 六原则一法则

  • 开闭原则(Open Close Principle):开闭原则的意思是**:对扩展开放,对修改关闭**。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。
  • 里氏代换原则(Liskov Substitution Principle):里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
  • 依赖倒转原则(Dependence Inversion Principle):这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
  • 接口隔离原则(Interface Segregation Principle):这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。
  • 迪米特法则,又称最少知道原则(Demeter Principle):最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
  • 合成复用原则(Composite Reuse Principle):合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

面向接口编程

  • 在真正的开发中,很多时候会选择面向接口编程。
  • 根本原因 :解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好。
  • 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的,在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了。
  • 而各个对象之间的协作关系则成为系统设计的关键,小到不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容,面向接口编程就是指按照这种思想来编程。

关于接口的理解

  • 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。

  • 接口的本身反映了系统设计人员对系统的抽象理解。

  • 接口应有两类:

    • 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class)
    • 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface)
  • 一个体有可能有多个抽象面,抽象体与抽象面是有区别的。

三个面向区别

  • 面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法。
  • 面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
  • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题。更多的体现就是对系统整体的架构。

面向过程

  • 面向过程是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数。
  • 优点:流程化使得编程任务明确,在开发之前基本考虑了实现方式和最终结果,具体步骤清楚,便于节点分析,效率高,面向过程强调代码的短小精悍,善于结合数据结构来开发高效率的程序。
  • 缺点:需要深入的思考,耗费精力,代码重用性低,扩展能力差,后期维护难度比较大。

  • 举个例子,下五子棋,面向过程的设计思路是首先分析解决这个问题的步骤:
    1. 开始游戏。
    2. 黑子先走。
    3. 绘制画面。
    4. 判断输赢。
    5. 轮到白子。
    6. 绘制画面。
    7. 判断输赢。
    8. 返回步骤2,9输出最后结果。
  • 用函数实现上面一个一个的步骤,然后在下五子棋的主函数里依次调用上面的函数:
1
2
3
4
5
6
7
8
9
10
11
下五子棋{
开始游戏()
黑子先走()
绘制画面()
判断输赢()
轮到白子()
绘制画面()
判断输赢()
返回到黑子先走()
输出最后结果。
}
  • 可见,面向过程始终关注的是怎么一步一步地判断棋局输赢的,通过控制代码,从而实现函数的顺序执行。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!