RSS

When I click “object-oriented” …

24 Jul

它是一种实践

面向对象不是编程模型而是一种人们总结出的实践,它优于过程化或模块化编程方式。

哲学

它的哲学是拉近现实物体或概念与程序实体之间的距离,不仅将程序中的参与单元看作对象并将对象归类,而且在对现实物体以对象的方式建模中,将各对象作为属性的数据纳入各自结构,并与其相关行为组织在一起;另外,还通过继承或组合等方式描述实体间的存在的数据或行为的关系。

形式

面向对象编程语言有两种形式,基于类型(class-based)和基于原型(prototype-based)。

  • 基于类型的形式自C++时代就确立了在静态语言中的绝对地位,它明确提出类型的概念,认为对象都是类型的实例化;类型通过继承的方式重用其他类型的属性和方法。可以用“is-a”来解释上述两关系:我们可以说对象是一个类型的具体化,也可以说继承自类型B的类型A是类型B的一个派生。基于类型的形式在重用其他类型的行为方面的还有另一种方式叫组合,它将类型B的对象作为类型A的属性,以便直接使用。可以用”has-a”来解释组合:类型A中有一个类型B的对象做属性。
  • 基于原型的形式也可被称为类型无关的或基于实例的编程形式,它最出名的实现语言莫过于javascript。除了直接创建自身对象之外,它以其他对象作为原型通过克隆(clone)的方式重用其他对象的行为。通过对象得到新型对象,并在被调用时追溯原型对象中的方法,支持这种编程方式的语言特性是委托(delegation)。

OOP核心

  • 封装(encapsulation),它是能称为面向对象编程的最重要的特点,它将对象自有的属性和行为封在类型中,限制内外的访问接口,在不同种类的类型之间划清界线,明确了模型,保证了数据安全。
  • 继承(inheritance),它实现了类型级别的抽象和代码重用。
  • 多态(polymorphism),它为面向对象设计提供了充足的自由度。它能通过接口级别的抽象,利用类型匹配和晚绑定,实现从多种表现形式中为对象或方法做出选择。

OOD原则

  • 单一职责原则(single responsibility principle)。封装的目的是将对象自身的行为限制在自身类型中,而该原则进一步强调类型应当专注,只因一个变数而变化,所有的行为集合体只在扮演一个角色,承担单一的职责。引申的,其中所有的方法也只各做一件事。
  • 开放封闭原则(open-close principle)。对扩展开放,对修改封闭。经常考虑的是现在如何设计才能在未来做扩展的同时,能尽量不修改现有系统的代码,或能够将修改降低到少数的几个地方。
  • Liskov替换原则(Liskov substitution principle)。它要求所有子类的对象在代替其父类被使用时都不会得到错误的结果,这是在保证以多态方式使用时不会出错;若该原则被打破,那么开放封闭原则多半也同时被打破了。这是一个比较苛刻的原则,子类重写父类方法似乎变得不可能了,可是仔细想想会发现,似乎当初对父类抽象得还不够彻底。
  • 依赖倒置原则(Dependency inversion principle)。高层模块需要调用低层模块的方法,但不能直接依赖,而是应让两者都依赖于接口。这是该原则的第一层意思,它的初衷是强调要面向接口编程,而不是面向实现,达到降低耦合的目的。这基本是对的,不过我觉得接口被过分强调了,应该在未来可能会扩展的地方考虑接口的使用,不要过度设计徒增代码。该原则还有第二层意思,抽象不应依赖于细节,细节应该依赖于抽象,这才是“倒置”二字的本意。因为我们往往是由简单到复杂,由单一类型到多种类型地在扩展程序,所以为有共同特点的类做抽象常是在已有实现类之后决定的,这时要考虑抽象是否彻底、是否有对实现的依赖。不过我觉得这种随机应变的抽象手法问题不大,大可不必一开始就死磕接口,那才是过度设计了,拥抱变化不是白说的。可以实现分析下问题,选择合适的设计模式是个好主意。
  • 接口隔离原则(Interface segregation principle)。这个原则比较简单,它针对的是过多的接口集中在一起的问题。就像为类划分单一的职责一样,也应为接口考虑较单一的分类,不要吧所有接口方法都堆在一个接口中。好处是客户可以有选择地实现特定的接口,而不实现无关的,实现解耦合。
———————-
后面一篇文章中对类继承和Liskov替换原则有更多讨论
 

About Wu Shaobo

@ThoughtWorks
Comments Off on When I click “object-oriented” …

Posted by in Uncategorized

 

Comments are closed.