凭什么给你长工资啊?参加答辩,别人说你好不行,要看看真本事么!nnd 一答辩小辫子就抓住了,主动权就没了。没办法我就准备了下面向对象分析和面向对象程序设计,分析哪部分牵扯到很多的系统,你们都 不熟悉 就算了。把多态贴出来,以后等我老的时候再看。可能上下文衔接不上,凑合看吧
目前的几个系统里面可以说是面向过程编程的成分更大,在面向对象程序设计里面的准则没有遵循。太多的耦合和冗余了。没有做到复用。
java的面向对象的方法学为设计提供了几种强大的技术:继承、组合、接口。
与继承相比接口更加灵活。接口方法继承的完美实现,利用接口并在一定的程度上模拟多继承。
组合是域优先的,如果共享数据,最好使用组合。如果想重用方法则使用继承。
继承是以方法优先的。
3.1继承
在综合版本的××系统中,所有的基础类都是继承于BaseObject基类过来的。BaseObject实现了序列化接口(serializable)和conleable两个标识性接口。这样易于修改或扩展那些被复用的实现。其他类容易进行新的实现,因为其大多数可继承而来。这也是继承的优点。
继承的缺点有哪些呢?
很多系统中都有人员这个类,假如定义了一个person类。系统的操作员根据不同的权限有不同的功能模块,假如分为一般操作员和系统管理员,那么这两个类是不是继承于person这个基类?这个类符合继承的定义(继承是一种通过扩展一个已有对象的实现,从而获得新功能的复用方法。)这是××初始的设计,但是发现如果这个人既有一般操作员的权限又有系统管理员的权限那么怎么处理?java不支持多重继承。所以开始的时候设计一般操作员和系统管理员继承于person类就是一个错误。
因为1、子类表达了“是一个…的特殊类型”,而非“是一个由…所扮演的角色”。
2、子类的一个实例永远不用转为另外一个对象。(权限的更改)。
继承的缺点之一破坏了封装性。由于“白盒”的复用,父类的内部实现细节对于子类通常是可见的。
继承最大的隐患是重载和覆写不要同时使用。
方法的重载是静态的,是编译时运行的。而覆写是动态的,发生在运行的时候。
public class Base{
void Iam(Base b){
System.out.println(“Base overload”);
}
void Iam(Child c){
System.out.println(“Child overload”);
}
public static void main(String args[]){
Base[] test = new Base[]{new Base(),new Child()};
int size = test.length;
for(int i = 0; i < size; i++){
test[i].Iam(test[i]);
}
}
}
public class Child extends Base{
viod Iam(Base b){
System.out.println(“Base override”);
}
}
在××初始阶段也有过类似的代码,即:BaseObject实现了equals(Object o)方法。而其余的类是继承于BaseObject方法过去的。如果该类的两个对象进行比较引用,那么该类也需要实现一个equals(Object o)方法。如果该类equals方法的参数改变了那么在ArrayList里面调用的是父类的equals(Object o)方法。
public class Departtax extends BaseObject{
public boolean equals(Departtax dep){
………..
}
}
继承的实现包括三种形式:
1. 直接继承父类的方法来实现复用
2. 调用父类的方法来实现自己的方法的复用
3.通过抽象方法来实现逻辑关系的复用。
3.2组合
上面的person类以及一般操作员类以及系统管理员类,如果使用继承是不符合需求的。
采用组合来弥补。
组合包括组成和聚集。组成通常是异构,而聚集多数是同构。通过内部类来实现的。
信用等级系统中大部分采用了组成。
容器类只能通过被包含对象的接口来对其访问。
每一个类都专注一项任务,封装性好,实现的相互依赖性小。黑盒的复用 被包含的对象的内部实现细节对外是不可用的。当然导致了系统的对象过多。
通过组合和继承的理解可以看出优先使用组合,而非类的继承。
3.3接口
如果再回头看BaseObject的时候,里面封装了clone和equals两个方法。如果需要比较两个对象的大小而非引用那么需要实现compareable接口。其实就equals方法来讲,大多数的类就没有用到,如果再实现compareable接口那么继承于BaseObject的有些类,更颇有微词了。
在jdk1.0以后发现对象的在文件或者网络的存储有着重要作用,则需要实现序列化接口。也相应的增加了compareable接口。
体现出了用接口来代替抽象类。违背继承的第三条实现原则。
接口是一个对象在对其它的对象进行调用时所知道的方法集合。
一个对象可以有多个接口(实际上,接口是对象所有方法的一个子集)。类型是对象的一个特定的接口。不同的对象可以具有相同的类型,而且一个对象可以具有多个不同的类型。一个对象仅能通过其接口才会被其它对象所了解。
某种意义上,接口是以一种非常局限的方式,将“是一种…”表达为“一种支持该接口的…”。接口是实现插件化(pluggability)的关键
实现继承(类继承):一个对象的实现是根据另一个对象的实现来定义的。
接口继承(子类型化):描述了一个对象可在什么时候被用来替代另一个对象。
接口的好处:
Client不必知道其使用对象的具体所属类。
一个对象可以很容易地被(实现了相同接口的)的另一个对象所替换。
对象间的连接不必硬绑定(hardwire)到一个具体类的对象上,因此增加了灵活性。松散藕合(loosens coupling)。增加了重用的可能性。提高了(对象)组合的机率,因为被包含对象可以是任何实现了一个指定接口的类。
针对接口的编程,并非接口的实现
微观来说:java编写的程序运行的环境是一个托管的平台java 虚拟机。Java程序执行的时候并不是启动一个可执行的文件而是动态的在指定路径下加载程序所需要的类。可以用jvm带的类加载器去加载所需要的应用类以及应用类所用到的api,我们可以用class.forName();去加载classpath中的类。从这个角度出发java的动态特性可以看出来。
大部分系统都采用jdbc驱动去连接数据库。Jdbc api来说。加载jdbc驱动,class.forName().把驱动程序放在classpath中,这是主动的去请求服务资源。
如果改了数据库那么就要改程序或者也可以把驱动写入属性文件里面不管怎么没有做到服务和被服务之间一无所知。如果配置datasource类来实现的话 采用jndi来获得抽象的服务资源工厂。在j2ee1.4规范中大部分采用了jndi查找+抽象工厂来获得服务资源。不用再new一个服务资源。好像无法回避组件对外界的强依赖性。
现在的依赖注入模式让请求服务组件由主动的请求服务资源改为被动的。请求服务组件没有任何去主动去获得服务组件的代码,而唯一拥有的就是服务组件必须实现的接口的引用。
目前的hibernate、ejb3.0 spring都采用了这种方式。