Content:
- 每个对象都有一个接口
- 每个对象都提供服务
- 被隐藏的具体实现
- 复用具体实现
每一个对象都有一个接口
- 所有的对象都是唯一的,就像再相似的双胞胎也存在差异,彼此也是唯一的,因为个体差异存在
- 而有若干对象但却有着很多共性,就是草原上一群奔腾的骏马,虽然各自唯一但却有相同的行为和特性,如此我们把具有相同特性和行为的一个群体或者集合抽象为一个类,,这就是类的概念。
- 经典的银行出纳员问题:
- 在银行出纳员问题中,有出纳,账号,客户,交易,和货币单位等许多的"对象"。
- 然后在这些对象中:每个出纳都有自己的名字,工号,年薪,性别,住址,级别,待遇,能执行入账,出账操作;每一个账号有余额,种类,消费。同时,每个账号会有不同的余额种类和消费,每个出纳也有自己的名字,工号和性别。
- 上面问题中的出纳,账号,客户,交易和货币都是一个类,而出纳001,出纳002,客户张三,客户李四都是一个个鲜活的对象,它们是抽象概念的实例。
- 类是对象的集合,对象是类的实例,对象之间存在个体差异。在程序执行期间具有不同的状态而其他方面都相似的对象会被分组到对象的类中。
-
面向对象的开发,实质上是在创造新的数据类型,所以一个类实际上是一个数据类型。开发中我们直接或间接的使用了别人的类,然后在独特的业务驱动下去创造自己的类。
比如:API给出的int,float,list,map,是java内置的类,而Jvm也欣然接受新的类,并和内置类有相同的管理机制。比如我们可以创造:User.class,Test.class,Car.class。 - 面向对象站在更高的解决问题的角度,不仅仅是解决一个问题,而是提供了一套解决问题的方案。一旦一个类被创建,那么我们可以在以后的任何地方去创建该类的对象去解决相应的问题。正是如此,java中才会有很多高质量的第三方开源库。比如:我需要解决网络通信问题,那么为可以从架构上开发一套网络通信框架,然后再其他需要网络通信的地方直接使用。这也是面向对象语言的强大之处。
- 每个对象都能满足某些请求,提供某些服务。比如,我在建设房子的时候,需要若干个灯泡,这些灯泡就是一个个对象,他们能为我们提供照明的服务。所以我可以抽象出:
<code>
interface Light{
public void on();
public void off();
public boolean isOn();
...
}
</code>
这是Light的一个抽象接口,接下来可以创建MyLight具有每个方法的实现。在层次结构上,这些是底层的准备工作,底层准备好之后,那么就直接使用:我装修房子需要灯,车库需要灯,楼梯也需要灯,那此时:
<code>
MyLight lt01 = new MyLight();
lt01 .on();//
MyLight lt02 = new MyLight();
lt02 .on();//
MyLight lt03 = new MyLight();
lt03 .on();//
</code>
一号灯解决房间照明,二号灯解决车库照明,三号灯解决楼梯照明....很多相同问题得以解决。而我们解决问题的套路是,得到一个灯的对象,然后使用它提供的服务,即调用对象的接口。
每个对象都提供服务
- 当正在试图开发或者理解一个程序设计时,最好的方法之一就是将对象想象为服务提供者。
- 程序本身将向用户提供服务,而开发程序时也是调用其它对象服务来满足自己的需求。程序开发者的目标就是:去创建(或者最好是在现有代码库中去寻找,比较不同的第三方开源库)能够提供理想的服务来解决问题的一序列对象。
- 将对象看作是服务提供者还有一个附带的好处:它有助于提高程序的内聚性。每个对象完成各自分内的事情,提供各自的服务,各施其职,然后程序则是若干对象的集合,若此协调工作解决需求问题。
- 将对象作为服务提供者是一件伟大的简化工具,这不仅在设计过程中非常有用,而且当其他人试图理解你的代码或重用某个对象时,依据服务来理解将会事半功倍。就像一个Project中总会有:Db模块,net模块,Utils模块...这也是对服务的一种划分,思维清晰。
被隐藏的具体实现
将呈现开发人员按照角色分为类创建者(那些新的数据类型的创建者)和客户端程序猿(使用别人类和库的类消费者,比如调用别人的API等),很显然,类创建者是值得敬畏的程序猿,因为他们扮演着软件世界里上帝的角色。
客户端程序猿的目标是搜集各种用来实现快速应用开发的类。类创建者的目标是构建类。类的创建者一般只是希望将类的接口暴露给客户端程序员,而不希望客户端程序员能看见和修改自己接口的内部实现。这时就需要将自己的内部实现隐藏起来,出现了访问控制机制。
访问机制存在的第一个原因是:让客户端程序员无法触及它们不应该触及的部分,比如类的内部数据和对象以及业务逻辑。客户端程序员只能享受服务而不能制定服务规则。
访问机制存在的第二个原因是:允许类库的设计者可以改变类内部的工作方式而不影响客户端程序员。比如:一开始的时候暴露了某个搜索排序的接口,但是后来你发现一种速度更快效果更优的算法,此时就可以在客户端程序员毫不知情的情况下,修改接口的实现。接口和实现分离,实现了高内聚,低耦合。
-
Java提供了三个关键字用于划分内部边界:public private 、protected。
- public 表示被其修饰的对象,方法和数据,可以被任何人使用。
- private 则是与public完全相反,只能被类创建者和类内部的方法所使用,客户端程序员或者第三方类是完全看不见的,它就像在类创建着和使用类的人直接建立了一堵高墙。
- protected关键字和private作用相当,差别仅在于类的继承着可以访问和使用被Protected修饰的对象方法或数据。
Java还提供了一种默认的访问权限,即包访问权限,当前对象方法未被 修饰时,即默认包访问权限--同一包下的其他类可以访问。
注意:接口中声明的成员变量默认都是 public static final 的,必须显示的初始化。因而在常量声明时可以省略这些修饰符。接口中的方法默认都是public abstract的。
复用具体实现
- 一旦一个类被创建并被测试完,那么它就应该代表一个有用的代码单元。
- 代码复用是面向对象语言所提供最了不起的优点之一。
- 最简单的复用是组合,Has-a的关系,比如汽车拥有引擎,电脑拥有主机。组合带来了极大的灵活性,新类的成员对象通常被修饰为private的,其实也是一种封装。
- 另一种方式是继承,实际优先考虑组合,因为它更加灵活简单。