面向对象的三大基本特征和五大设计原则

2017-02-19  本文已影响0人  二叉树儿
面向对象学习大纲

1、面向对象概念

1.1、理解面向对象

  1. 面向对象是相对面向过程而言;
  2. 面向对象和面向过程都是一种思想;
  3. 面向过程:强调的是功能行为,面向对象:将功能封装进对象,强调具备了功能的对象;
  4. 面向对象是基于面向过程的。

1.2、面向对象特点

是一种符合人们思考习惯的思想,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者,使用面向对象思想编程时:

  1. 先要去找具有所需的功能的对象来用;
  2. 如果该对象不存在,那么创建一个具有所需功能的对象。

1.3、类与对象的关系

  1. 类:对现实生活中事物的描述,它将数据以及这些数据上的操作封装在一起,对象:就是这类事物,实实在在存在的;
  2. 类是抽象的,不占用内存,而对象是具体的,占用存储空间;
  3. 类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板;
  4. 映射到java中,描述就是class定义的类。具体对象就是对应java在堆内存中用new建立实体。

2、面向对象三大基本特征:封装、继承、多态

2.1、封装

面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性,对象是封装的最基本单位。封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。

2.1.1、访问权限控制

类的属性和行为根据需求的不同可以通过private、protected、public权限修饰符去修饰,比如小明有一个属性money,对于money属性如果不允许任何人访问,则使用private修饰,如果对自己的儿子开放权限(子类),则使用protected修饰,如果小明很无私,对所有人开放就可以使用public修饰。对于行为也是如此。通常的做法是:将一个类中的成员变量定义成私有的,只有这个类自己的方法才可以访问到这些成员变量,同时提供一些get、set方法。

2.1.2、封装原则:谁拥有数据,谁就对外提供操作这些数据的方法

2.1.2.1、人要在黑板上画圆

这一共涉及三个对象:人、黑板、圆,画圆的方法要分配给哪个对象呢?由于画圆需要使用到圆心和半径,圆心和半径显然是圆的属性,如果将它们在类中定义成了私有的成员变量,那么,画圆的方法必须分配给圆,它才能访问到圆心和半径这两个属性,人以后只是调用圆的画圆方法、表示给圆发给消息而已,画圆这个方法不应该分配在人这个对象上,这就是面向对象的封装性,即将对象封装成一个高度自治和相对封闭的个体,对象状态(属性)由这个对象自己的行为(方法)来读取和改变。

2.1.2.1、列车司机刹车

刹车的动作是分配给司机,还是分配给火车,显然,应该分配给火车,因为司机自身是不可能有那么大的力气将一个火车给停下来的,只有火车自己才能完成这一动作,火车需要调用内部的离合器和刹车片等多个器件协作才能完成刹车这个动作,司机刹车的过程只是给火车发了一个消息,通知火车要执行刹车动作而已。

2.2、抽象

抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽象。抽象包括行为抽象和状态抽象两个方面。例如,定义一个Person类,如下:

public class Person{ 
    String name;//名字
    int age;    //年龄
 }

人本来是很复杂的事物,有很多方面,但因为当前系统只需要了解人的姓名和年龄,所以上面定义的类中只包含姓名和年龄这两个属性,这就是一种抽像,使用抽象可以避免考虑一些与目标无关的细节。我对抽象的理解就是不要用显微镜去看一个事物的所有方面,这样涉及的内容就太多了,而是要善于划分问题的边界,当前系统需要什么,就只考虑什么。

2.3、继承

在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。

2.3.1、单一继承(继承某个类)

继承示意图

Circle、Square、Triangle继承自Shape,这几个类即使什么都不做,也自动拥有了父类draw()、move()等方法(尽管private成员被隐藏起来,并且不可访问)

2.3.2、多继承特性(实现多个接口)

实现接口示意图

出自Java编程思想:

接口不仅仅只是一种更纯粹形式的抽象类,它的目标比这要高。因为接口是根本没有任何具体实现的---也就是说,没有任何与接口相关的存储;因此,也就无法阻止多个接口的组合。这一点是很有价值的,因为你有时需要去表示“一个x是一个a和一个b以及一个c”。在C++中,组合多个类的接口的行为被称作多重继承。它可能会使你背负很沉重的包袱,因为每个类都有一个具体实现。在Java中,你可以执行相同的行为,但是只有一个类可以有具体实现。

在导出类中,不强制要求必须有一个是抽象的或“具体的”基类。如果要从一个非接口的类继承,那么只能从一个类去继承。其余的基元素都必须是接口。需要将所有的接口名都置于implements关键字之后,用逗号将它们一一隔开。可以继承任意多个接口,并可以向上转型为每个接口。因为每个接口都是一个独立类型。

2.4、多态

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:将子类类型的指针赋值给父类类型的指针。

Shape circle = new Circle();

多态的实现:方法的覆盖,是指子类重新定义父类的方法的做法

3、面向对象五大设计原则:SOLID

3.1、单一职责原则(Single Resposibility Principle)

"对一个类而言,应该仅有一个引起它变化的原因。"本原则是我们非常熟悉地"高内聚性原则"的引申,但是通过将"职责"极具创意地定义为"变化的原因",使得本原则极具操作性,尽显大师风范。同时,本原则还揭示了内聚性和耦合生,基本途径就是提高内聚性;如果一个类承担的职责过多,那么这些职责就会相互依赖,一个职责的变化可能会影响另一个职责的履行。其实OOD的实质,就是合理地进行类的职责分配。

3.2、开放封闭原则(Open Closed principle)

"软件实体应该是可以扩展的,但是不可修改。"本原则紧紧围绕变化展开,变化来临时,如果不必改动软件实体裁的源代码,就能扩充它的行为,那么这个软件实体设计就是满足开放封闭原则的。如果说我们预测到某种变化,或者某种变化发生了,我们应当创建抽象类来隔离以后发生的同类变化。在Java中,这种抽象是指抽象基类或接口;在C++中,这各抽象是指抽象基类或纯抽象基类。当然,没有对所有情况都贴切的模型,我们必须对软件实体应该面对的变化做出选择。

3.3、里氏替换原则(Liskov Substituion Principle)

"子类型必须能够替换掉它们的基类型。"本原则和开放封闭原则关系密切,正是子类型的可替换性,才使得使用基类型模块无需修改就可扩充。Liskov替换原则从基于契约的设计演化而来,契约通过为每个方法声明"先验条件"和"后验条件";定义子类时,必须遵守这些"先验条件"和"后验条件"。当前基于契的设计发展势头正劲,对实现"软件工厂"的"组装生产"梦想是一个有力的支持

3.4、接口隔离原则(Interface Segregation Principle)

"多个专用接口优于一个单一的通用接口。"本原则是单一职责原则用于接口设计的自然结果。一个接口应该保证,实现该接口的实例对象可以只呈现为单一的角色;这样,当某个客户程序的要求发生变化,而迫使接口发生改变时,影响到其他客户程序的可能生性小。

3.5、依赖倒置原则(Dependecy Inversion Principle)

抽象不应依赖于细节,细节应该依赖于抽象。"本原则几乎就是软件设计的正本清源之道。因为人解决问题的思考过程是先抽象后具体,从笼统到细节,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体。于是,"细节依赖于抽象"就意味着后来的依赖于先前的,这是自然而然的重用之道。而且,抽象的实体代表着笼而统之的认识,人们总是比较容易正确认识它们,而且本身也是不易变的,依赖于它们是安全的。依赖倒置原则适应了人类认识过程的规律,是面向对象设计的标志所在。

上一篇下一篇

猜你喜欢

热点阅读